diff --git a/package.json b/package.json
index 55a7a10ed0ed1a9cc5c1053d0e55562f26a02f03..192ed1cb679635b6e257667aa7d6d2bc4d3c37d9 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,8 @@
     "react-jsonschema-form-layout-grid": "^2.1.0",
     "react-router-dom": "^5.1.2",
     "react-scripts": "^3.4.1",
-    "styled-components": "^4.4.1"
+    "styled-components": "^4.4.1",
+    "deep-equal": "^2.0.4"
   },
   "scripts": {
     "start": "react-scripts start",
diff --git a/src/App.css b/src/App.css
index 03377a920cda0f5024f535531200e82d0d749ebf..eaffbecc078dbbab291e0e31af08e3fed901e571 100644
--- a/src/App.css
+++ b/src/App.css
@@ -20,74 +20,3 @@
 .App-link {
   color: #1315c4;
 }
-
-.Observations-header {
-  background-color: #282c34;
-  min-height: 100vh;
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  justify-content: inherit;
-  font-size: calc(10px + 2vmin);
-  color: white;
-}
-
-.card-img-top {
-  width: 30vh;
-  height: 15vw;
-  object-fit: cover;
-  background-color: darkgrey;
-}
-
-.card-datasource {
-  display: flex;
-  object-fit: cover;
-  background-color: #d4d4d4;
-}
-
-.card-description {
-  display: flex;
-
-  //background-color: #BBDEFB;
-  font-family: Raleway;
-  //font-size: 14pt;
-}
-
-.card-telescope {
-  display: flex;
-  width: 40vh;
-  height: 35vw;
-}
-
-.card-query {
-  display: inline;
-  align-items: flex-start;
-  justify-content: inherit;
-  background-color: lightgrey;
-}
-
-.key {
-  font-weight: bold;
-}
-
-.value {
-  font-style: italic;
-}
-
-@media (min-width:400px) {
-  .card-columns {
-    column-count: 1;
-  }
-}
-
-@media (min-width:800px) {
-  .card-columns {
-    column-count: 2;
-  }
-}
-
-@media (min-width:1200px) {
-  .card-columns {
-    column-count: 3;
-  }
-}
diff --git a/src/App.js b/src/App.js
index 147e3a98a9d20e76780052f4694a573e85a37813..c462317b967f19164906133fc16492611255fa21 100644
--- a/src/App.js
+++ b/src/App.js
@@ -2,6 +2,7 @@ import React from "react";
 import "./App.css";
 import Routes from "./routes/Routes";
 import { GlobalContextProvider } from "./contexts/GlobalContext";
+import { QueryContextProvider } from "./contexts/QueryContext";
 
 // This is the App, only application global stuff goes here, like the global state provider.
 
@@ -9,7 +10,9 @@ export default function App() {
   return (
     <div>
       <GlobalContextProvider>
-        <Routes />
+        <QueryContextProvider>
+          <Routes />
+        </QueryContextProvider>
       </GlobalContextProvider>
     </div>
   );
diff --git a/src/components/Interactive.js b/src/components/Interactive.js
index b3508f3beaf43e391098e289588ba751960d6a54..e219659de3e859639ca23cd1d4825e69099fceb4 100644
--- a/src/components/Interactive.js
+++ b/src/components/Interactive.js
@@ -3,6 +3,13 @@ import { Alert } from "react-bootstrap";
 
 export default function Interactive() {
   return (
+    // <div class="embed-responsive embed-responsive-16by9">
+    //   <iframe
+    //     class="embed-responsive-item"
+    //     src="http://130.246.212.44/escape/"
+    //     allowfullscreen
+    //   ></iframe>
+    // </div>
     <Alert variant="warning">
       <p>You will leave ESAP GUI and be redirected to</p>
       <a
diff --git a/src/components/NavBar.js b/src/components/NavBar.js
index 5a32597e5769f6307a02c787966fb31223319563..10b442c39a2dc383051ac606a01c60382e16cb99 100644
--- a/src/components/NavBar.js
+++ b/src/components/NavBar.js
@@ -3,10 +3,10 @@ import { Navbar, Nav } from "react-bootstrap";
 import { NavLink } from "react-router-dom";
 import AuthControl from "./auth/authControl";
 
-import { GlobalContext } from "../contexts/GlobalContext";
+import { QueryContext } from "../contexts/QueryContext";
 
 export default function NavBar() {
-  const { config } = useContext(GlobalContext);
+  const { config } = useContext(QueryContext);
   if (!config) return null;
   // construct the navigation bar based on the configuration
   const navlist = config.navbar;
diff --git a/src/components/Rucio.js b/src/components/Rucio.js
index 6dd2613edf49f20b5644027270190debe7f9ff91..9e28f718d3b9146559fb66ce4411a5b453f0c6f2 100644
--- a/src/components/Rucio.js
+++ b/src/components/Rucio.js
@@ -1,17 +1,14 @@
 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"
-        rel="noopener noreferrer"
-        href="https://escape-dios-dl.cern.ch/ui/"
-      >
-        Rucio Web UI
-      </a>
-    </Alert>
+    <div className="embed-responsive embed-responsive-16by9">
+      <iframe
+        title="rucio"
+        className="embed-responsive-item"
+        src="https://escape-rucio.cern.ch"
+        allowFullScreen
+      ></iframe>
+    </div>
   );
 }
diff --git a/src/components/archives/ArchiveCard.js b/src/components/archives/ArchiveCard.js
index a4dcad088c8fb0aab1c1c8058499e088fc440d92..76ac2ea4322496771790fcfbb1d40ef467f57393 100644
--- a/src/components/archives/ArchiveCard.js
+++ b/src/components/archives/ArchiveCard.js
@@ -1,16 +1,14 @@
 import React from "react";
-import { Card, Container, Row, Button, Image } from "react-bootstrap";
+import { Card, Button, Image } from "react-bootstrap";
 import { NavLink } from "react-router-dom";
 
 // display a single archive on a card
 export default function ArchiveCard({ archive }) {
   return (
-    <Card className="card-description">
+    <Card>
       <Card.Body>
         <Card.Title className="h2">{archive.name}</Card.Title>
-        <Container fluid>
-          <Row>
-            <Card className="card-description">
+          <Card className="card-description">
               <Card.Body>
                 <Image
                   className="mx-auto d-block"
@@ -21,19 +19,24 @@ export default function ArchiveCard({ archive }) {
                 <Card.Title className="h3 pt-3">{archive.short_description}</Card.Title>
                 <Card.Text className="text-justify">{archive.long_description}</Card.Text>
               </Card.Body>
+          </Card>
+        {/* <Container fluid>
+          <Row>
+            
             </Card>
           </Row>
           <Row className="p-2">
-            <Button
-              className="mx-auto"
+            
+          </Row>
+        </Container> */}
+        <Button
+              className="mt-3"
               as={NavLink}
               variant="outline-info"
               to={`/archives/${archive.uri}`}
             >
               Visit {archive.name} Archives
-            </Button>
-          </Row>
-        </Container>
+        </Button>
       </Card.Body>
     </Card>
   );
diff --git a/src/components/archives/Archives.js b/src/components/archives/Archives.js
index f2148c055ddd5cfab06cfe00ec15b63f65f5be7c..8bc97d45349ae7045c87acf346601c07b1935b07 100644
--- a/src/components/archives/Archives.js
+++ b/src/components/archives/Archives.js
@@ -1,5 +1,5 @@
 import React, { useContext } from "react";
-import { CardColumns } from "react-bootstrap";
+import { Container, Row, Col } from "react-bootstrap";
 import ArchiveCard from "./ArchiveCard";
 import { GlobalContext } from "../../contexts/GlobalContext";
 
@@ -9,11 +9,13 @@ export function Archives() {
 
   console.log("archives: ", { archives });
   return (
-    <CardColumns className="row-2">
+    <Container fluid>
+      <Row>
       {archives.map((archive) => {
         let key = "archive-" + archive.id;
-        return <ArchiveCard key={key} archive={archive} />;
+        return <Col><ArchiveCard key={key} archive={archive} /></Col>;
       })}
-    </CardColumns>
+      </Row>
+    </Container>
   );
 }
diff --git a/src/components/archives/DataProductCategories.js b/src/components/archives/DataProductCategories.js
index d7f4d71f5be66d7bcf2a123e35784e95ad746f56..beb3cf92a1c894cb2d095d3c24b3631774c58837 100644
--- a/src/components/archives/DataProductCategories.js
+++ b/src/components/archives/DataProductCategories.js
@@ -1,12 +1,15 @@
 import React, { useState, useContext, useEffect } from "react";
-import { NavLink } from "react-router-dom";
+import { useHistory } from "react-router-dom";
 import { ListGroup, Card, Button, Row, Col } from "react-bootstrap";
 import { GlobalContext } from "../../contexts/GlobalContext";
+import { QueryContext } from "../../contexts/QueryContext";
 import axios from "axios";
 
 export default function DataProductCategories({ archive }) {
   const { api_host } = useContext(GlobalContext);
+  const { setDPLevel, setCollection } = useContext(QueryContext);
   const [categories, setCategories] = useState([]);
+  const history = useHistory();
 
   useEffect(() => {
     axios
@@ -39,9 +42,18 @@ export default function DataProductCategories({ archive }) {
                 let query_url = `${category.archive_uri_derived}/query`;
                 console.log("query_url:", query_url);
                 button = (
-                  <Button as={NavLink} variant="outline-info" to={query_url}>
+                  // need to add level (e.g raw) and category (e.g imaging) infomation to send to the form
+                  // probably need to define onSubmit instead of point to query_url
+                  <Button  
+                    onClick={() => {
+                      console.log('onClick', category)
+                      setDPLevel(category.level);
+                      setCollection(category.collection);
+                      history.push(query_url);}}
+                  >
                     Browse Catalog & Run Queries
                   </Button>
+
                 );
               } else if (category.catalog_user_url_derived) {
                 button = (
diff --git a/src/components/basket/addtobasket.js b/src/components/basket/addtobasket.js
index 10408fd34cd4b902ff8ba7ffffbde840a81fb96b..93122ad910e7fc8e943f45758e9bae384f0d428d 100644
--- a/src/components/basket/addtobasket.js
+++ b/src/components/basket/addtobasket.js
@@ -1,19 +1,39 @@
-import React, { useState } from "react";
+import React, { useContext } from "react";
+import * as deepEqual from "deep-equal";
+import { Form } from "react-bootstrap";
+import { GlobalContext } from "../../contexts/GlobalContext";
+import { BasketContext } from "../../contexts/BasketContext";
 
-export default function Addtobasket({ add }) {
-  const [info, setInfo] = useState("");
+export default function Addtobasket(props) {
+  const { isAuthenticated } = useContext(GlobalContext);
+  const basketContext = useContext(BasketContext);
 
-  return (
-    // input field is only here for testing
-    // this will be replaced by real dataset later.
-    <div className="Item">
-      <input
-        type="text"
-        placeholder="New dataset info"
-        value={info}
-        onChange={(e) => setInfo(e.target.value)}
-      ></input>
-      <button onClick={() => add(info)}>Add to basket</button>
-    </div>
-  );
+  function isInBasket(testBasketItem) {
+    const found = basketContext.datasets.some(basketItem => deepEqual(basketItem, testBasketItem));
+    return found;
+  }
+
+  function addToBasket(addToBasketItem) {
+    basketContext.add(addToBasketItem);
+    console.log([addToBasketItem, basketContext]);
+  }
+
+  function removeFromBasket(removeFromBasketItem) {
+    basketContext.remove(removeFromBasketItem);
+    console.log([removeFromBasketItem, basketContext]);
+  }
+
+  if (isAuthenticated){
+    return (
+      <Form.Check id={props.id} type="checkbox" onChange={(event) => {
+        const action = event.target.checked ? addToBasket : removeFromBasket;
+        action(props.item);
+      }} checked={isInBasket(props.item) ? "checked" : ""} />
+    );
+  }
+  else{
+    return (
+      <Form.Check id={props.id} type="checkbox" disabled />
+    );
+  }
 }
diff --git a/src/components/basket/savebasket.js b/src/components/basket/savebasket.js
new file mode 100644
index 0000000000000000000000000000000000000000..5fbe63ae7cc35bbc4efc1710e2e4fb5a6e683a92
--- /dev/null
+++ b/src/components/basket/savebasket.js
@@ -0,0 +1,55 @@
+import React, { useContext } from "react";
+import { Button } from "react-bootstrap";
+import { GlobalContext } from "../../contexts/GlobalContext";
+import { BasketContext } from "../../contexts/BasketContext";
+import axios from "axios";
+
+
+export default function SaveBasket(props) {
+  const { api_host, isAuthenticated } = useContext(GlobalContext);
+  const basketContext = useContext(BasketContext);
+
+  function saveBasket(basketData){
+    const payload = {shopping_cart: basketData};
+    console.log(payload);
+
+    const profileUrl = api_host + "accounts/user-profiles/";
+    axios
+      .get(profileUrl, {withCredentials: true})
+      .then((response) => {
+        const userProfileUrl = profileUrl + response.data.results[0].user_name + "/";
+
+        axios
+          .patch(userProfileUrl, payload, {withCredentials: true})
+          .then((response) => {
+            console.log("patch", response);
+          })
+          .catch((error) => {
+            console.log(error);
+          });
+      })
+      .catch((error) => {
+        console.log(error);
+      });
+  }
+
+
+  if(isAuthenticated){
+    return (
+        <Button
+          type="button"
+          variant="primary"
+          onClick={() => saveBasket(basketContext.datasets)}
+          {...props}
+        >Save Data Selection</Button>
+    );
+  }
+  else{
+    return (<>
+      <Button variant="warning" disabled {...props}>
+        Log In to Enable Data Selection
+      </Button>
+    </>
+    );
+  }
+}
diff --git a/src/components/query/ASTRONVOResults.js b/src/components/query/ASTRONVOResults.js
index 1a5735b385b6690444b403f2acf21d0739a5773a..76937c2d05845f7bc1f3bd89f15e83578a2d4005 100644
--- a/src/components/query/ASTRONVOResults.js
+++ b/src/components/query/ASTRONVOResults.js
@@ -3,16 +3,30 @@ import { Table, Alert } from "react-bootstrap";
 import { QueryContext } from "../../contexts/QueryContext";
 import LoadingSpinner from "../LoadingSpinner";
 import Paginate from "../Paginate";
+import HandlePreview from "./HandlePreview";
+import Preview from "./Preview";
 
 export default function ASTRONVOResults({ catalog }) {
-  const { queryMap } = useContext(QueryContext);
+  const { queryMap, page, setPage, preview } = useContext(QueryContext);
   if (!queryMap) return null;
   if (queryMap.get(catalog).status === "fetched") {
+    if (!("results" in queryMap.get(catalog).results))
+      return <Alert variant="warning">{queryMap.get(catalog).results}</Alert>;
     if (queryMap.get(catalog).results.results.length === 0)
       return <Alert variant="warning">No matching results found!</Alert>;
+
+    const numPages = queryMap.get(catalog).results.pages;
     console.log(queryMap.get(catalog).results.results);
     return (
       <>
+        <Paginate
+          getNewPage={(args) => {
+            return args.target ? setPage(parseFloat(args.target.text)) : null;
+          }}
+          currentPage={page}
+          numAdjacent={3}
+          numPages={numPages}
+        />
         <Table className="mt-3" responsive>
           <thead>
             <tr className="bg-light">
@@ -29,30 +43,45 @@ export default function ASTRONVOResults({ catalog }) {
               <th>Calibration Level</th>
               <th>Size</th>
               <th>Link to data</th>
+              <th></th>
             </tr>
           </thead>
           <tbody>
             {queryMap.get(catalog).results.results.map((result) => {
               return (
-                <tr key={result.result}>
-                  {/* <th>
-                  <InputGroup>
-                    <InputGroup.Checkbox />
-                  </InputGroup>
-                </th> */}
-                  <td>{result.obs_collection}</td>
-                  <td>{Number(result.ra).toFixed(1)}</td>
-                  <td>{Number(result.dec).toFixed(1)}</td>
-                  <td>{Number(result.fov).toFixed(1)}</td>
-                  <td>{result.dataproduct_type}</td>
-                  <td>{result.calibration_level}</td>
-                  <td>{Number((result.size / 1024).toFixed(1))} MB</td>
-                  <td>
-                    <a href={result.url} rel="noopener noreferrer" download>
-                      Download
-                    </a>
-                  </td>
-                </tr>
+                <>
+                  <tr key={result.url}>
+                    {/* <th>
+                      <InputGroup>
+                        <InputGroup.Checkbox />
+                      </InputGroup>
+                      </th> */}
+                    <td>{result.obs_collection}</td>
+                    <td>{Number(result.ra).toFixed(1)}</td>
+                    <td>{Number(result.dec).toFixed(1)}</td>
+                    <td>{Number(result.fov).toFixed(1)}</td>
+                    <td>{result.dataproduct_type}</td>
+                    <td>{result.calibration_level}</td>
+                    <td>{Number((result.size / 1024).toFixed(1))} MB</td>
+                    <td>
+                      <a href={result.url} rel="noopener noreferrer" download>
+                        Download data
+                      </a>
+                    </td>
+                    <td>
+                      <HandlePreview result={result} />
+                    </td>
+                  </tr>
+                  {preview === result.url && 
+                    <tr key={result.url}>
+                      <td></td>
+                      <td></td>
+                      <td></td>
+                      <td></td>
+                      <td colSpan="4" ><Preview /></td>
+                      <td></td>
+                    </tr>}
+                </>
               );
             })}
           </tbody>
diff --git a/src/components/query/ApertifResults.js b/src/components/query/ApertifResults.js
index b360f12e6653e6da0080e96407dcd16fbfc4f24f..15b35243b35cd29cc5d0dd3d4439504bcd2481ac 100644
--- a/src/components/query/ApertifResults.js
+++ b/src/components/query/ApertifResults.js
@@ -3,16 +3,30 @@ import { Table, Alert } from "react-bootstrap";
 import { QueryContext } from "../../contexts/QueryContext";
 import LoadingSpinner from "../LoadingSpinner";
 import Paginate from "../Paginate";
+import HandlePreview from "./HandlePreview";
+import Preview from "./Preview";
 
 export default function ApertifResults({ catalog }) {
-  const { queryMap } = useContext(QueryContext);
+  const { queryMap, page, setPage, preview } = useContext(QueryContext);
   if (!queryMap) return null;
   if (queryMap.get(catalog).status === "fetched") {
+    if (!("results" in queryMap.get(catalog).results))
+      return <Alert variant="warning">{queryMap.get(catalog).results}</Alert>;
     if (queryMap.get(catalog).results.results.length === 0)
       return <Alert variant="warning">No matching results found!</Alert>;
+
+    const numPages = queryMap.get(catalog).results.pages;
     console.log("Query results:", queryMap.get(catalog).results.results);
     return (
       <>
+        <Paginate
+          getNewPage={(args) => {
+            return args.target ? setPage(parseFloat(args.target.text)) : null;
+          }}
+          currentPage={page}
+          numAdjacent={3}
+          numPages={numPages}
+        />
         <Table className="mt-3" responsive>
           <thead>
             <tr className="bg-light">
@@ -29,11 +43,13 @@ export default function ApertifResults({ catalog }) {
               <th>Data Product Type</th>
               <th>Data Product Subtype</th>
               <th>Link to data</th>
+              <th></th>
             </tr>
           </thead>
           <tbody>
             {queryMap.get(catalog).results.results.map((result) => {
               return (
+                <>
                 <tr key={result.PID}>
                   {/* <th>
                   <InputGroup>
@@ -52,26 +68,29 @@ export default function ApertifResults({ catalog }) {
                       href={result.url}
                       target="_blank"
                       rel="noopener noreferrer"
+                      download
                     >
-                      View data
+                      Download data
                     </a>
-                    {result.dataProductSubType === "continuumMF" ? (
-                      <a
-                        href={result.thumbnail}
-                        target="_blank"
-                        rel="noopener noreferrer"
-                        className="ml-3"
-                      >
-                        Thumbnail
-                      </a>
-                    ) : null}
+                  </td>
+                  <td>
+                      <HandlePreview result={result} />
                   </td>
                 </tr>
+                {preview === result.url && 
+                    <tr key={result.url}>
+                      <td></td>
+                      <td></td>
+                      <td></td>
+                      <td></td>
+                      <td colSpan="4" ><Preview /></td>
+                      <td></td>
+                    </tr>}
+                </>
               );
             })}
           </tbody>
         </Table>
-        {/* <Paginate /> */}
       </>
     );
   } else {
diff --git a/src/components/query/HandlePreview.js b/src/components/query/HandlePreview.js
new file mode 100644
index 0000000000000000000000000000000000000000..04946bb3d282af85c5a94978c78df55ea596038b
--- /dev/null
+++ b/src/components/query/HandlePreview.js
@@ -0,0 +1,34 @@
+import React, { useContext } from 'react';
+import { Button } from 'react-bootstrap';
+import { QueryContext } from '../../contexts/QueryContext';
+
+export default function HandlePreview({ result }) {
+    const { preview, setPreview, setDS9, setURL } = useContext(QueryContext);
+    return (
+        <>
+            {/* if results is in .fits format and is smaller than 10 MB,
+            display it with js9 */}
+            {((result.url.includes('fits')  || (result.url.includes('FITS'))) && 
+                Number(result.size) < 10000) ? 
+                (<Button 
+                    onClick={() => {
+                        preview ? setPreview("") : setPreview(result.url);
+                        setURL(result.url);
+                        setDS9(true);
+                    }}
+                >View fits with DS9</Button>) :
+                (result.thumbnail && (
+                    <Button
+                        onClick={()=>{
+                            preview ? setPreview("") : setPreview(result.url);
+                            setURL(result.thumbnail);
+                        }}
+                    >
+                        View Thumbnail
+                    </Button>
+                ))
+            }
+        </>
+    )
+}
+
diff --git a/src/components/query/LOFARResults.js b/src/components/query/LOFARResults.js
new file mode 100644
index 0000000000000000000000000000000000000000..0aaf6bd37cf93b60bf9d9fd277993681a2dfd05f
--- /dev/null
+++ b/src/components/query/LOFARResults.js
@@ -0,0 +1,97 @@
+import React, { useContext } from "react";
+import { Table, Alert } from "react-bootstrap";
+import { QueryContext } from "../../contexts/QueryContext";
+import LoadingSpinner from "../LoadingSpinner";
+
+export default function LOFARResults({ catalog }) {
+  const { queryMap } = useContext(QueryContext);
+  if (!queryMap) return null;
+  if (queryMap.get(catalog).status === "fetched") {
+    if (!("results" in queryMap.get(catalog).results))
+      return <Alert variant="warning">{queryMap.get(catalog).results}</Alert>;
+    if (queryMap.get(catalog).results.results.length === 0)
+      return <Alert variant="warning">No matching results found!</Alert>;
+
+    //const numPages = queryMap.get(catalog).results.pages;
+    console.log("Query results:", queryMap.get(catalog).results.results);
+    return (
+      <>
+        {/* <Paginate
+          getNewPage={(args) => {
+            return args.target ? setPage(parseFloat(args.target.text)) : null;
+          }}
+          currentPage={page}
+          numAdjacent={3}
+          numPages={numPages}
+        /> */}
+        <Table className="mt-3" responsive>
+          <thead>
+            <tr className="bg-light">
+              {/* <th>
+              <InputGroup>
+                <InputGroup.Checkbox />
+              </InputGroup>
+            </th> */}
+              <th>Project</th>
+              <th>SAS ID</th>
+              <th>Target Name</th>
+              <th>RA</th>
+              <th>Dec</th>
+              <th>Release Date</th>
+              <th>Start Time</th>
+              <th>Duration</th>
+              <th>Pipeline</th>
+              <th>Antenna Set</th>
+              <th>Instrument Filter</th>
+            </tr>
+          </thead>
+          <tbody>
+            {queryMap.get(catalog).results.results.map((result) => {
+              return (
+                <tr key={result.PID}>
+                  {/* <th>
+                  <InputGroup>
+                    <InputGroup.Checkbox />
+                  </InputGroup>
+                </th> */}
+                  <td>{result.project}</td>
+                  <td>{result.sas_id}</td>
+                  <td>{result.target}</td>
+                  <td>{Number(result.ra).toFixed(1)}</td>
+                  <td>{Number(result.dec).toFixed(1)}</td>
+                  <td>{result.releaseDate}</td>
+                  <td>{result.startTime}</td>
+                  <td>{result.duration}</td>
+                  <td>{result.pipeline}</td>
+                  <td>{result.antennaSet}</td>
+                  <td>{result.instrumentFilter}</td>
+                  {/* <td>
+                    <a
+                      href={result.url}
+                      target="_blank"
+                      rel="noopener noreferrer"
+                    >
+                      View data
+                    </a>
+                    {result.dataProductSubType === "continuumMF" ? (
+                      <a
+                        href={result.thumbnail}
+                        target="_blank"
+                        rel="noopener noreferrer"
+                        className="ml-3"
+                      >
+                        Thumbnail
+                      </a>
+                    ) : null}
+                  </td> */}
+                </tr>
+              );
+            })}
+          </tbody>
+        </Table>
+      </>
+    );
+  } else {
+    return <LoadingSpinner />;
+  }
+}
diff --git a/src/components/query/Preview.js b/src/components/query/Preview.js
new file mode 100644
index 0000000000000000000000000000000000000000..84896fd86620a12333644ec9ffa947e9eff198dd
--- /dev/null
+++ b/src/components/query/Preview.js
@@ -0,0 +1,32 @@
+import React, { useContext } from 'react';
+import { Image } from 'react-bootstrap';
+import { QueryContext } from '../../contexts/QueryContext';
+
+export default function Preview() {
+    const { preview, ds9, url } = useContext(QueryContext);
+    return (
+        <>
+        {console.log("preview: ", preview)}
+        {console.log("url: ", url)}
+        {(preview &&
+            (ds9 ? 
+            <iframe 
+                title="DS9"
+                className="embed-responsive-item"
+                height="700"
+                width="700"
+                src={"https://js9.si.edu/js9/js9.html?url="+JSON.parse(JSON.stringify(url))+"&colormap=viridis&scale=log"}
+                allowFullScreen
+            ></iframe>
+            :
+            <Image 
+                width={700}
+                className={"mt-3"}
+                src={url}
+                alt=""
+            />)
+        )}
+        </>
+    )
+}
+
diff --git a/src/components/query/QueryADEX.js b/src/components/query/QueryADEX.js
new file mode 100644
index 0000000000000000000000000000000000000000..96243532d47e28f408aa03835d7851d2a0f477ff
--- /dev/null
+++ b/src/components/query/QueryADEX.js
@@ -0,0 +1,152 @@
+import React, { useContext, useEffect } from "react";
+import { useParams, useHistory } from "react-router-dom";
+import axios from "axios";
+import { Container } from "react-bootstrap";
+import Form from "react-jsonschema-form";
+import { GlobalContext } from "../../contexts/GlobalContext";
+import { QueryContext } from "../../contexts/QueryContext";
+import QueryResults from "./QueryResults";
+import parseQueryForm from "../../utils/form/parseQueryForm";
+
+export default function QueryCatalogs() {
+  // queryMap is a map of dictionaries, where each dictionary consists of
+  // {"catalog": "catalogname",
+  //  "catalogquery": "querystring",
+  //  "status": "fetching|fechted",
+  //  "results": null}
+  const { config, setConfigName, defaultConf, queryMap, formData, setFormData, page } = useContext(QueryContext);
+  const { api_host } = useContext(
+    GlobalContext
+  );
+  const { uri } = useParams();
+  const history = useHistory();
+  console.log("uri:", uri);
+  console.log("default conf:", defaultConf);
+
+  // 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;
+    }
+    return () => {
+      console.log("cleaned up");
+      queryMap.clear();
+      setFormData();
+      setConfigName(uri);
+    };
+  }, [uri]);
+
+  useEffect(() => {
+    console.log(config.query_schema);
+    if (!formData) return;
+    const gui = config.query_schema.name;
+    const queries = parseQueryForm(gui, formData, page);
+
+    // 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
+    queryMap.clear();
+    queries.forEach((query) => {
+      queryMap.set(query.catalog, {
+        catalog: query.catalog,
+        esapquery: query.esapquery,
+        status: "fetching",
+        results: null,
+      });
+      const url = api_host + "query/query/?" + query.esapquery;
+      axios
+        .get(url)
+        .then((queryResponse) => {
+          queryMap.set(query.catalog, {
+            catalog: query.catalog,
+            esapquery: query.esapquery,
+            status: "fetched",
+            results: queryResponse.data,
+          });
+        })
+        .catch(() => {
+          queryMap.set(query.catalog, {
+            catalog: query.catalog,
+            esapquery: query.esapquery,
+            status: "error",
+            results: null,
+          });
+        });
+    });
+  }, [formData, page]);
+
+  function formTemplate({ TitleField, properties, title, description }) {
+    return (
+      <div>
+        <TitleField title={title} />
+        <div className="row">
+          {properties.map((prop) => (
+            <div
+              className="col-lg-2 col-md-4 col-sm-6 col-xs-12"
+              key={prop.content.key}
+            >
+              {prop.content}
+            </div>
+          ))}
+        </div>
+        {description}
+      </div>
+    );
+  }
+
+  console.log("queryMap", Array.from(queryMap.values()));
+
+  const uiSchemaProp = config.ui_schema ? { uiSchema: config.ui_schema } : {};
+  return (
+    <Container fluid>
+      <Form
+        schema={config.query_schema}
+        ObjectFieldTemplate={formTemplate}
+        formData={formData}
+        onBlur={(field, value) => {
+          if (field == "root_catalog") {
+            console.log("Change query catalog to : ", value);
+            if (value == "adex") {
+              history.push("/query");
+            } else {
+              history.push("/archives/" + value + "/query");
+            }
+          }
+        }}
+        onSubmit={({ formData }) => setFormData(formData)}
+        {...uiSchemaProp}
+      ></Form>
+      {Array.from(queryMap.keys()).map((catalog) => {
+        console.log("catalog:", catalog);
+        const details = queryMap.get(catalog);
+        console.log("Details:", details);
+        console.log("Results:", details.results);
+        let catalogName =
+          config.query_schema.properties.catalog.enumNames[
+            config.query_schema.properties.catalog.enum.findIndex(
+              (name) => name === catalog
+            )
+          ];
+        return (
+          <div key={catalog} className="mt-3">
+            <h4>Query results for {catalogName}</h4>
+            <QueryResults catalog={catalog} />
+          </div>
+        );
+      })}
+    </Container>
+  );
+}
diff --git a/src/components/query/QueryCatalogs.js b/src/components/query/QueryCatalogs.js
index 913d2aabf0450eb7cbfba1350a6b2bd375782360..4fa5fc8732722480e6d356978f272e6fc55a5109 100644
--- a/src/components/query/QueryCatalogs.js
+++ b/src/components/query/QueryCatalogs.js
@@ -4,6 +4,7 @@ import axios from "axios";
 import { Container } from "react-bootstrap";
 import Form from "react-jsonschema-form";
 import { GlobalContext } from "../../contexts/GlobalContext";
+import { BasketContextProvider } from "../../contexts/BasketContext"
 import { QueryContext } from "../../contexts/QueryContext";
 import QueryResults from "./QueryResults";
 import parseQueryForm from "../../utils/form/parseQueryForm";
@@ -14,10 +15,13 @@ export default function QueryCatalogs() {
   //  "catalogquery": "querystring",
   //  "status": "fetching|fechted",
   //  "results": null}
-  const { queryMap, formData, setFormData, page } = useContext(QueryContext);
-  const { config, api_host, setConfigName } = useContext(GlobalContext);
+  const { config, setConfigName, defaultConf, queryMap, formData, setFormData, page } = useContext(QueryContext);
+  const { api_host } = useContext(
+    GlobalContext
+  );
   const { uri } = useParams();
-  console.log(uri);
+  console.log("uri:", uri);
+  console.log("default conf:", defaultConf);
 
   // set ConfigName for archive
   useEffect(() => {
@@ -31,6 +35,9 @@ export default function QueryCatalogs() {
       case "zooniverse":
         setConfigName("zooniverse");
         break;
+      case "esap_rucio":
+        setConfigName("esap_rucio");
+        break;
       case "astron_vo":
         setConfigName("astron_vo");
         break;
@@ -38,11 +45,13 @@ export default function QueryCatalogs() {
         setConfigName("lofar");
         break;
       default:
-        setConfigName("esap_ivoa");
+        break;
     }
     return () => {
       console.log("cleaned up");
-      setConfigName("esap_ivoa");
+      queryMap.clear();
+      setFormData();
+      setConfigName(defaultConf);
     };
   }, [uri]);
 
@@ -129,7 +138,9 @@ export default function QueryCatalogs() {
         return (
           <div key={catalog} className="mt-3">
             <h4>Query results for {catalogName}</h4>
-            <QueryResults catalog={catalog} />
+            <BasketContextProvider>
+              <QueryResults catalog={catalog} />
+            </BasketContextProvider>
           </div>
         );
       })}
diff --git a/src/components/query/QueryIVOARegistry.js b/src/components/query/QueryIVOARegistry.js
index cf1101a5d9266a9e42c8ac3a5eb7ca5e00351250..677b69c452fd27f2ecfb61d55aa0643647513cc4 100644
--- a/src/components/query/QueryIVOARegistry.js
+++ b/src/components/query/QueryIVOARegistry.js
@@ -17,11 +17,16 @@ export default function QueryIVOARegistry() {
   //  "catalogquery": "querystring",
   //  "status": "fetching|fechted",
   //  "results": null}
-  const { queryMap, formData, setFormData } = useContext(QueryContext);
-  const { config, api_host, setConfigName } = useContext(GlobalContext);
-  const { selectedRegistry, queryStep, setQueryStep } = useContext(IVOAContext);
+  const { config, setConfigName, defaultConf, queryMap, formData, setFormData, page } = useContext(QueryContext);
+  const { api_host } = useContext(
+    GlobalContext
+  );
+  const { selectedRegistry, queryStep, setQueryStep, regPage } = useContext(
+    IVOAContext
+  );
   const { uri } = useParams();
   console.log("uri:", uri);
+  console.log("default conf: ", defaultConf);
 
   // set ConfigName for archive
   useEffect(() => {
@@ -46,7 +51,7 @@ export default function QueryIVOARegistry() {
     }
     return () => {
       console.log("Set configuration back to default!");
-      setConfigName("esap_ivoa");
+      setConfigName(defaultConf);
     };
   }, [uri]);
 
@@ -59,16 +64,17 @@ export default function QueryIVOARegistry() {
 
     if (queryStep === "run-query") {
       selectedRegistry.forEach((access_url) => {
-        queries = [...queries, ...parseVOServiceForm(formData, access_url)];
+        queries = [
+          ...queries,
+          ...parseVOServiceForm(formData, access_url, page),
+        ];
       });
     } else {
-      queries = parseQueryForm(gui, formData);
+      queries = parseQueryForm(gui, formData, regPage);
     }
 
     console.log("queries:", queries);
 
-    // 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
     queryMap.clear();
     queries.forEach((query) => {
       queryMap.set(query.catalog, {
@@ -82,25 +88,43 @@ export default function QueryIVOARegistry() {
       axios
         .get(url)
         .then((queryResponse) => {
-          queryMap.set(query.catalog, {
-            catalog: query.catalog,
-            service_type: query.service_type,
-            esapquery: query.esapquery,
-            status: "fetched",
-            results: queryResponse.data,
-          });
+          if(queryStep === "run-query") {
+          let tf_url = api_host + "query/get-tables-fields/?dataset_uri=vo_reg&access_url=" + query.catalog;
+          console.log("table fields url: ", tf_url);
+          axios
+            .get(tf_url)
+            .then((tfResponse) => {
+              queryMap.set(query.catalog, {
+                catalog: query.catalog,
+                service_type: query.service_type,
+                vo_table_schema: tfResponse.data.results.find((item) => item.table_name === "ivoa.obscore"),
+                esapquery: query.esapquery,
+                status: "fetched",
+                results: queryResponse.data,
+              });
+            })
+          }
+          else {
+            queryMap.set(query.catalog, {
+              catalog: query.catalog,
+              service_type: query.service_type,
+              esapquery: query.esapquery,
+              status: "fetched",
+              results: queryResponse.data,
+          })};                      
         })
         .catch(() => {
           queryMap.set(query.catalog, {
             catalog: query.catalog,
             service_type: query.service_type,
+            vo_table_schema:"",
             esapquery: query.esapquery,
             status: "error",
             results: null,
           });
         });
     });
-  }, [formData]);
+  }, [formData, page, regPage]);
 
   function formTemplate({ TitleField, properties, title, description }) {
     return (
@@ -132,6 +156,7 @@ export default function QueryIVOARegistry() {
       query: { "ui:widget": "textarea" },
       keyword: { "ui:widget": "hidden" },
       tap_schema: { "ui:widget": "hidden" },
+      waveband: { "ui:widget": "hidden" },
     };
     console.log("new ui schema:", uiSchemaProp);
     return (
@@ -176,7 +201,7 @@ export default function QueryIVOARegistry() {
           {...uiSchemaProp}
         >
           <div>
-            <Button type="submit">Get Registry Services</Button>
+            <Button type="submit">Query VO Registry</Button>
           </div>
         </Form>
         {Array.from(queryMap.keys()).map((catalog) => {
@@ -184,17 +209,17 @@ export default function QueryIVOARegistry() {
           const details = queryMap.get(catalog);
           console.log("Details:", details);
           console.log("Results:", details.results);
-          let catalogName =
-            config.query_schema.properties.catalog.enumNames[
-              config.query_schema.properties.catalog.enum.findIndex(
-                (name) => name === catalog
-              )
-            ];
+          // let catalogName =
+          //   config.query_schema.properties.catalog.enumNames[
+          //     config.query_schema.properties.catalog.enum.findIndex(
+          //       (name) => name === catalog
+          //     )
+          //   ];
           return (
             <div key={catalog} className="mt-3">
               <Row>
                 <Col>
-                  <h4>List of registries</h4>
+                  <h4>List of resources</h4>
                 </Col>
                 <Col>
                   {selectedRegistry.length === 0 ? (
@@ -206,7 +231,7 @@ export default function QueryIVOARegistry() {
                         setQueryStep("run-query");
                       }}
                     >
-                      Query selected registry
+                      Query selected resources
                     </Button>
                   )}
                 </Col>
diff --git a/src/components/query/QueryResults.js b/src/components/query/QueryResults.js
index edc9542aed74a5a35a07649a4e78e932fe3c9c94..69e23c17de7eb00bbe9e39e62a16a18c98bbbd0b 100644
--- a/src/components/query/QueryResults.js
+++ b/src/components/query/QueryResults.js
@@ -2,7 +2,9 @@ import React from "react";
 import ApertifResults from "./ApertifResults";
 import ASTRONVOResults from "./ASTRONVOResults";
 import ZooniverseResults from "./ZooniverseResults";
-import VORegistryResults from "./VORegistryResults";
+import VORegListResults from "./VORegListResults";
+import LOFARResults from "./LOFARResults";
+import RucioResults from "./RucioResults";
 
 export default function QueryResults({ catalog }) {
   switch (catalog) {
@@ -15,7 +17,11 @@ export default function QueryResults({ catalog }) {
     case "zooniverse_workflows":
       return <ZooniverseResults catalog={catalog} />;
     case "vo_reg":
-      return <VORegistryResults catalog={catalog} />;
+      return <VORegListResults catalog={catalog} />;
+    case "lofar":
+      return <LOFARResults catalog={catalog} />;
+    case "rucio":
+      return <RucioResults catalog={catalog} />;
     default:
       return null;
   }
diff --git a/src/components/query/RucioResults.js b/src/components/query/RucioResults.js
new file mode 100644
index 0000000000000000000000000000000000000000..4788f1368995d50d6729918f17cc37012ed6bb91
--- /dev/null
+++ b/src/components/query/RucioResults.js
@@ -0,0 +1,131 @@
+import React, { useContext } from "react";
+import { Table, Alert, Form } from "react-bootstrap";
+import { QueryContext } from "../../contexts/QueryContext";
+// import { BasketContext } from "../../contexts/BasketContext";
+import LoadingSpinner from "../LoadingSpinner";
+import Paginate from "../Paginate";
+// import SaveBasket from "../basket/savebasket";
+
+function titleCase(string) {
+  var sentence = string.toLowerCase().split(" ");
+  for (var i = 0; i < sentence.length; i++) {
+    sentence[i] = sentence[i][0].toUpperCase() + sentence[i].slice(1);
+  }
+  return sentence.join(" ");
+}
+
+function newPageCallback(setPage) {
+  return (args) => {
+    if (args.target) {
+      setPage(parseFloat(args.target.text));
+    }
+  };
+}
+
+export default function RucioResults({ catalog }) {
+  const context = useContext(QueryContext);
+  // const basketContext = useContext(BasketContext);
+  const { queryMap, page, setPage } = context;
+
+  // console.log(queryMap, page, context.queryMap.get(catalog).status);
+
+  if (!context.queryMap) return null;
+  if (context.queryMap.get(catalog).status === "fetched") {
+    if (context.queryMap.get(catalog).results.results.length === 0)
+      return <Alert variant="warning">No matching results found!</Alert>;
+    else if (catalog === "rucio") {
+      const result = queryMap.get("rucio").results.results[0];
+      const numPages = queryMap.get("rucio").results.pages;
+
+      const fields = Object.keys(result).map(
+        (key) => key
+      );
+      const headers = Object.keys(result).map((field) => {
+        const title = titleCase(field.replace("_", " "));
+        return <th key={`header_${field}`}>{title}</th>;
+      });
+
+      return (
+        <>
+          <Paginate
+            getNewPage={newPageCallback(setPage)}
+            currentPage={page}
+            numAdjacent={3}
+            numPages={numPages}
+          />
+          <Form>
+            {/*<SaveBasket />*/}
+            <Table className="mt-3" responsive>
+              <thead>
+                <tr className="bg-light">
+                  {/* <th>
+                <InputGroup>
+                  <InputGroup.Checkbox />
+                </InputGroup>
+              </th> */}
+                  {headers}
+                </tr>
+              </thead>
+              <tbody>
+                {queryMap
+                  .get("rucio")
+                  .results.results.map((result, resultCounter) => {
+                    const cells = fields.map((field) => {
+                      const reactKey = `item_${resultCounter}_${field}`;
+                      return (
+                        <td key={reactKey}>
+                          {result[field]}
+                        </td>
+                      );
+                    });
+                    return (
+                      <tr key={`item_${resultCounter}`}>
+                        {/* <th>
+                    <InputGroup>
+                      <InputGroup.Checkbox />
+                    </InputGroup>
+                  </th> */}
+                        {/*<td>
+                        <Form.Check id={`selectClassifications_${result.project_id}`} type="checkbox" onChange={(event) => {
+                          const action = event.target.checked ? addToBasket : removeFromBasket;
+                          action(result.project_id, basketContext, "project", "classifications");
+                        }} checked={isInBasket(result.project_id, basketContext, "project", "classifications") ? "checked" : ""} />
+                      </td>
+                      <td>
+                        <Form.Check id={`selectSubjects_${result.project_id}`} type="checkbox" onChange={(event) => {
+                          const action = event.target.checked ? addToBasket : removeFromBasket;
+                          action(result.project_id, basketContext, "project", "subjects");
+                        }} checked={isInBasket(result.project_id, basketContext, "project", "subjects") ? "checked" : ""} />
+                      </td>*/}
+                        {/*<td>{result.project_id}</td>
+                      <td>{result.display_name}</td>
+                      <td>{created_at}</td>
+                      <td>{updated_at}</td>
+                      <td>{launch_date}</td>
+                      <td>{live}</td>
+                      <td>
+                        <a href={`https://zooniverse.org/projects/${result.slug}`}>
+                          Link
+                      </a>
+                      </td>*/}
+                        {cells}
+                      </tr>
+                    );
+                  })}
+              </tbody>
+            </Table>
+          </Form>
+          <Paginate
+            getNewPage={newPageCallback(setPage)}
+            currentPage={page}
+            numAdjacent={3}
+            numPages={numPages}
+          />
+        </>
+      );
+    }
+  }
+  else {
+    return <LoadingSpinner />;
+  }
+}
diff --git a/src/components/query/VORegistryResults.js b/src/components/query/VORegListResults.js
similarity index 87%
rename from src/components/query/VORegistryResults.js
rename to src/components/query/VORegListResults.js
index d8481c93430700d4c8ef622cc70a238703f9fa6c..19c6f2a23877f25cea921000ab15f62bd2eca8b6 100644
--- a/src/components/query/VORegistryResults.js
+++ b/src/components/query/VORegListResults.js
@@ -1,11 +1,11 @@
-import React, { useContext, useEffect, useState } from "react";
+import React, { useContext, useEffect } from "react";
 import { Table, Alert, InputGroup } from "react-bootstrap";
 import { QueryContext } from "../../contexts/QueryContext";
 import LoadingSpinner from "../LoadingSpinner";
 import Paginate from "../Paginate";
 import { IVOAContext } from "../../contexts/IVOAContext";
 
-export default function VORegistryResults({ catalog }) {
+export default function VORegListResults({ catalog }) {
   const { queryMap } = useContext(QueryContext);
   const {
     selectedRegistry,
@@ -13,6 +13,8 @@ export default function VORegistryResults({ catalog }) {
     removeRegistry,
     registryList,
     setRegistryList,
+    regPage,
+    setRegPage,
   } = useContext(IVOAContext);
   // const [checkAll, setCheckAll] = useState("");
 
@@ -35,8 +37,20 @@ export default function VORegistryResults({ catalog }) {
     setRegistryList(queryMap.get(catalog).results.results);
     console.log("Registry List:", registryList);
 
+    const numPages = queryMap.get(catalog).results.pages;
+
     return (
       <>
+        <Paginate
+          getNewPage={(args) => {
+            return args.target
+              ? setRegPage(parseFloat(args.target.text))
+              : null;
+          }}
+          currentPage={regPage}
+          numAdjacent={3}
+          numPages={numPages}
+        />
         <Table className="mt-3" responsive>
           <thead>
             <tr className="bg-light">
@@ -60,7 +74,7 @@ export default function VORegistryResults({ catalog }) {
                   />
                 </InputGroup>
               </th>
-              <th>Name</th>
+              <th>Resource</th>
               <th>Access URL</th>
               <th>Waveband</th>
               <th>Title</th>
@@ -96,7 +110,6 @@ export default function VORegistryResults({ catalog }) {
             })}
           </tbody>
         </Table>
-        {/* <Paginate /> */}
       </>
     );
   } else {
diff --git a/src/components/query/VOServiceResults.js b/src/components/query/VOServiceResults.js
index 0f9ee8c79bc649c1c5e2b91202a8dcea1c09145d..3d8147c0a76b4284a0802fe8060eca4cf4a2f9f3 100644
--- a/src/components/query/VOServiceResults.js
+++ b/src/components/query/VOServiceResults.js
@@ -1,40 +1,113 @@
 import React, { useContext } from "react";
-import { Alert, Table } from "react-bootstrap";
+import { Alert, Table, Button } from "react-bootstrap"; 
 import { QueryContext } from "../../contexts/QueryContext";
+import LoadingSpinner from "../LoadingSpinner";
+import Paginate from "../Paginate";
+import Preview from "./Preview";
 
 export default function VORegistryResults({ catalog }) {
-  const { queryMap } = useContext(QueryContext);
+  const { queryMap, page, setPage, preview, setPreview, setURL } = useContext(QueryContext);
 
   if (!queryMap.get(catalog)) return null;
   console.log("VO service queryMap:", queryMap.get(catalog));
+
   if (queryMap.get(catalog).status === "fetched") {
+    // if (queryMap.get(catalog).results[0].includes("ERROR"))
+    //   return (
+    //     <Alert variant="warning">{queryMap.get(catalog).results[0]}</Alert>
+    //   );
     if (queryMap.get(catalog).results.results.length === 0)
       return <Alert variant="warning">No matching results found!</Alert>;
+
+    const numPages = queryMap.get(catalog).results.pages;
+    let indice = [];
+
     return (
       <div>
         <h1>Results from {catalog}</h1>
+        <Paginate
+          getNewPage={(args) => {
+            return args.target ? setPage(parseFloat(args.target.text)) : null;
+          }}
+          currentPage={page}
+          numAdjacent={3}
+          numPages={numPages}
+        />
         <Table className="mt-3" responsive>
           <thead>
             <tr className="bg-light">
-              <th>Link to data</th>
+              {queryMap.get(catalog).vo_table_schema.fields.map((field, index) => {
+                if ((field.name === "dataproduct_type") || (field.name === "dataproduct_subtype") ||
+                    (field.name === "calib_level") || (field.name === "obs_collection") ||
+                    (field.name === "obs_id") ||
+                    (field.name === "calib_level") || (field.name === "access_url") ||
+                    (field.name === "access_estsize") || (field.name === "target_name") ||
+                    (field.name === "s_ra") || (field.name === "s_dec") ||
+                    (field.name === "s_fov") ||
+                    (field.name === "instrument_name") || (field.name === "preview")
+                ) {
+                  indice.push(index);
+                  return (<th>{field.name}</th>);
+                }
+                return null;
+              })}
             </tr>
           </thead>
           <tbody>
             {queryMap.get(catalog).results.results.map((result) => {
+
+              let queryResult = result.result.split(",");
+
               return (
-                <tr key={result.result}>
-                  <td>
-                    <a href={result.result} rel="noopener noreferrer" download>
-                      {result.result}
-                    </a>
-                  </td>
-                </tr>
+                <>
+                  <tr key={queryResult[queryMap.get(catalog).vo_table_schema.fields.findIndex((item) => item.name === "access_url")]}>
+                    {queryResult.map((field, index) => {
+                      if (indice.includes(index)) {
+                        if (queryMap.get(catalog).vo_table_schema.fields[index].name === "access_url") {
+                          return (<td><a href={field} rel="noopener noreferrer" download>Download data</a></td>);
+                        }
+                        if (queryMap.get(catalog).vo_table_schema.fields[index].name === "preview") {
+                          return (<td>
+                            {
+                              <Button
+                                  onClick={()=>{
+                                      setPreview(field);
+                                      setURL(field);
+                                  }}
+                              >
+                                  View Thumbnail
+                              </Button>
+                            }
+                          </td> );
+                        }
+                        if ((queryMap.get(catalog).vo_table_schema.fields[index].name === "s_ra") ||
+                            (queryMap.get(catalog).vo_table_schema.fields[index].name === "s_dec") ||
+                            (queryMap.get(catalog).vo_table_schema.fields[index].name === "s_fov")
+                        ) {
+                          return (<td>{Number(field).toFixed(1)}</td>)
+                        }
+                        return (<td>{field}</td>) ;
+                      }
+                      return null;
+                    })}
+                  </tr>
+                  { 
+                    preview === queryResult[queryMap.get(catalog).vo_table_schema.fields.findIndex((item) => item.name === "preview")] && 
+                      <tr key={queryResult.preview}>
+                        <td></td>
+                        <td></td>
+                        <td></td>
+                        <td colSpan={queryResult.length-3} ><Preview /></td>
+                      </tr>
+                  }
+                </>
               );
             })}
           </tbody>
         </Table>
       </div>
     );
+  } else {
+    return <LoadingSpinner />;
   }
-  return null;
 }
diff --git a/src/components/query/ZooniverseResults.js b/src/components/query/ZooniverseResults.js
index 69ff383d90af05b207d7549bfd45f6db2558ed42..aef7c46823e3d2cb49b457924272817ba37033a0 100644
--- a/src/components/query/ZooniverseResults.js
+++ b/src/components/query/ZooniverseResults.js
@@ -1,8 +1,12 @@
 import React, { useContext, useState } from "react";
-import { Table, Alert } from "react-bootstrap";
+import { Table, Alert, Form, Button } from "react-bootstrap";
+import * as deepEqual from "deep-equal";
 import { QueryContext } from "../../contexts/QueryContext";
+import { BasketContext } from "../../contexts/BasketContext";
 import LoadingSpinner from "../LoadingSpinner";
 import Paginate, { pagination_fields } from "../Paginate";
+import SaveBasket from "../basket/savebasket";
+import AddToBasket from "../basket/addtobasket";
 
 const DATETIME_OPTIONS = {
   year: "numeric",
@@ -15,7 +19,7 @@ const DATETIME_OPTIONS = {
   timeZoneName: "short",
 };
 
-Object.isObject = function (obj) {
+Object.isObject = function(obj) {
   return (obj && obj.constructor === this) || false;
 };
 
@@ -84,10 +88,30 @@ function newPageCallback(setPage) {
   };
 }
 
+function projectBasketItem(projectId, category){
+  return {
+    archive: "zooniverse",
+    catalog: "project",
+    project_id: projectId,
+    category: category
+  };
+}
+
+function workflowBasketItem(projectId, workflowId, category){
+  return {
+    archive: "zooniverse",
+    catalog: "workflow",
+    project_id: projectId,
+    workflow_id: workflowId,
+    category: category
+  };
+}
+
+
 function ZooniverseProjectResults(context) {
   const { queryMap, page, setPage } = context;
   const date_formatter = new Intl.DateTimeFormat("default", DATETIME_OPTIONS);
-  const result = queryMap.get("zooniverse_projects").results.query_results[0];
+  const result = queryMap.get("zooniverse_projects").results.results[0];
   const numPages = result.pages;
   const mandatory_fields = [
     "launch_date",
@@ -114,70 +138,81 @@ function ZooniverseProjectResults(context) {
         numAdjacent={3}
         numPages={numPages}
       />
-      <Table className="mt-3" responsive>
-        <thead>
-          <tr className="bg-light">
-            {/* <th>
+      <Form>
+        <SaveBasket />
+        <Table className="mt-3" responsive>
+          <thead>
+            <tr className="bg-light">
+              {/* <th>
               <InputGroup>
                 <InputGroup.Checkbox />
               </InputGroup>
             </th> */}
-            <th>ID</th>
-            <th>Display Name</th>
-            <th>Created</th>
-            <th>Updated</th>
-            <th>Launched</th>
-            <th>Live</th>
-            <th>View</th>
-            {remaining_headers}
-          </tr>
-        </thead>
-        <tbody>
-          {queryMap
-            .get("zooniverse_projects")
-            .results.query_results.map((result) => {
-              const launch_date = result.launch_date
-                ? date_formatter.format(new Date(result.launch_date))
-                : "Not Launched";
-              const created_at = date_formatter.format(
-                new Date(result.created_at)
-              );
-              const updated_at = date_formatter.format(
-                new Date(result.updated_at)
-              );
-              const live = result.live ? "Yes" : "No";
-              const remaining_cells = remaining_fields.map((field) => {
-                const reactKey = `project_${result.project_id}_${field}`;
-                return (
-                  <td key={reactKey}>
-                    {renderIfCompound(result[field], reactKey)}
-                  </td>
+              <th>Select Classification Data</th>
+              <th>Select Subject Data</th>
+              <th>ID</th>
+              <th>Display Name</th>
+              <th>Created</th>
+              <th>Updated</th>
+              <th>Launched</th>
+              <th>Live</th>
+              <th>View</th>
+              {remaining_headers}
+            </tr>
+          </thead>
+          <tbody>
+            {queryMap
+              .get("zooniverse_projects")
+              .results.results.map((result) => {
+                const launch_date = result.launch_date
+                  ? date_formatter.format(new Date(result.launch_date))
+                  : "Not Launched";
+                const created_at = date_formatter.format(
+                  new Date(result.created_at)
+                );
+                const updated_at = date_formatter.format(
+                  new Date(result.updated_at)
                 );
-              });
-              return (
-                <tr key={`project_${result.project_id}`}>
-                  {/* <th>
+                const live = result.live ? "Yes" : "No";
+                const remaining_cells = remaining_fields.map((field) => {
+                  const reactKey = `project_${result.project_id}_${field}`;
+                  return (
+                    <td key={reactKey}>
+                      {renderIfCompound(result[field], reactKey)}
+                    </td>
+                  );
+                });
+                return (
+                  <tr key={`project_${result.project_id}`}>
+                    {/* <th>
                   <InputGroup>
                     <InputGroup.Checkbox />
                   </InputGroup>
                 </th> */}
-                  <td>{result.project_id}</td>
-                  <td>{result.display_name}</td>
-                  <td>{created_at}</td>
-                  <td>{updated_at}</td>
-                  <td>{launch_date}</td>
-                  <td>{live}</td>
-                  <td>
-                    <a href={`https://zooniverse.org/projects/${result.slug}`}>
-                      Link
+                    <td>
+                      <AddToBasket id={`selectClassifications_${result.project_id}`}  item={projectBasketItem(result.project_id, "classifications")} />
+                    </td>
+                    <td>
+                      <AddToBasket id={`selectSubjects_${result.project_id}`}  item={projectBasketItem(result.project_id, "subjects")} />
+                    </td>
+                    <td>{result.project_id}</td>
+                    <td>{result.display_name}</td>
+                    <td>{created_at}</td>
+                    <td>{updated_at}</td>
+                    <td>{launch_date}</td>
+                    <td>{live}</td>
+                    <td>
+                      <a href={`https://zooniverse.org/projects/${result.slug}`}>
+                        Link
                     </a>
-                  </td>
-                  {remaining_cells}
-                </tr>
-              );
-            })}
-        </tbody>
-      </Table>
+                    </td>
+                    {remaining_cells}
+                  </tr>
+                );
+              })}
+          </tbody>
+        </Table>
+      </Form>
       <Paginate
         getNewPage={newPageCallback(setPage)}
         currentPage={page}
@@ -191,7 +226,7 @@ function ZooniverseProjectResults(context) {
 function ZooniverseWorkflowResults(context) {
   const { queryMap, page, setPage } = context;
   let date_formatter = new Intl.DateTimeFormat("default", DATETIME_OPTIONS);
-  let result = queryMap.get("zooniverse_workflows").results.query_results[0];
+  let result = queryMap.get("zooniverse_workflows").results.results[0];
   let result_workflow = result.workflows[0];
   const numPages = result.pages;
   let mandatory_fields = [
@@ -208,6 +243,7 @@ function ZooniverseWorkflowResults(context) {
     let title = titleCase(field.replace("_", " "));
     return <th key={`project_header_${field}`}>{title}</th>;
   });
+  const saveBasketStyle = { marginBottom : "10px"} ;
   return (
     <>
       <Paginate
@@ -216,9 +252,11 @@ function ZooniverseWorkflowResults(context) {
         numAdjacent={3}
         numPages={numPages}
       />
+      <Form>
+      <SaveBasket style={saveBasketStyle} />
       {queryMap
         .get("zooniverse_workflows")
-        .results.query_results.map((project) => {
+        .results.results.map((project) => {
           return (
             <div key={project.project_id}>
               <h4>{project.display_name}</h4>
@@ -230,6 +268,8 @@ function ZooniverseWorkflowResults(context) {
                 <InputGroup.Checkbox />
               </InputGroup>
             </th> */}
+                    <th>Select Classification Data</th>
+                    <th>Select Subject Data</th>
                     <th>ID</th>
                     <th>Display Name</th>
                     <th>Created</th>
@@ -261,6 +301,12 @@ function ZooniverseWorkflowResults(context) {
                       <InputGroup.Checkbox />
                     </InputGroup>
                   </th> */}
+                        <td>
+                          <AddToBasket id={`selectClassifications_${workflow.workflow_id}`}  item={workflowBasketItem(result.project_id, workflow.workflow_id, "classifications")} />
+                        </td>
+                        <td>
+                          <AddToBasket id={`selectSubjects_${workflow.workflow_id}`}  item={workflowBasketItem(result.project_id, workflow.workflow_id, "subjects")} />
+                        </td>
                         <td>{workflow.workflow_id}</td>
                         <td>{workflow.display_name}</td>
                         <td>{created_at}</td>
@@ -275,6 +321,7 @@ function ZooniverseWorkflowResults(context) {
             </div>
           );
         })}
+      </Form>
       <Paginate
         getNewPage={newPageCallback(setPage)}
         currentPage={page}
@@ -287,14 +334,17 @@ function ZooniverseWorkflowResults(context) {
 
 export default function ZooniverseResults({ catalog }) {
   const context = useContext(QueryContext);
+  const basketContext = useContext(BasketContext);
   if (!context.queryMap) return null;
   if (context.queryMap.get(catalog).status === "fetched") {
-    if (context.queryMap.get(catalog).results.query_results.length === 0)
+    if (context.queryMap.get(catalog).results.results.length === 0)
       return <Alert variant="warning">No matching results found!</Alert>;
     else if (catalog === "zooniverse_projects") {
-      return ZooniverseProjectResults(context);
+      console.log(`basketContext -> ${basketContext}`);
+      console.log(basketContext);
+      return ZooniverseProjectResults(context, basketContext);
     } else if (catalog === "zooniverse_workflows") {
-      return ZooniverseWorkflowResults(context);
+      return ZooniverseWorkflowResults(context, basketContext);
     } else {
       return <Alert variant="warning">Unrecognised Zooniverse Catalog!</Alert>;
     }
diff --git a/src/contexts/BasketContext.js b/src/contexts/BasketContext.js
index fd948e80ea70b9170e8d7bae68e5505de430d580..35880d0d8d8dcc13a4c7771095486a6e2c17af87 100644
--- a/src/contexts/BasketContext.js
+++ b/src/contexts/BasketContext.js
@@ -1,7 +1,4 @@
 import React, { useState, createContext } from "react";
-import Databasket from "../components/basket/databasket";
-import Addtobasket from "../components/basket/addtobasket";
-import BasketContext from "../contexts/BasketContext";
 
 export const BasketContext = createContext();
 
@@ -18,6 +15,7 @@ export function BasketContextProvider({ children }) {
     copy.splice(index, 1);
     setDatasets(copy);
   }
+
   return (
     <BasketContext.Provider
       value={{ datasets, add: handleAddDataset, remove: handleRemoveDataset }}
diff --git a/src/contexts/GlobalContext.js b/src/contexts/GlobalContext.js
index d8c42dcfbba472643df6364b482f3c14dfd3a148..f76cf0c95d339ceab169d32001f3fa768383f0d9 100644
--- a/src/contexts/GlobalContext.js
+++ b/src/contexts/GlobalContext.js
@@ -1,29 +1,19 @@
 import React, { createContext, useState, useEffect } from "react";
+import { Alert } from "react-bootstrap";
 import axios from "axios";
 import getCookie from "../utils/getCookie";
 
 export const GlobalContext = createContext();
 
 export function GlobalContextProvider({ children }) {
+  
   console.log("ASTRON ESAP version ", Date());
   const api_host =
     process.env.NODE_ENV === "development"
-      ? "http://sdc.astron.nl:5555/esap-api/"
+      ? "https://sdc.astron.nl:5555/esap-api/"
       : "/esap-api/";
-
-  const [config, setConfig] = useState();
-  const [configName, setConfigName] = useState("esap_ivoa");
-
-  useEffect(() => {
-    let configNameString = "";
-    if (configName) {
-      configNameString = `?name=${configName}`;
-    }
-    axios
-      .get(api_host + "query/configuration" + configNameString)
-      .then((response) => setConfig(response.data["configuration"]));
-  }, [api_host, configName]);
-  console.log("config: ", { config });
+  // "https://sdc.astron.nl:5555/esap-api/"
+  // "http://localhost:5555/esap-api/"
 
   const [archives, setArchives] = useState();
   useEffect(() => {
@@ -32,6 +22,7 @@ export function GlobalContextProvider({ children }) {
       .then((response) => setArchives(response.data.results));
   }, [api_host]);
 
+  // !!!!! Still need to look at sessionid and stuff
   const [sessionid, setSessionid] = useState(getCookie("sessionid"));
   console.log("waah", sessionid, getCookie("sessionid"), document.cookie);
   const [isAuthenticated, setIsAuthenticated] = useState(
@@ -52,17 +43,29 @@ export function GlobalContextProvider({ children }) {
     return null;
   };
 
+  const handleError = (event) => {
+    setIsAuthenticated(false);
+    setSessionid(null);
+
+    return (
+      <>
+      <Alert variant="warning">An error has occurred during login!</Alert>
+      <Alert variant="warning">{event.staticContext}</Alert>
+      </>
+    );
+  };
+  
+
   return (
     <GlobalContext.Provider
       value={{
         api_host,
         isAuthenticated,
         sessionid,
-        config,
         archives,
         handleLogin,
         handleLogout,
-        setConfigName,
+        handleError,
       }}
     >
       {children}
diff --git a/src/contexts/IVOAContext.js b/src/contexts/IVOAContext.js
index a5363958e05f9505b8046e3577721360e5c4b50d..e3a755312e9a4905448677479f54ea5cbb3a7993 100644
--- a/src/contexts/IVOAContext.js
+++ b/src/contexts/IVOAContext.js
@@ -1,5 +1,4 @@
 import React, { createContext, useState } from "react";
-import useMap from "../hooks/useMap";
 
 export const IVOAContext = createContext();
 
@@ -7,6 +6,8 @@ export function IVOAContextProvider({ children }) {
   const [registryList, setRegistryList] = useState([]);
   const [selectedRegistry, setSelectedRegistry] = useState([]);
   const [queryStep, setQueryStep] = useState("get-services");
+  const [regPage, setRegPage] = useState(1);
+
   /* 
     IVOA query steps:
     1. get-services
@@ -40,6 +41,8 @@ export function IVOAContextProvider({ children }) {
         selectedRegistry,
         addRegistry: handleAddRegistry,
         removeRegistry: handleRemoveRegistry,
+        regPage,
+        setRegPage,
         registryList,
         setRegistryList,
         queryStep,
diff --git a/src/contexts/QueryContext.js b/src/contexts/QueryContext.js
index e0ad5419511ddddacc8a575a820f7ae199e5a56e..f9a37e027eb697ed67688040c6fff206ed7a4018 100644
--- a/src/contexts/QueryContext.js
+++ b/src/contexts/QueryContext.js
@@ -1,12 +1,53 @@
-import React, { createContext, useState } from "react";
+import React, { createContext, useState, useEffect, useContext } from "react";
+import axios from "axios";
 import useMap from "../hooks/useMap";
+import { GlobalContext } from "./GlobalContext";
 
 export const QueryContext = createContext();
 
 export function QueryContextProvider({ children }) {
+  const defaultConf = "esap_ivoa";
   const queryMap = useMap();
   const [formData, setFormData] = useState();
   const [page, setPage] = useState(1);
+  const [url, setURL] = useState("https://uilennest.net/astrobase/data/191231001/3836665.fits");
+  const [dplevel, setDPLevel] = useState();
+  const [collection, setCollection] = useState();
+  const [config, setConfig] = useState();
+  const [configName, setConfigName] = useState(defaultConf);
+  const { api_host } = useContext(GlobalContext);
+  const [preview, setPreview] = useState(false);
+  const [ds9, setDS9] = useState(false);
+
+  useEffect(() => {
+    let configNameString = "";
+    if (configName) {
+      configNameString = `?name=${configName}`;
+    }
+    axios
+      .get(api_host + "query/configuration" + configNameString)
+      .then((response) => {
+        let config = response.data["configuration"];
+        let props = config.query_schema.properties;
+        console.log("config props: ", props);
+        console.log("collection value: ", collection);
+        console.log("dplevel value: ", dplevel);
+        Object.keys(props).map((key) => {
+          if (key === "collection" && collection) {
+            console.log("has key collection, default value is: ", props[key]["default"]);
+            props[key]["default"] = collection;
+          }
+          if (key === "level" && dplevel) {
+            console.log("has key dplevel, default value is: ", props[key]["default"]);
+            props[key]["default"] = dplevel;
+          }
+          return null;
+        });
+        setConfig(config);
+      });
+  }, [api_host, configName, dplevel, collection]);
+  console.log("config: ", { config });
+
   return (
     <QueryContext.Provider
       value={{
@@ -15,6 +56,19 @@ export function QueryContextProvider({ children }) {
         queryMap,
         formData,
         setFormData,
+        url,
+        setURL,
+        dplevel,
+        setDPLevel,
+        collection,
+        setCollection,
+        config,
+        setConfigName,
+        defaultConf,
+        ds9,
+        setDS9,
+        preview,
+        setPreview,
       }}
     >
       {children}
diff --git a/src/routes/Routes.js b/src/routes/Routes.js
index cc4098e741edcc92f1ea27b75432113034c25f56..b70b60d98bdb5dad03f40c9bcaa7260bd923fcce 100644
--- a/src/routes/Routes.js
+++ b/src/routes/Routes.js
@@ -7,32 +7,23 @@ import QueryCatalogs from "../components/query/QueryCatalogs";
 import QueryIVOARegistry from "../components/query/QueryIVOARegistry";
 import { BrowserRouter as Router } from "react-router-dom";
 import NavBar from "../components/NavBar";
-import { QueryContextProvider } from "../contexts/QueryContext";
+import { QueryContext } from "../contexts/QueryContext";
 import Rucio from "../components/Rucio";
 import Interactive from "../components/Interactive";
 import { IVOAContextProvider } from "../contexts/IVOAContext";
 
 export default function Routes() {
-  const { config, handleLogin, handleLogout } = useContext(GlobalContext);
+  const { handleLogin, handleLogout, handleError } = useContext(GlobalContext);
+  const { config } = useContext(QueryContext);
   if (!config) return null;
 
   return (
     <Router basename={config.frontend_basename}>
       <NavBar />
       <Switch>
-        <Route exact path="/">
+        <Route exact path={["/", "/archives"]}>
           <Archives />
         </Route>
-        <Route exact path="/archives">
-          <Archives />
-        </Route>
-        <Route exact path="/query">
-          <QueryContextProvider>
-            <IVOAContextProvider>
-              <QueryIVOARegistry />
-            </IVOAContextProvider>
-          </QueryContextProvider>
-        </Route>
         <Route exact path="/rucio">
           <Rucio />
         </Route>
@@ -41,18 +32,15 @@ export default function Routes() {
         </Route>
         <Route exact path="/login" component={handleLogin} />
         <Route exact path="/logout" component={handleLogout} />
+        <Route exact path="/error" component={handleError} />
         <Route exact path="/archives/:uri" component={ArchiveDetails} />
-        <Route exact path="/archives/ivoa/query">
-          <QueryContextProvider>
-            <IVOAContextProvider>
-              <QueryIVOARegistry />
-            </IVOAContextProvider>
-          </QueryContextProvider>
+        <Route exact path={["/vo-query", "/archives/ivoa/query"]}>
+          <IVOAContextProvider>
+            <QueryIVOARegistry />
+          </IVOAContextProvider>
         </Route>
-        <Route exact path="/archives/:uri/query">
-          <QueryContextProvider>
-            <QueryCatalogs />
-          </QueryContextProvider>
+        <Route exact path={["/adex-query", "/archives/:uri/query"]}>
+          <QueryCatalogs />
         </Route>
       </Switch>
     </Router>
diff --git a/src/utils/form/parseADEXForm.js b/src/utils/form/parseADEXForm.js
index 351fabef237b4d6f60208855092efa1e64e4060b..75f134d0e1ae7407460128178484854c52e4ae1d 100644
--- a/src/utils/form/parseADEXForm.js
+++ b/src/utils/form/parseADEXForm.js
@@ -1,5 +1,5 @@
-export default function ParseADEXForm(formData) {
-  let catalogs = ["apertif", "astron_vo"];
+export default function ParseADEXForm(formData, page) {
+  let catalogs = ["apertif", "astron_vo", "lofar"];
   let queries = [];
   // queries is an array of dictionaries, where each dictionary consists of
   // {"catalog": "catalogname",
@@ -20,10 +20,14 @@ export default function ParseADEXForm(formData) {
   //  "status": "null|fetching|fetched",
   //  "results": null}
   let catalog = formInput.find(([key]) => key === "catalog")[1];
-  if (catalog === "all") {
+  if (catalog === "adex") {
     console.log("Catalogs:", catalogs);
     catalogs.map((catalog) => {
-      let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+      let esapquery =
+        query +
+        `${`${query}` ? "&" : ""}archive_uri=` +
+        catalog +
+        "&page_size=20";
 
       queries.push({
         catalog: catalog,
@@ -32,7 +36,11 @@ export default function ParseADEXForm(formData) {
       return null;
     });
   } else {
-    let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+    let esapquery =
+      query +
+      `${`${query}` ? "&" : ""}archive_uri=` +
+      catalog +
+      `&page_size=30&page=${page}`;
 
     queries.push({
       catalog: catalog,
diff --git a/src/utils/form/parseASTRONVOForm.js b/src/utils/form/parseASTRONVOForm.js
index 9162c828a9635cabe750e5dbbcccfd933dc8ea4c..6406cf850f4d9ce0453210e69e1bef7cb9ff5269 100644
--- a/src/utils/form/parseASTRONVOForm.js
+++ b/src/utils/form/parseASTRONVOForm.js
@@ -1,4 +1,4 @@
-export default function ParseASTRONVOForm(formData) {
+export default function ParseASTRONVOForm(formData, page) {
   let queries = [];
   // queries is an array of dictionaries, where each dictionary consists of
   // {"catalog": "catalogname",
@@ -19,7 +19,9 @@ export default function ParseASTRONVOForm(formData) {
   //  "status": "null|fetching|fetched",
   //  "results": null}
   let catalog = formInput.find(([key]) => key === "catalog")[1];
-  let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+  let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog; //+ `&page=${page}`
+  // testing api with page=1, failing at the backend at the moment
+  page === 1 ? console.log("Page number is 1") : (esapquery += `&page=${page}`);
   queries.push({
     catalog: catalog,
     esapquery: esapquery,
diff --git a/src/utils/form/parseApertifForm.js b/src/utils/form/parseApertifForm.js
index 4a764050acb24deea951cb6778e8e023e62364c6..6aab904362942e15d814bdf12d9ca3f12d7b244e 100644
--- a/src/utils/form/parseApertifForm.js
+++ b/src/utils/form/parseApertifForm.js
@@ -1,4 +1,4 @@
-export default function ParseApertifForm(formData) {
+export default function ParseApertifForm(formData, page) {
   let queries = [];
   // queries is an array of dictionaries, where each dictionary consists of
   // {"catalog": "catalogname",
@@ -19,7 +19,8 @@ export default function ParseApertifForm(formData) {
   //  "status": "null|fetching|fetched",
   //  "results": null}
   let catalog = formInput.find(([key]) => key === "catalog")[1];
-  let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+  let esapquery =
+    query + `${`${query}` ? "&" : ""}archive_uri=` + catalog + `&page=${page}`;
   queries.push({
     catalog: catalog,
     esapquery: esapquery,
diff --git a/src/utils/form/parseIVOAForm.js b/src/utils/form/parseIVOAForm.js
index e518ff0ccaf91f1b5730b7f98bdc8fe9df92bef7..2b3fadcf898d051b1ed7b733e549fd25e049fe1b 100644
--- a/src/utils/form/parseIVOAForm.js
+++ b/src/utils/form/parseIVOAForm.js
@@ -1,4 +1,4 @@
-export default function ParseIVOAForm(formData) {
+export default function ParseIVOAForm(formData, page) {
   let queries = [];
   // queries is an array of dictionaries, where each dictionary consists of
   // {"catalog": "catalogname",
@@ -25,7 +25,11 @@ export default function ParseIVOAForm(formData) {
   let service_type = formInput.find(([key]) => key === "service_type")[1];
 
   let esapquery =
-    "get-services/?" + query + `${`${query}` ? "&" : ""}dataset_uri=` + catalog;
+    "get-services/?" +
+    query +
+    `${`${query}` ? "&" : ""}dataset_uri=` +
+    catalog +
+    `&page=${page}`;
 
   queries.push({
     catalog: catalog,
diff --git a/src/utils/form/parseLOFARForm.js b/src/utils/form/parseLOFARForm.js
index badc2b8512cc5c64457384b6e23c3b435f4eb1d8..8f8ff91cf9c6cd1e297449c00b2e41702ed20a51 100644
--- a/src/utils/form/parseLOFARForm.js
+++ b/src/utils/form/parseLOFARForm.js
@@ -1,4 +1,4 @@
-export default function ParseLOFARForm(formData) {
+export default function ParseLOFARForm(formData, page) {
   let queries = [];
   // queries is an array of dictionaries, where each dictionary consists of
   // {"catalog": "catalogname",
@@ -19,7 +19,8 @@ export default function ParseLOFARForm(formData) {
   //  "status": "null|fetching|fetched",
   //  "results": null}
   let catalog = formInput.find(([key]) => key === "catalog")[1];
-  let esapquery = query + `${`${query}` ? "&" : ""}archive_uri=` + catalog;
+  let esapquery =
+    query + `${`${query}` ? "&" : ""}archive_uri=` + catalog + `&page=${page}`;
   queries.push({
     catalog: catalog,
     esapquery: esapquery,
diff --git a/src/utils/form/parseQueryForm.js b/src/utils/form/parseQueryForm.js
index ecf4e15093d67ab8c6142f82e434ee406d4128d9..62d7ec47344ccab0d0631caf302fb3369b441a42 100644
--- a/src/utils/form/parseQueryForm.js
+++ b/src/utils/form/parseQueryForm.js
@@ -4,21 +4,24 @@ import parseLOFARForm from "./parseLOFARForm";
 import parseIVOAForm from "./parseIVOAForm";
 import parseApertifForm from "./parseApertifForm";
 import parseASTRONVOForm from "./parseASTRONVOForm";
+import parseRucioForm from "./parseRucioForm";
 
 export default function parseQueryForm(gui, formData, page) {
   switch (gui) {
     case "adex":
-      return parseADEXForm(formData);
+      return parseADEXForm(formData, page);
     case "zooniverse":
       return parseZooniverseForm(formData, page);
     case "lofar":
-      return parseLOFARForm(formData);
+      return parseLOFARForm(formData, page);
     case "apertif":
-      return parseApertifForm(formData);
+      return parseApertifForm(formData, page);
     case "astron_vo":
-      return parseASTRONVOForm(formData);
+      return parseASTRONVOForm(formData, page);
     case "ivoa":
-      return parseIVOAForm(formData);
+      return parseIVOAForm(formData, page);
+    case "rucio":
+        return parseRucioForm(formData, page);
     default:
       return null;
   }
diff --git a/src/utils/form/parseRucioForm.js b/src/utils/form/parseRucioForm.js
new file mode 100644
index 0000000000000000000000000000000000000000..a0571bb15f2f15432fc230ea49a9d0309eaa281c
--- /dev/null
+++ b/src/utils/form/parseRucioForm.js
@@ -0,0 +1,21 @@
+export default function parseRucioForm(formData, page) {
+  let formInput = Object.entries(formData);
+
+  let query = "";
+
+  for (let [key, value] of formInput) {
+    query += `${`${query}` ? "&" : ""}` + key + "=" + value;
+  }
+
+  let esapquery = [
+    query,
+    "archive_uri=esap_rucio",
+    `catalog=rucio`,
+  ].join("&");
+
+  console.log("Rucio Query", query);
+  return [{
+    catalog: "rucio",
+    esapquery: esapquery + `&page=${page}`
+  }];
+}
diff --git a/src/utils/form/parseVOServiceForm.js b/src/utils/form/parseVOServiceForm.js
index c42aec9a71378c01d5b44ba9d9e675ff0b09abf9..69d411fc81eab9f8780108629e78264c70f23caa 100644
--- a/src/utils/form/parseVOServiceForm.js
+++ b/src/utils/form/parseVOServiceForm.js
@@ -1,4 +1,4 @@
-export default function ParseVOServiceForm(formData, access_url) {
+export default function ParseVOServiceForm(formData, access_url, page) {
   let queries = [];
   // queries is an array of dictionaries, where each dictionary consists of
   // {"catalog": "catalogname",
@@ -17,7 +17,7 @@ export default function ParseVOServiceForm(formData, access_url) {
       query += `${`${query}` ? "&" : ""}` + key + "=" + value;
     }
   }
-  query += `${`${query}` ? "&" : ""}` + "access_url=" + access_url;
+  query += `${`${query}` ? "&" : ""}access_url=${access_url}`;
 
   console.log("Query:", query);
   // If catalog is set to "all", query for each catalog needs to be generated
@@ -29,7 +29,11 @@ export default function ParseVOServiceForm(formData, access_url) {
   let service_type = formInput.find(([key]) => key === "service_type")[1];
 
   let esapquery =
-    "query/?" + query + `${`${query}` ? "&" : ""}dataset_uri=` + catalog;
+    "query/?" +
+    query +
+    `${`${query}` ? "&" : ""}dataset_uri=` +
+    catalog +
+    `&page=${page}`;
 
   queries.push({
     catalog: access_url,