diff --git a/src/routes/admin/+layout.svelte b/src/routes/admin/+layout.svelte
new file mode 100644
index 0000000..bc5a4cb
--- /dev/null
+++ b/src/routes/admin/+layout.svelte
@@ -0,0 +1,58 @@
+
+
+
+
+
diff --git a/src/routes/admin/+page.svelte b/src/routes/admin/+page.svelte
index df26030..d02028d 100644
--- a/src/routes/admin/+page.svelte
+++ b/src/routes/admin/+page.svelte
@@ -1 +1,3 @@
Welcome home, Wilson
+
+Upload Photo
diff --git a/src/routes/admin/login/+page.svelte b/src/routes/admin/login/+page.svelte
index 18ff60c..a4b01e5 100644
--- a/src/routes/admin/login/+page.svelte
+++ b/src/routes/admin/login/+page.svelte
@@ -1,11 +1,39 @@
Admin login
-
+
+
+
diff --git a/src/routes/admin/logout/+server.ts b/src/routes/admin/logout/+server.ts
new file mode 100644
index 0000000..b67604e
--- /dev/null
+++ b/src/routes/admin/logout/+server.ts
@@ -0,0 +1,7 @@
+import { CookieAuthentication } from "$lib/blog/auth/CookieAuthentication.js";
+import { redirect, type ServerLoad } from "@sveltejs/kit";
+
+export const GET: ServerLoad = ({ cookies }) => {
+ new CookieAuthentication(cookies).logout();
+ redirect(307, "/");
+};
diff --git a/src/routes/admin/photos/+page.server.ts b/src/routes/admin/photos/+page.server.ts
new file mode 100644
index 0000000..b73c1f8
--- /dev/null
+++ b/src/routes/admin/photos/+page.server.ts
@@ -0,0 +1,47 @@
+import { writeFile } from "node:fs/promises";
+import { Buffer } from "node:buffer";
+import { join } from "node:path";
+
+import { PRIVATE_PHOTO_UPLOAD_DIR } from "$env/static/private";
+import type { Actions, ServerLoad } from "@sveltejs/kit";
+import { randomUUID } from "crypto";
+
+export const load: ServerLoad = async ({ locals }) => {
+ const photos = await locals.prisma.photoPost.findMany({
+ select: {
+ id: true,
+ fileName: true,
+ title: true,
+ description: true,
+ createdAt: true,
+ },
+ });
+ return { photos };
+};
+
+export const actions = {
+ default: async ({ request, locals }) => {
+ const formData = await request.formData();
+ const file = formData.get("file") as File;
+ const title = formData.get("title") as string;
+ const description = formData.get("description") as string;
+
+ const filetype = file.type.split("/")[1];
+ const fileName = `${randomUUID()}.${filetype}`;
+ const fileLocation = join(PRIVATE_PHOTO_UPLOAD_DIR, fileName);
+
+ const fileContentBuffer = await file.arrayBuffer();
+ await writeFile(fileLocation, Buffer.from(fileContentBuffer));
+
+ await locals.prisma.photoPost.create({
+ data: {
+ fileName,
+ title,
+ description,
+ createdAt: new Date(),
+ },
+ });
+
+ return { success: true };
+ },
+} satisfies Actions;
diff --git a/src/routes/admin/photos/+page.svelte b/src/routes/admin/photos/+page.svelte
new file mode 100644
index 0000000..7129fd1
--- /dev/null
+++ b/src/routes/admin/photos/+page.svelte
@@ -0,0 +1,12 @@
+
+
+
diff --git a/src/routes/admin/photos/FeedItem.svelte b/src/routes/admin/photos/FeedItem.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/admin/photos/PhotoFeed.svelte b/src/routes/admin/photos/PhotoFeed.svelte
new file mode 100644
index 0000000..46b4dd5
--- /dev/null
+++ b/src/routes/admin/photos/PhotoFeed.svelte
@@ -0,0 +1,35 @@
+
+
+
+ {#each photos as photo, id}
+ -
+
+ {photo.title}
+
+ {/each}
+
+
+
diff --git a/src/routes/admin/photos/upload/+page.svelte b/src/routes/admin/photos/upload/+page.svelte
new file mode 100644
index 0000000..6ab7c5f
--- /dev/null
+++ b/src/routes/admin/photos/upload/+page.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+