diff --git a/api.py b/api.py
index 40ce757f5a8d8b7b4a92451bcc50cd7a8bd35e2e..b380dff26560daed665aed28171e57d4d0fc11a4 100644
--- a/api.py
+++ b/api.py
@@ -18,7 +18,7 @@ from picview.database import (
     UserData,
     PictureData,
     AlbumData,
-    Share,
+    SharedAlbumData,
 )
 from picview.utils import create_access_token
 
@@ -210,17 +210,17 @@ async def get_picture_file(
     return {}
 
 
-@app.get("/shares", response_model=list[Share], tags=["shares"])
+@app.get("/shares", response_model=list[SharedAlbumData], tags=["shares"])
 async def get_shares(
     current_user: Annotated[User, Depends(get_current_user)],
-) -> list[Share]:
+) -> list[SharedAlbumData]:
 
     database = Database(config)
     return database.get_shares(current_user)
 
 
-@app.get("/shares/{secret}", response_model=Share | None, tags=["shares"])
-async def get_share(secret: str) -> Share | None:
+@app.get("/shares/{secret}", response_model=SharedAlbumData | None, tags=["shares"])
+async def get_share(secret: str) -> SharedAlbumData | None:
     database = Database(config)
     return database.get_share(secret)
 
diff --git a/picview/database.py b/picview/database.py
index 8fce3795b88923ca063f8e13d158f7d51c753577..a3c7897f70a7dc22b114a2ddbb6909cf8d72c394 100644
--- a/picview/database.py
+++ b/picview/database.py
@@ -58,6 +58,17 @@ class AlbumData(BaseModel):
     tags: list[TagData]
 
 
+class SharedAlbumData(BaseModel):
+    id: int | None
+    name: str
+    desc: str
+    begin: datetime
+    end: datetime
+    tags: list[TagData]
+    expiration_date: datetime
+    secret: str
+
+
 class UserData(BaseModel):
     login: str
 
@@ -199,17 +210,42 @@ class Database:
         )
         return self.session.exec(query).first()
 
-    def get_shares(self, user: User) -> list[Share]:
-
-        query = select(Share).join(Album).where(Album.user == user.id)
-
-        shares = self.session.exec(query).all()
-        return list(shares)
-
-    def get_share(self, secret: str) -> Share | None:
-        query = select(Share).join(Album).where(Share.secret == secret)
-        share = self.session.exec(query).first()
-        return share
+    def get_shares(self, user: User) -> list[SharedAlbumData]:
+
+        query = select(Share, Album).join(Album).where(Album.user == user.id)
+
+        shares_albums = self.session.exec(query).all()
+        result = []
+        for share, album in shares_albums:
+            result.append(
+                SharedAlbumData(
+                    id=album.id,
+                    name=album.name,
+                    desc=album.desc,
+                    begin=album.begin,
+                    end=album.end,
+                    tags=[TagData(label=t.label, color=t.color) for t in album.tags],
+                    expiration_date=share.expiration_date,
+                    secret=share.secret,
+                )
+            )
+        return result
+
+    def get_share(self, secret: str) -> SharedAlbumData | None:
+        query = select(Share, Album).join(Album).where(Share.secret == secret)
+        share_album = self.session.exec(query).first()
+        if share_album:
+            share, album = share_album
+            return SharedAlbumData(
+                id=album.id,
+                name=album.name,
+                desc=album.desc,
+                begin=album.begin,
+                end=album.end,
+                tags=[TagData(label=t.label, color=t.color) for t in album.tags],
+                expiration_date=share.expiration_date,
+                secret=share.secret,
+            )
 
     def get_share_pictures(self, share_secret: str) -> list[Picture]:
 
diff --git a/src/App.jsx b/src/App.jsx
index c04555808d6934fb6c8e67521d9f449c33109700..c04fe10e8ca4db0ef0fd886b28a3f00417f4e3ce 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -19,6 +19,7 @@ import Album from "./routes/Album";
 import Albums from "./routes/Albums";
 import Login from "./routes/Login";
 import Main from "./routes/Main";
+import Share from "./routes/Share";
 
 // components
 import NavBar from "./components/Navbar";
@@ -41,6 +42,7 @@ export default function App() {
             <NavBar />
             <Routes>
               <Route path="/login" element={<Login />} />
+              <Route path="/shares/:shareId" element={<Share />} />
               <Route element={<RequireAuth />}>
                 <Route path="/" element={<Main />} />
                 <Route path="/albums" element={<Albums />} />
diff --git a/src/components/Album.jsx b/src/components/Album.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..3273886dc5900930987d5f9c5d6fd3e44298dbbb
--- /dev/null
+++ b/src/components/Album.jsx
@@ -0,0 +1,93 @@
+import Box from "@mui/material/Box";
+import Typography from "@mui/material/Typography";
+import { useEffect, useState } from "react";
+
+import FullScreenPicture from "../components/FullScreenPicture";
+import PictureList from "../components/PictureList";
+import { blobUrlMapping } from "../components/Thumbnail";
+import { getScreenSize } from "../functions/utils";
+
+export default function Album({ album, pictures }) {
+  // screen size
+  const [screenSize, setScreenSize] = useState(getScreenSize());
+  const handleResize = () => {
+    setScreenSize(getScreenSize());
+  };
+  useEffect(() => {
+    window.addEventListener("resize", handleResize);
+  });
+
+  const [fullPicture, setFullPicture] = useState([null, null]);
+  const [openFullScreen, setOpenFullScreen] = useState(false);
+  const findPicture = (picId, nextOrPrev) => {
+    const npi = pictures.findIndex((p) => p.id === picId);
+    return pictures[npi + (nextOrPrev === "next" ? 1 : -1)];
+  };
+
+  const nextFullScreenPicture = (picId) => {
+    const nextPic = findPicture(picId, "next");
+    if (nextPic) {
+      setFullPicture([nextPic, blobUrlMapping[nextPic.id]]);
+    } else {
+      setFullPicture([null, null]);
+      setOpenFullScreen(false);
+    }
+  };
+  const prevFullScreenPicture = (picId) => {
+    const prevPic = findPicture(picId, "prev");
+    if (prevPic) {
+      setFullPicture([prevPic, blobUrlMapping[prevPic.id]]);
+    } else {
+      setFullPicture([null, null]);
+      setOpenFullScreen(false);
+    }
+  };
+  const thumbnailObject = {};
+  pictures.forEach((picture) => {
+    const cdate = new Date(picture.cdate);
+    const strDate = `${cdate.getFullYear()}-${String(
+      cdate.getMonth() + 1,
+    ).padStart(2, "0")}-${String(cdate.getDate()).padStart(2, "0")}`;
+    if (thumbnailObject[strDate] === undefined) {
+      thumbnailObject[strDate] = [];
+    }
+    thumbnailObject[strDate].push(picture);
+  });
+  const listOfPictureList = [];
+  Object.entries(thumbnailObject).forEach(([date, pictures]) => {
+    listOfPictureList.push(
+      <PictureList
+        dateStr={date}
+        pictures={pictures}
+        setOpenFullScreen={setOpenFullScreen}
+        setFullPicture={setFullPicture}
+      />,
+    );
+  });
+  const title = album ? (
+    <div>
+      <Typography variant="h3">{album.name}</Typography>
+      <Typography variant="h6" gutterBottom>
+        {album.desc}
+      </Typography>
+      <hr />
+    </div>
+  ) : null;
+
+  return (
+    <>
+      <Box component="section" sx={{ p: screenSize === "small" ? 0 : 2 }}>
+        <FullScreenPicture
+          open={openFullScreen}
+          setOpen={setOpenFullScreen}
+          picture={fullPicture}
+          setPicture={setFullPicture}
+          nextFullScreenPicture={nextFullScreenPicture}
+          prevFullScreenPicture={prevFullScreenPicture}
+        />
+        {title}
+        {listOfPictureList}
+      </Box>
+    </>
+  );
+}
diff --git a/src/components/FullScreenPicture.jsx b/src/components/FullScreenPicture.jsx
index b03db9f9f1b87356ef8925a29d93723e1e20681a..4d71f4c23b88c3c5d0a79a69575bee3205ee239c 100644
--- a/src/components/FullScreenPicture.jsx
+++ b/src/components/FullScreenPicture.jsx
@@ -1,10 +1,11 @@
-import { useCallback, useEffect, useState } from "react";
+import { useCallback, useContext, useEffect, useState } from "react";
 import ReactTouchEvents from "react-touch-events";
 
 import Dialog from "@mui/material/Dialog";
 
-import { fetchPicture } from "../functions/api";
+import { fetchPicture, fetchSharePicture } from "../functions/api";
 
+import { AlbumContext } from "../context/AlbumTypeContext";
 import { useUser } from "../context/UserContext";
 
 export default function FullScreenPicture({
@@ -18,6 +19,8 @@ export default function FullScreenPicture({
   const { token } = useUser();
   const [hugeBlobUrl, setHugeBlobUrl] = useState([null, null]);
 
+  const albumContext = useContext(AlbumContext);
+
   useEffect(() => {
     if (picture[1]) {
       setHugeBlobUrl([picture[1], false]);
@@ -53,12 +56,15 @@ export default function FullScreenPicture({
     const controller = new AbortController();
     if (picture[0]) {
       const fetchData = async () => {
-        const responseData = await fetchPicture(
-          token,
-          picture[0].id,
-          false,
-          controller,
-        );
+        const responseData =
+          albumContext.type === "share"
+            ? await fetchSharePicture(
+                albumContext.secret,
+                picture[0].id,
+                false,
+                controller,
+              )
+            : await fetchPicture(token, picture[0].id, false, controller);
         if (responseData) {
           setHugeBlobUrl([URL.createObjectURL(responseData), true]);
         }
diff --git a/src/components/Thumbnail.jsx b/src/components/Thumbnail.jsx
index 3404674d702101d4402b1e295726f2fae1435987..e79803b13cf0d76d9def7d9f75e13ea9e298181e 100644
--- a/src/components/Thumbnail.jsx
+++ b/src/components/Thumbnail.jsx
@@ -4,14 +4,15 @@ import Card from "@mui/material/Card";
 import IconButton from "@mui/material/IconButton";
 import ImageListItem from "@mui/material/ImageListItem";
 import ImageListItemBar from "@mui/material/ImageListItemBar";
-import { useEffect, useState } from "react";
+import { useContext, useEffect, useState } from "react";
 
 import PictureInfoModal from "./PictureInfoModal";
 
 import { getScreenSize } from "../functions/utils";
 
-import { fetchPicture } from "../functions/api";
+import { fetchPicture, fetchSharePicture } from "../functions/api";
 
+import { AlbumContext } from "../context/AlbumTypeContext";
 import { useUser } from "../context/UserContext";
 
 export let instancesCount = 0;
@@ -28,6 +29,8 @@ export default function Thumbnail({
   const [opacity, setOpacity] = useState(0);
   const [openModal, setOpenModal] = useState(false);
 
+  const albumContext = useContext(AlbumContext);
+
   const [screenSize, setScreenSize] = useState(getScreenSize());
   const handleResize = () => {
     setScreenSize(getScreenSize());
@@ -45,7 +48,10 @@ export default function Thumbnail({
 
   useEffect(() => {
     const fetchData = async () => {
-      const responseData = await fetchPicture(token, picture.id, true);
+      const responseData =
+        albumContext.type === "share"
+          ? await fetchSharePicture(albumContext.secret, picture.id, true)
+          : await fetchPicture(token, picture.id, true);
       setBlobUrl(URL.createObjectURL(responseData));
       blobUrlMapping[picture.id] = URL.createObjectURL(responseData);
       setLoading(false);
diff --git a/src/context/AlbumTypeContext.js b/src/context/AlbumTypeContext.js
new file mode 100644
index 0000000000000000000000000000000000000000..0baaada5941b0248ba54af9904eaafaa7aacb484
--- /dev/null
+++ b/src/context/AlbumTypeContext.js
@@ -0,0 +1,3 @@
+import { createContext } from "react";
+
+export const AlbumContext = createContext({ type: "album", secret: null });
diff --git a/src/functions/api.js b/src/functions/api.js
index f3f3e8ecbc9f7b4a99d272490b21258e7b994fd1..6349e79b101076b2eb95596fe357ddbf1fdfe9e4 100644
--- a/src/functions/api.js
+++ b/src/functions/api.js
@@ -61,13 +61,21 @@ export const fetchAlbums = async (token) => {
 };
 
 export const fetchAlbum = async (token, albumId) => {
-  return await apiRequest(`/album/${albumId}`, getHeaders(token));
+  return await apiRequest(`/albums/${albumId}`, getHeaders(token));
 };
 
 export const fetchAlbumPictures = async (token, albumId) => {
   return await apiRequest(`/albums/pictures/${albumId}`, getHeaders(token));
 };
 
+export const fetchShare = async (shareId) => {
+  return await apiRequest(`/shares/${shareId}`);
+};
+
+export const fetchSharePictures = async (shareId) => {
+  return await apiRequest(`/shares/pictures/${shareId}`);
+};
+
 export const fetchPicture = async (
   token,
   pictureId,
@@ -88,6 +96,26 @@ export const fetchPicture = async (
   );
 };
 
+export const fetchSharePicture = async (
+  shareId,
+  pictureId,
+  thumbnail = false,
+  controller = null,
+) => {
+  return await apiRequest(
+    `/shares/pictures/file/${shareId}/${pictureId}?thumbnail=${thumbnail}`,
+    getHeaders(),
+    "GET",
+    null,
+    {
+      accept: "*/*",
+      responseType: "blob",
+      signal: controller ? controller.signal : null,
+    },
+    true,
+  );
+};
+
 export const fetchToken = async (login, password) => {
   const headers = { "Content-Type": "application/x-www-form-urlencoded" };
   const dataStr = `grant_type=password&username=${login}&password=${password}&scope=&client_id=string&client_secret=string`;
diff --git a/src/routes/Album.jsx b/src/routes/Album.jsx
index 87f2dd59cc8588f56133feb30b14463ab9b7293e..75d3e3fe6fa8ccf757ad7c3a320a32ac3d19c8e3 100644
--- a/src/routes/Album.jsx
+++ b/src/routes/Album.jsx
@@ -1,15 +1,11 @@
 import { useEffect, useState } from "react";
 import { useParams } from "react-router";
 
-import Box from "@mui/material/Box";
-import Typography from "@mui/material/Typography";
+import { default as AlbumComponent } from "../components/Album";
 
-import FullScreenPicture from "../components/FullScreenPicture";
-import PictureList from "../components/PictureList";
-import { blobUrlMapping } from "../components/Thumbnail";
 import { fetchAlbum, fetchAlbumPictures } from "../functions/api";
-import { getScreenSize } from "../functions/utils";
 
+import { AlbumContext } from "../context/AlbumTypeContext";
 import { useUser } from "../context/UserContext";
 
 export default function Album() {
@@ -19,40 +15,6 @@ export default function Album() {
 
   const { token } = useUser();
 
-  // screen size
-  const [screenSize, setScreenSize] = useState(getScreenSize());
-  const handleResize = () => {
-    setScreenSize(getScreenSize());
-  };
-  useEffect(() => {
-    window.addEventListener("resize", handleResize);
-  });
-
-  const [fullPicture, setFullPicture] = useState([null, null]);
-  const [openFullScreen, setOpenFullScreen] = useState(false);
-  const findPicture = (picId, nextOrPrev) => {
-    const npi = pictures.findIndex((p) => p.id === picId);
-    return pictures[npi + (nextOrPrev === "next" ? 1 : -1)];
-  };
-  const nextFullScreenPicture = (picId) => {
-    const nextPic = findPicture(picId, "next");
-    if (nextPic) {
-      setFullPicture([nextPic, blobUrlMapping[nextPic.id]]);
-    } else {
-      setFullPicture([null, null]);
-      setOpenFullScreen(false);
-    }
-  };
-  const prevFullScreenPicture = (picId) => {
-    const prevPic = findPicture(picId, "prev");
-    if (prevPic) {
-      setFullPicture([prevPic, blobUrlMapping[prevPic.id]]);
-    } else {
-      setFullPicture([null, null]);
-      setOpenFullScreen(false);
-    }
-  };
-
   useEffect(() => {
     const fetchData = async () => {
       const responseData = await fetchAlbum(token, albumId);
@@ -69,52 +31,9 @@ export default function Album() {
     fetchData();
   }, [album]);
 
-  const thumbnailObject = {};
-  pictures.forEach((picture) => {
-    const cdate = new Date(picture.cdate);
-    const strDate = `${cdate.getFullYear()}-${String(
-      cdate.getMonth() + 1,
-    ).padStart(2, "0")}-${String(cdate.getDate()).padStart(2, "0")}`;
-    if (thumbnailObject[strDate] === undefined) {
-      thumbnailObject[strDate] = [];
-    }
-    thumbnailObject[strDate].push(picture);
-  });
-  const listOfPictureList = [];
-  Object.entries(thumbnailObject).forEach(([date, pictures]) => {
-    listOfPictureList.push(
-      <PictureList
-        dateStr={date}
-        pictures={pictures}
-        setOpenFullScreen={setOpenFullScreen}
-        setFullPicture={setFullPicture}
-      />,
-    );
-  });
-  const title = album ? (
-    <div>
-      <Typography variant="h3">{album.name}</Typography>
-      <Typography variant="h6" gutterBottom>
-        {album.desc}
-      </Typography>
-      <hr />
-    </div>
-  ) : null;
-
   return (
-    <>
-      <Box component="section" sx={{ p: screenSize === "small" ? 0 : 2 }}>
-        <FullScreenPicture
-          open={openFullScreen}
-          setOpen={setOpenFullScreen}
-          picture={fullPicture}
-          setPicture={setFullPicture}
-          nextFullScreenPicture={nextFullScreenPicture}
-          prevFullScreenPicture={prevFullScreenPicture}
-        />
-        {title}
-        {listOfPictureList}
-      </Box>
-    </>
+    <AlbumContext.Provider value={{ type: "album" }}>
+      <AlbumComponent album={album} pictures={pictures} />
+    </AlbumContext.Provider>
   );
 }
diff --git a/src/routes/Share.jsx b/src/routes/Share.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..d83d571c24dd49dc2e5ae0bd000098c4936842c9
--- /dev/null
+++ b/src/routes/Share.jsx
@@ -0,0 +1,36 @@
+import { useEffect, useState } from "react";
+import { useParams } from "react-router";
+
+import { default as AlbumComponent } from "../components/Album";
+
+import { fetchShare, fetchSharePictures } from "../functions/api";
+
+import { AlbumContext } from "../context/AlbumTypeContext";
+
+export default function Share() {
+  const { shareId } = useParams();
+  const [share, setShare] = useState(null);
+  const [pictures, setPictures] = useState([]);
+
+  useEffect(() => {
+    const fetchData = async () => {
+      const responseData = await fetchShare(shareId);
+      setShare(responseData);
+    };
+    fetchData();
+  }, []);
+
+  useEffect(() => {
+    const fetchData = async () => {
+      const responseData = await fetchSharePictures(shareId);
+      setPictures(responseData);
+    };
+    fetchData();
+  }, [share]);
+
+  return (
+    <AlbumContext.Provider value={{ type: "share", secret: shareId }}>
+      <AlbumComponent album={share} pictures={pictures} />
+    </AlbumContext.Provider>
+  );
+}