diff --git a/src/routes/g/+page.svelte b/src/routes/g/+page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/.gallery b/src/routes/g/.gallery
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/[slug]/[[timestamp]]/+page.js b/src/routes/g/[slug]/[[timestamp]]/+page.js
new file mode 100644
index 0000000..68a532e
--- /dev/null
+++ b/src/routes/g/[slug]/[[timestamp]]/+page.js
@@ -0,0 +1,16 @@
+import { error } from '@sveltejs/kit';
+import albums from '$lib/albums.json';
+
+/** @type {import('./$types').PageLoad} */
+export function load({ params }) {
+ const album = albums.find((album) => album.slug === params.slug);
+ if (album) {
+ return {
+ title: album.title,
+ content: album.description,
+ image: '/s/lga/?i=LFB04128-Enhanced-NR.jpg'
+ };
+ }
+
+ throw error(404, 'Not found');
+}
diff --git a/src/routes/g/[slug]/[[timestamp]]/+page.svelte b/src/routes/g/[slug]/[[timestamp]]/+page.svelte
new file mode 100644
index 0000000..0aad292
--- /dev/null
+++ b/src/routes/g/[slug]/[[timestamp]]/+page.svelte
@@ -0,0 +1,8 @@
+
+
+
{data.title}
+
{@html data.content}
+
diff --git a/src/routes/g/[slug]/[[timestamp]]/.album b/src/routes/g/[slug]/[[timestamp]]/.album
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/[slug]/[[timestamp]]/d/+server.js b/src/routes/g/[slug]/[[timestamp]]/d/+server.js
new file mode 100644
index 0000000..56529e6
--- /dev/null
+++ b/src/routes/g/[slug]/[[timestamp]]/d/+server.js
@@ -0,0 +1,17 @@
+import { error } from '@sveltejs/kit';
+
+/** @type {import('./$types').RequestHandler} */
+export function GET({ url }) {
+ const min = Number(url.searchParams.get('min') ?? '0');
+ const max = Number(url.searchParams.get('max') ?? '1');
+
+ const d = max - min;
+
+ if (isNaN(d) || d < 0) {
+ throw error(400, 'min and max must be numbers, and min must be less than max');
+ }
+
+ const random = min + Math.random() * d;
+
+ return new Response(String(random));
+}
diff --git a/src/routes/g/[slug]/[[timestamp]]/d/.download b/src/routes/g/[slug]/[[timestamp]]/d/.download
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/[slug]/[[timestamp]]/i/[item]/+page.js b/src/routes/g/[slug]/[[timestamp]]/i/[item]/+page.js
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/[slug]/[[timestamp]]/i/[item]/+page.svelte b/src/routes/g/[slug]/[[timestamp]]/i/[item]/+page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/[slug]/[[timestamp]]/i/[item]/.image-frame b/src/routes/g/[slug]/[[timestamp]]/i/[item]/.image-frame
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/[slug]/[[timestamp]]/i/[item]/d/+server.js b/src/routes/g/[slug]/[[timestamp]]/i/[item]/d/+server.js
new file mode 100644
index 0000000..88aad42
--- /dev/null
+++ b/src/routes/g/[slug]/[[timestamp]]/i/[item]/d/+server.js
@@ -0,0 +1,26 @@
+import { error } from '@sveltejs/kit';
+
+/** @type {import('./$types').RequestHandler} */
+export function GET({ url }) {
+ const noAttachment = url.searchParams.has('r');
+
+
+
+ const min = Number(url.searchParams.get('min') ?? '0');
+ const max = Number(url.searchParams.get('max') ?? '1');
+
+ const d = max - min;
+
+ if (isNaN(d) || d < 0) {
+ throw error(400, 'min and max must be numbers, and min must be less than max');
+ }
+
+ const random = min + Math.random() * d;
+
+ return new Response(String(random), {
+ headers: {
+ 'Content-Type': 'text/plain',
+ 'Content-Disposition': noAttachment ? 'inline' : 'attachment'
+ }
+ });
+}
diff --git a/src/routes/g/[slug]/[[timestamp]]/i/[item]/d/.download b/src/routes/g/[slug]/[[timestamp]]/i/[item]/d/.download
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/[slug]/[[timestamp]]/i/[item]/t/+server.js b/src/routes/g/[slug]/[[timestamp]]/i/[item]/t/+server.js
new file mode 100644
index 0000000..56529e6
--- /dev/null
+++ b/src/routes/g/[slug]/[[timestamp]]/i/[item]/t/+server.js
@@ -0,0 +1,17 @@
+import { error } from '@sveltejs/kit';
+
+/** @type {import('./$types').RequestHandler} */
+export function GET({ url }) {
+ const min = Number(url.searchParams.get('min') ?? '0');
+ const max = Number(url.searchParams.get('max') ?? '1');
+
+ const d = max - min;
+
+ if (isNaN(d) || d < 0) {
+ throw error(400, 'min and max must be numbers, and min must be less than max');
+ }
+
+ const random = min + Math.random() * d;
+
+ return new Response(String(random));
+}
diff --git a/src/routes/g/[slug]/[[timestamp]]/i/[item]/t/.thumbnail b/src/routes/g/[slug]/[[timestamp]]/i/[item]/t/.thumbnail
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/g/[slug]/[[timestamp]]/j/+server.js b/src/routes/g/[slug]/[[timestamp]]/j/+server.js
new file mode 100644
index 0000000..88aad42
--- /dev/null
+++ b/src/routes/g/[slug]/[[timestamp]]/j/+server.js
@@ -0,0 +1,26 @@
+import { error } from '@sveltejs/kit';
+
+/** @type {import('./$types').RequestHandler} */
+export function GET({ url }) {
+ const noAttachment = url.searchParams.has('r');
+
+
+
+ const min = Number(url.searchParams.get('min') ?? '0');
+ const max = Number(url.searchParams.get('max') ?? '1');
+
+ const d = max - min;
+
+ if (isNaN(d) || d < 0) {
+ throw error(400, 'min and max must be numbers, and min must be less than max');
+ }
+
+ const random = min + Math.random() * d;
+
+ return new Response(String(random), {
+ headers: {
+ 'Content-Type': 'text/plain',
+ 'Content-Disposition': noAttachment ? 'inline' : 'attachment'
+ }
+ });
+}
diff --git a/src/routes/g/[slug]/[[timestamp]]/j/.json b/src/routes/g/[slug]/[[timestamp]]/j/.json
new file mode 100644
index 0000000..e69de29