diff --git a/src/components/Interactive.js b/src/components/Interactive.js
new file mode 100644
index 0000000000000000000000000000000000000000..9ba219db463f3dc15c3ff14fea76442992a3a822
--- /dev/null
+++ b/src/components/Interactive.js
@@ -0,0 +1,6 @@
+import React from "react";
+import { Alert } from "react-bootstrap";
+
+export default function Interactive() {
+  return <Alert variant="info">This service is under development!</Alert>;
+}
diff --git a/src/components/Rucio.js b/src/components/Rucio.js
new file mode 100644
index 0000000000000000000000000000000000000000..22e27122d5931b78a1cc6d9b88f52e063b89ed0b
--- /dev/null
+++ b/src/components/Rucio.js
@@ -0,0 +1,13 @@
+import React from "react";
+import { Alert } from "react-bootstrap";
+
+export default function Rucio() {
+  return (
+    <Alert variant="warning">
+      <p>You will leave ESAP GUI and be redirected to</p>
+      <a target="_blank" href="https://escape-dios-dl.cern.ch/ui/">
+        Rucio Web UI
+      </a>
+    </Alert>
+  );
+}
diff --git a/src/components/archives/ArchiveDetails.js b/src/components/archives/ArchiveDetails.js
index fa5e2759f7f3762805d243068fb24a3203407bfa..9ac3f575b9c86d70dadaf4a61da50d5b033ffa68 100644
--- a/src/components/archives/ArchiveDetails.js
+++ b/src/components/archives/ArchiveDetails.js
@@ -1,23 +1,23 @@
 import React, { useContext } from "react";
 import { useParams } from "react-router-dom";
 import { GlobalContext } from "../../contexts/GlobalContext";
-import { Container, Row, Col, Card, Table, Alert, Image } from "react-bootstrap";
+import {
+  Container,
+  Row,
+  Col,
+  Card,
+  Table,
+  Alert,
+  Image,
+} from "react-bootstrap";
 import DataProductCategories from "./DataProductCategories";
 
 export default function ArchiveDetails(props) {
   const { uri } = useParams();
   console.log(uri);
-  const { archives, defaultConfigName, setConfigName } = useContext(GlobalContext);
+  const { archives } = useContext(GlobalContext);
   if (!archives) return null;
 
-  /* This is a nasty hack. There must be a better way! */
-  if (uri.search("zooniverse") >= 0){
-    setConfigName("zooniverse");
-  }
-  else{
-    setConfigName(defaultConfigName);
-  }
-
   const archive = archives.find((archive) => archive.uri === uri);
   if (!archive) return <Alert variant="danger">No Archive found!</Alert>;
   console.log(archive);
@@ -46,15 +46,19 @@ export default function ArchiveDetails(props) {
                   </tbody>
                 </Table>
                 <Card>
-                <Image
-                  className="mx-auto d-block"
-                  src={archive.thumbnail}
-                  alt=""
-                  rounded
-                  fluid
-                />
-                <Card.Title className="text-center h4 pt-3">{archive.short_description}</Card.Title>
-                <Card.Text className="text-justify m-3">{archive.long_description}</Card.Text>
+                  <Image
+                    className="mx-auto d-block"
+                    src={archive.thumbnail}
+                    alt=""
+                    rounded
+                    fluid
+                  />
+                  <Card.Title className="text-center h4 pt-3">
+                    {archive.short_description}
+                  </Card.Title>
+                  <Card.Text className="text-justify m-3">
+                    {archive.long_description}
+                  </Card.Text>
                 </Card>
               </Card.Body>
             </Card>
diff --git a/src/components/archives/Archives.js b/src/components/archives/Archives.js
index a53113a9c2846f1adcf2410c40ca3bf47dda8fa0..f2148c055ddd5cfab06cfe00ec15b63f65f5be7c 100644
--- a/src/components/archives/Archives.js
+++ b/src/components/archives/Archives.js
@@ -1,23 +1,19 @@
 import React, { useContext } from "react";
-import { CardColumns} from "react-bootstrap";
+import { CardColumns } from "react-bootstrap";
 import ArchiveCard from "./ArchiveCard";
 import { GlobalContext } from "../../contexts/GlobalContext";
 
 export function Archives() {
-  const { archives, defaultConfigName, setConfigName} = useContext(GlobalContext);
+  const { archives } = useContext(GlobalContext);
   if (!archives) return null;
 
-  setConfigName(defaultConfigName);
-
   console.log("archives: ", { archives });
   return (
     <CardColumns className="row-2">
-            {archives.map((archive) => {
-              let key = "archive-" + archive.id;
-              return (
-                  <ArchiveCard key={key} archive={archive} />
-              );
-            })}
+      {archives.map((archive) => {
+        let key = "archive-" + archive.id;
+        return <ArchiveCard key={key} archive={archive} />;
+      })}
     </CardColumns>
   );
 }
diff --git a/src/components/archives/DataProductCategories.js b/src/components/archives/DataProductCategories.js
index 3846156353758d54215d96e93c8d37161a02f970..d7f4d71f5be66d7bcf2a123e35784e95ad746f56 100644
--- a/src/components/archives/DataProductCategories.js
+++ b/src/components/archives/DataProductCategories.js
@@ -1,12 +1,6 @@
 import React, { useState, useContext, useEffect } from "react";
 import { NavLink } from "react-router-dom";
-import {
-  ListGroup,
-  Card,
-  Button,
-  Row,
-  Col,
-} from "react-bootstrap";
+import { ListGroup, Card, Button, Row, Col } from "react-bootstrap";
 import { GlobalContext } from "../../contexts/GlobalContext";
 import axios from "axios";
 
@@ -37,13 +31,15 @@ export default function DataProductCategories({ archive }) {
           {categories
             .filter((category) => archive.datasets.includes(category.uri))
             .map((category) => {
-              console.log(category);
+              console.log("category:", category);
               let button;
               let extra_info;
               let documentation;
               if (category.service_connector) {
+                let query_url = `${category.archive_uri_derived}/query`;
+                console.log("query_url:", query_url);
                 button = (
-                  <Button as={NavLink} variant="outline-info" to="/query">
+                  <Button as={NavLink} variant="outline-info" to={query_url}>
                     Browse Catalog & Run Queries
                   </Button>
                 );
diff --git a/src/components/query/QueryCatalogs.js b/src/components/query/QueryCatalogs.js
index c5709c393b687fb1cf5c41bd34fbbb0466296052..a7554b7e7601288333cc71f8bf1c7eb2f42874b2 100644
--- a/src/components/query/QueryCatalogs.js
+++ b/src/components/query/QueryCatalogs.js
@@ -1,4 +1,5 @@
 import React, { useContext, useEffect } from "react";
+import { useParams } from "react-router-dom";
 import axios from "axios";
 import { Container } from "react-bootstrap";
 import Form from "react-jsonschema-form";
@@ -14,16 +15,38 @@ export default function QueryCatalogs() {
   //  "status": "fetching|fechted",
   //  "results": null}
   const { queryMap, formData, setFormData } = useContext(QueryContext);
-  const { config, api_host } = useContext(GlobalContext);
+  const { config, api_host, setConfigName } = useContext(GlobalContext);
+  const { uri } = useParams();
+  console.log(uri);
 
-  console.log(config.query_schema);
+  // set ConfigName for archive
   useEffect(() => {
+    switch (uri) {
+      case "adex":
+        setConfigName("adex");
+        break;
+      case "apertif":
+        setConfigName("apertif");
+        break;
+      case "zooniverse":
+        setConfigName("zooniverse");
+        break;
+      case "astron_vo":
+        setConfigName("astron_vo");
+        break;
+      case "lofar":
+        setConfigName("lofar");
+        break;
+      default:
+        setConfigName("esap_ivoa");
+    }
+  }, [uri]);
+
+  useEffect(() => {
+    console.log(config.query_schema);
     if (!formData) return;
-    let catalogs = config.query_schema.properties.catalog.enum.filter(
-      (name) => name !== "all"
-    );
     let gui = config.query_schema.name;
-    const queries = parseQueryForm(gui, formData, catalogs);
+    const queries = parseQueryForm(gui, formData);
 
     // Ideally query for each catalog is sent to ESAP API Gateway, and query results is returned
     // This is under development in the backend at the moment
@@ -78,7 +101,7 @@ export default function QueryCatalogs() {
 
   console.log("queryMap", Array.from(queryMap.values()));
 
-  const uiSchemaProp = config.ui_schema ? { uiSchema : config.ui_schema } : {};
+  const uiSchemaProp = config.ui_schema ? { uiSchema: config.ui_schema } : {};
   return (
     <Container fluid>
       <Form
diff --git a/src/contexts/GlobalContext.js b/src/contexts/GlobalContext.js
index 0b828c476758051005a753ec2cca6c2594127260..04ccbf45edf45304985dff5f28588436dfc9f275 100644
--- a/src/contexts/GlobalContext.js
+++ b/src/contexts/GlobalContext.js
@@ -8,17 +8,16 @@ export function GlobalContextProvider({ children }) {
   console.log("ASTRON ESAP version 14 aug 2020");
   const api_host =
     process.env.NODE_ENV === "development"
-      ? "http://sdc.astron.nl:15671/esap-api/"
+      ? "http://localhost:8000/esap-api/"
       : "/esap-api/";
 
   const [config, setConfig] = useState();
-  const [configName, setConfigName] = useState("esap_config");
-  const [defaultConfigName, setDefaultConfigName] = useState("esap_config");
+  const [configName, setConfigName] = useState("esap_ivoa");
 
   useEffect(() => {
-    let configNameString=""
-    if (configName){
-      configNameString=`?name=${configName}`
+    let configNameString = "";
+    if (configName) {
+      configNameString = `?name=${configName}`;
     }
     axios
       .get(api_host + "query/configuration" + configNameString)
@@ -63,7 +62,7 @@ export function GlobalContextProvider({ children }) {
         archives,
         handleLogin,
         handleLogout,
-        setConfigName
+        setConfigName,
       }}
     >
       {children}
diff --git a/src/routes/Routes.js b/src/routes/Routes.js
index e28032c493e06f280a9c7d9067f4091b3785911c..319cd3b8deffef20ab98d3eb8105f8755cf38b12 100644
--- a/src/routes/Routes.js
+++ b/src/routes/Routes.js
@@ -7,6 +7,8 @@ import QueryCatalogs from "../components/query/QueryCatalogs";
 import { BrowserRouter as Router } from "react-router-dom";
 import NavBar from "../components/NavBar";
 import { QueryContextProvider } from "../contexts/QueryContext";
+import Rucio from "../components/Rucio";
+import Interactive from "../components/Interactive";
 
 export default function Routes() {
   const { config, handleLogin, handleLogout } = useContext(GlobalContext);
@@ -22,14 +24,25 @@ export default function Routes() {
         <Route exact path="/archives">
           <Archives />
         </Route>
-        <Route path="/query">
+        <Route exact path="/query">
           <QueryContextProvider>
             <QueryCatalogs />
           </QueryContextProvider>
         </Route>
+        <Route exact path="/rucio">
+          <Rucio />
+        </Route>
+        <Route exact path="/interactive">
+          <Interactive />
+        </Route>
         <Route exact path="/login" component={handleLogin} />
         <Route exact path="/logout" component={handleLogout} />
-        <Route path="/archives/:uri" component={ArchiveDetails} />
+        <Route exact path="/archives/:uri" component={ArchiveDetails} />
+        <Route exact path="/archives/:uri/query">
+          <QueryContextProvider>
+            <QueryCatalogs />
+          </QueryContextProvider>
+        </Route>
       </Switch>
     </Router>
   );
diff --git a/src/utils/form/parseADEXForm.js b/src/utils/form/parseADEXForm.js
index c4f17bd8a42aa373f5cd0652ba8e2353c099f662..d2f9460dc23fc6ea74995f1f051a881a8590194f 100644
--- a/src/utils/form/parseADEXForm.js
+++ b/src/utils/form/parseADEXForm.js
@@ -1,4 +1,5 @@
-export default function ParseADEXForm(formData, catalogs) {
+export default function ParseADEXForm(formData) {
+  let catalogs = ["apertif", "astron_vo"];
   let queries = [];
   // queries is an array of dictionaries, where each dictionary consists of
   // {"catalog": "catalogname",
diff --git a/src/utils/form/parseASTRONVOForm.js b/src/utils/form/parseASTRONVOForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c4a4694f0f8f66d6dcc14186d89d456185fe2d8
--- /dev/null
+++ b/src/utils/form/parseASTRONVOForm.js
@@ -0,0 +1,44 @@
+export default function ParseASTRONVOForm(formData) {
+  let catalogs = "astron_vo";
+  let queries = [];
+  // queries is an array of dictionaries, where each dictionary consists of
+  // {"catalog": "catalogname",
+  //  "esapquery": "querystring"}
+  let query = "";
+  let formInput = Object.entries(formData);
+  console.log(formInput);
+
+  for (let [key, value] of formInput) {
+    console.log(`${key}: ${value}`);
+    if (value && value !== "all" && key !== "catalog") {
+      query += `${`${query}` ? "&" : ""}` + key + "=" + value;
+    }
+  }
+  console.log("Query:", query);
+  // If catalog is set to "all", query for each catalog needs to be generated {"catalog": "catalogname",
+  //  "catalogquery": "querystring",
+  //  "status": "null|fetching|fetched",
+  //  "results": null}
+  let catalog = formInput.find(([key]) => key === "catalog")[1];
+  if (catalog === "all") {
+    console.log("Catalogs:", catalogs);
+    catalogs.map((catalog) => {
+      let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+
+      queries.push({
+        catalog: catalog,
+        esapquery: esapquery,
+      });
+      return null;
+    });
+  } else {
+    let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+
+    queries.push({
+      catalog: catalog,
+      esapquery: esapquery,
+    });
+  }
+  console.log("Queries:", queries);
+  return queries;
+}
diff --git a/src/utils/form/parseApertifForm.js b/src/utils/form/parseApertifForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..1540ce1a41be4dba8b0b8dd8001f68257949cd1b
--- /dev/null
+++ b/src/utils/form/parseApertifForm.js
@@ -0,0 +1,44 @@
+export default function ParseApertifForm(formData) {
+  let catalogs = "apertif";
+  let queries = [];
+  // queries is an array of dictionaries, where each dictionary consists of
+  // {"catalog": "catalogname",
+  //  "esapquery": "querystring"}
+  let query = "";
+  let formInput = Object.entries(formData);
+  console.log("formInput:", formInput);
+
+  for (let [key, value] of formInput) {
+    console.log(`${key}: ${value}`);
+    if (value && value !== "all" && key !== "catalog") {
+      query += `${`${query}` ? "&" : ""}` + key + "=" + value;
+    }
+  }
+  console.log("Query:", query);
+  // If catalog is set to "all", query for each catalog needs to be generated {"catalog": "catalogname",
+  //  "catalogquery": "querystring",
+  //  "status": "null|fetching|fetched",
+  //  "results": null}
+  let catalog = formInput.find(([key]) => key === "catalog")[1];
+  if (catalog === "all") {
+    console.log("Catalogs:", catalogs);
+    catalogs.map((catalog) => {
+      let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+
+      queries.push({
+        catalog: catalog,
+        esapquery: esapquery,
+      });
+      return null;
+    });
+  } else {
+    let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+
+    queries.push({
+      catalog: catalog,
+      esapquery: esapquery,
+    });
+  }
+  console.log("Queries:", queries);
+  return queries;
+}
diff --git a/src/utils/form/parseIVOAForm.js b/src/utils/form/parseIVOAForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..3df6e0ee67420e98962b0186bde9a857de1b9e51
--- /dev/null
+++ b/src/utils/form/parseIVOAForm.js
@@ -0,0 +1,44 @@
+export default function ParseIVOAForm(formData) {
+  let catalogs = "ivoa";
+  let queries = [];
+  // queries is an array of dictionaries, where each dictionary consists of
+  // {"catalog": "catalogname",
+  //  "esapquery": "querystring"}
+  let query = "";
+  let formInput = Object.entries(formData);
+  console.log(formInput);
+
+  for (let [key, value] of formInput) {
+    console.log(`${key}: ${value}`);
+    if (value && value !== "all" && key !== "catalog") {
+      query += `${`${query}` ? "&" : ""}` + key + "=" + value;
+    }
+  }
+  console.log("Query:", query);
+  // If catalog is set to "all", query for each catalog needs to be generated {"catalog": "catalogname",
+  //  "catalogquery": "querystring",
+  //  "status": "null|fetching|fetched",
+  //  "results": null}
+  let catalog = formInput.find(([key]) => key === "catalog")[1];
+  if (catalog === "all") {
+    console.log("Catalogs:", catalogs);
+    catalogs.map((catalog) => {
+      let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+
+      queries.push({
+        catalog: catalog,
+        esapquery: esapquery,
+      });
+      return null;
+    });
+  } else {
+    let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+
+    queries.push({
+      catalog: catalog,
+      esapquery: esapquery,
+    });
+  }
+  console.log("Queries:", queries);
+  return queries;
+}
diff --git a/src/utils/form/parseLOFARForm.js b/src/utils/form/parseLOFARForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..7446420a0e15f91534608c5a5448fb5580669309
--- /dev/null
+++ b/src/utils/form/parseLOFARForm.js
@@ -0,0 +1,44 @@
+export default function ParseLOFARForm(formData) {
+  let catalogs = "lofar";
+  let queries = [];
+  // queries is an array of dictionaries, where each dictionary consists of
+  // {"catalog": "catalogname",
+  //  "esapquery": "querystring"}
+  let query = "";
+  let formInput = Object.entries(formData);
+  console.log(formInput);
+
+  for (let [key, value] of formInput) {
+    console.log(`${key}: ${value}`);
+    if (value && value !== "all" && key !== "catalog") {
+      query += `${`${query}` ? "&" : ""}` + key + "=" + value;
+    }
+  }
+  console.log("Query:", query);
+  // If catalog is set to "all", query for each catalog needs to be generated {"catalog": "catalogname",
+  //  "catalogquery": "querystring",
+  //  "status": "null|fetching|fetched",
+  //  "results": null}
+  let catalog = formInput.find(([key]) => key === "catalog")[1];
+  if (catalog === "all") {
+    console.log("Catalogs:", catalogs);
+    catalogs.map((catalog) => {
+      let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+
+      queries.push({
+        catalog: catalog,
+        esapquery: esapquery,
+      });
+      return null;
+    });
+  } else {
+    let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+
+    queries.push({
+      catalog: catalog,
+      esapquery: esapquery,
+    });
+  }
+  console.log("Queries:", queries);
+  return queries;
+}
diff --git a/src/utils/form/parseQueryForm.js b/src/utils/form/parseQueryForm.js
index 21f9315428e7af25435b27b52d64b99f2cde7adb..3b6aa52313083712aab068003b2df983a77756a3 100644
--- a/src/utils/form/parseQueryForm.js
+++ b/src/utils/form/parseQueryForm.js
@@ -1,12 +1,24 @@
 import parseADEXForm from "./parseADEXForm";
 import parseZooniverseForm from "./parseZooniverseForm";
+import parseLOFARForm from "./parseLOFARForm";
+import parseIVOAForm from "./parseIVOAForm";
+import parseApertifForm from "./parseApertifForm";
+import parseASTRONVOForm from "./parseASTRONVOForm";
 
-export default function parseQueryForm(gui, formData, catalogs) {
+export default function parseQueryForm(gui, formData) {
   switch (gui) {
     case "adex":
-      return parseADEXForm(formData, catalogs);
+      return parseADEXForm(formData);
     case "zooniverse":
-      return parseZooniverseForm(formData, catalogs);
+      return parseZooniverseForm(formData);
+    case "lofar":
+      return parseLOFARForm(formData);
+    case "apertif":
+      return parseApertifForm(formData);
+    case "astron_vo":
+      return parseASTRONVOForm(formData);
+    case "ivoa":
+      return parseIVOAForm(formData);
     default:
       return null;
   }
diff --git a/src/utils/form/parseZooniverseForm.js b/src/utils/form/parseZooniverseForm.js
index c4fa8ceabc4b7fbbaab45686ea5328dad23fa783..8d12202f0a3a777b692f079fbbb7972d42a1afbe 100644
--- a/src/utils/form/parseZooniverseForm.js
+++ b/src/utils/form/parseZooniverseForm.js
@@ -1,4 +1,5 @@
-export default function parseZooniverseForm(formData, catalogs) {
+export default function parseZooniverseForm(formData) {
+  let catalogs = "zooniverse";
   let queries = [];
   // queries is an array of dictionaries, where each dictionary consists of
   // {"catalog": "catalogname",
@@ -23,7 +24,11 @@ export default function parseZooniverseForm(formData, catalogs) {
   if (catalog === "all") {
     console.log(`Catalogs: ${catalogs}`);
     catalogs.map((catalog) => {
-      let esapquery = [query, "archive_uri=zooniverse", `catalog=${catalog}`].join("&");
+      let esapquery = [
+        query,
+        "archive_uri=zooniverse",
+        `catalog=${catalog}`,
+      ].join("&");
 
       queries.push({
         catalog: catalog,
@@ -32,7 +37,11 @@ export default function parseZooniverseForm(formData, catalogs) {
       return null;
     });
   } else {
-    let esapquery = [query, "archive_uri=zooniverse", `catalog=${catalog}`].join("&");
+    let esapquery = [
+      query,
+      "archive_uri=zooniverse",
+      `catalog=${catalog}`,
+    ].join("&");
 
     queries.push({
       catalog: catalog,