From 8a9c56c3d590f7975e98f68aa034c25d8587dcdd Mon Sep 17 00:00:00 2001 From: lew Date: Sun, 5 Apr 2026 01:04:11 +0100 Subject: [PATCH] flatten monorepo, migrate off Vercel - Remove penfield (split to own repo on Forgejo) - Move www/ contents to root, rename to wynne.rs - Swap @astrojs/vercel for @astrojs/node, upgrade to Astro 6 - Remove auth-astro/GitHub OAuth (TinyAuth at proxy layer) - Remove Vercel deploy webhook - Switch to local SQLite DB (drop Turso) - Update generate-stats.js for new build output paths --- www/.env.example => .env.example | 0 .gitignore | 2 +- www/astro.config.mjs => astro.config.mjs | 7 +- {www/content => content}/bookmarks.yaml | 0 {www/content => content}/hello.md | 0 {www/db => db}/config.ts | 0 db/seed.ts | 14 + package.json | 27 +- penfield/astro.config.mjs | 5 - penfield/package.json | 13 - penfield/src/data/intros.ts | 6 - penfield/src/data/moods.ts | 17 - penfield/src/pages/index.astro | 11 - penfield/vercel.json | 5 - pnpm-workspace.yaml | 3 - {www/public => public}/changelog.txt | 0 {www/public => public}/config.yaml | 0 {www/public => public}/cv.txt | 0 {www/public => public}/js/params.js | 0 {www/public => public}/man.txt | 0 {www/public => public}/now.txt | 0 {www/public => public}/stats.txt | 0 {www/scripts => scripts}/generate-stats.js | 14 +- {www/src => src}/content.config.ts | 0 {www/src => src}/env.d.ts | 0 {www/src => src}/layouts/Layout.astro | 0 {www/src => src}/lib/api.ts | 0 {www/src => src}/lib/consts.ts | 0 {www/src => src}/lib/db.ts | 0 {www/src => src}/lib/format.ts | 0 {www/src => src}/lib/posts.ts | 0 {www/src => src}/lib/rate-limit.ts | 0 {www/src => src}/lib/txt.ts | 0 {www/src => src}/pages/404.astro | 0 {www/src => src}/pages/[slug].astro | 0 {www/src => src}/pages/admin.astro | 26 - {www/src => src}/pages/api/guestbook.ts | 0 {www/src => src}/pages/api/guestbook/[id].ts | 11 +- {www/src => src}/pages/feed.xml.ts | 0 .../src => src}/pages/guestbook-count.json.ts | 0 {www/src => src}/pages/index.astro | 0 {www/src => src}/pages/sitemap.txt.ts | 0 {www/src => src}/plugins/remark-aside.ts | 0 {www/src => src}/scripts/guestbook-sign.ts | 0 {www/src => src}/styles/global.css | 0 www/auth.config.ts | 25 - www/db/seed.ts | 54 - www/package-lock.json | 6861 ----------------- www/package.json | 27 - www/src/lib/auth.ts | 26 - www/src/pages/api/deploy.ts | 18 - www/vercel.json | 8 - 52 files changed, 45 insertions(+), 7135 deletions(-) rename www/.env.example => .env.example (100%) rename www/astro.config.mjs => astro.config.mjs (80%) rename {www/content => content}/bookmarks.yaml (100%) rename {www/content => content}/hello.md (100%) rename {www/db => db}/config.ts (100%) create mode 100644 db/seed.ts delete mode 100644 penfield/astro.config.mjs delete mode 100644 penfield/package.json delete mode 100644 penfield/src/data/intros.ts delete mode 100644 penfield/src/data/moods.ts delete mode 100644 penfield/src/pages/index.astro delete mode 100644 penfield/vercel.json delete mode 100644 pnpm-workspace.yaml rename {www/public => public}/changelog.txt (100%) rename {www/public => public}/config.yaml (100%) rename {www/public => public}/cv.txt (100%) rename {www/public => public}/js/params.js (100%) rename {www/public => public}/man.txt (100%) rename {www/public => public}/now.txt (100%) rename {www/public => public}/stats.txt (100%) rename {www/scripts => scripts}/generate-stats.js (82%) rename {www/src => src}/content.config.ts (100%) rename {www/src => src}/env.d.ts (100%) rename {www/src => src}/layouts/Layout.astro (100%) rename {www/src => src}/lib/api.ts (100%) rename {www/src => src}/lib/consts.ts (100%) rename {www/src => src}/lib/db.ts (100%) rename {www/src => src}/lib/format.ts (100%) rename {www/src => src}/lib/posts.ts (100%) rename {www/src => src}/lib/rate-limit.ts (100%) rename {www/src => src}/lib/txt.ts (100%) rename {www/src => src}/pages/404.astro (100%) rename {www/src => src}/pages/[slug].astro (100%) rename {www/src => src}/pages/admin.astro (54%) rename {www/src => src}/pages/api/guestbook.ts (100%) rename {www/src => src}/pages/api/guestbook/[id].ts (55%) rename {www/src => src}/pages/feed.xml.ts (100%) rename {www/src => src}/pages/guestbook-count.json.ts (100%) rename {www/src => src}/pages/index.astro (100%) rename {www/src => src}/pages/sitemap.txt.ts (100%) rename {www/src => src}/plugins/remark-aside.ts (100%) rename {www/src => src}/scripts/guestbook-sign.ts (100%) rename {www/src => src}/styles/global.css (100%) delete mode 100644 www/auth.config.ts delete mode 100644 www/db/seed.ts delete mode 100644 www/package-lock.json delete mode 100644 www/package.json delete mode 100644 www/src/lib/auth.ts delete mode 100644 www/src/pages/api/deploy.ts delete mode 100644 www/vercel.json diff --git a/www/.env.example b/.env.example similarity index 100% rename from www/.env.example rename to .env.example diff --git a/.gitignore b/.gitignore index fa6ee4f..4628d50 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ node_modules dist .astro -.vercel +data pnpm-lock.yaml **/.env diff --git a/www/astro.config.mjs b/astro.config.mjs similarity index 80% rename from www/astro.config.mjs rename to astro.config.mjs index fc75032..336687f 100644 --- a/www/astro.config.mjs +++ b/astro.config.mjs @@ -1,7 +1,6 @@ import { defineConfig } from 'astro/config'; -import vercel from '@astrojs/vercel'; +import node from '@astrojs/node'; import db from '@astrojs/db'; -import auth from 'auth-astro'; import remarkDirective from 'remark-directive'; import remarkGfm from 'remark-gfm'; import remarkSlug from 'remark-slug'; @@ -10,8 +9,8 @@ import remarkAside from './src/plugins/remark-aside.ts'; export default defineConfig({ output: 'static', - adapter: vercel(), - integrations: [db(), auth()], + adapter: node({ mode: 'standalone' }), + integrations: [db()], markdown: { remarkPlugins: [ remarkGfm, diff --git a/www/content/bookmarks.yaml b/content/bookmarks.yaml similarity index 100% rename from www/content/bookmarks.yaml rename to content/bookmarks.yaml diff --git a/www/content/hello.md b/content/hello.md similarity index 100% rename from www/content/hello.md rename to content/hello.md diff --git a/www/db/config.ts b/db/config.ts similarity index 100% rename from www/db/config.ts rename to db/config.ts diff --git a/db/seed.ts b/db/seed.ts new file mode 100644 index 0000000..b6bd429 --- /dev/null +++ b/db/seed.ts @@ -0,0 +1,14 @@ +import { db, Guestbook } from 'astro:db'; + +export default async function seed() { + await db.insert(Guestbook).values([ + { + id: 1, + name: 'test', + message: 'hello from dev', + url: null, + createdAt: new Date(), + approved: true, + }, + ]); +} diff --git a/package.json b/package.json index 6ebe20f..97967a8 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,24 @@ { - "name": "ily", - "private": true, - "packageManager": "pnpm@10.28.0", + "name": "wynne.rs", + "type": "module", "scripts": { - "dev:penfield": "pnpm --filter @ily/penfield dev", - "dev:www": "pnpm --filter @ily/www dev", - "build:penfield": "pnpm --filter @ily/penfield build", - "build:www": "pnpm --filter @ily/www build" + "dev": "astro dev --port 4322", + "build": "ASTRO_DATABASE_FILE=data/guestbook.db astro build && node scripts/generate-stats.js", + "preview": "astro preview" + }, + "dependencies": { + "@astrojs/db": "^0.20.1", + "@astrojs/node": "^10.0.4", + "@astrojs/rss": "^4.0.18", + "astro": "^6.1.3", + "js-yaml": "^4.1.1" + }, + "devDependencies": { + "@types/js-yaml": "^4.0.9", + "remark-directive": "^3.0.0", + "remark-gfm": "^4.0.0", + "remark-slug": "^7.0.1", + "remark-smartypants": "^3.0.2", + "unist-util-visit": "^5.1.0" } } diff --git a/penfield/astro.config.mjs b/penfield/astro.config.mjs deleted file mode 100644 index e93aeb8..0000000 --- a/penfield/astro.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -import { defineConfig } from 'astro/config'; - -export default defineConfig({ - output: 'static' -}); diff --git a/penfield/package.json b/penfield/package.json deleted file mode 100644 index 4f71c6a..0000000 --- a/penfield/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "@ily/penfield", - "type": "module", - "packageManager": "pnpm@10.28.0", - "scripts": { - "dev": "astro dev", - "build": "astro build", - "preview": "astro preview" - }, - "dependencies": { - "astro": "^5.16.13" - } -} diff --git a/penfield/src/data/intros.ts b/penfield/src/data/intros.ts deleted file mode 100644 index 5ff0b77..0000000 --- a/penfield/src/data/intros.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const intros = [ - { text: "You wake up. Your Penfield thrums." }, - { text: "Your Penfield Mood Organ chimes." }, - { text: "Your Penfield Mood Organ wakes you." }, - { text: "You are awoken by your Penfield Mood Organ." }, -]; diff --git a/penfield/src/data/moods.ts b/penfield/src/data/moods.ts deleted file mode 100644 index e94b40e..0000000 --- a/penfield/src/data/moods.ts +++ /dev/null @@ -1,17 +0,0 @@ -export const moods = [ - { num: 3, text: "Desire to dial" }, - { num: 382, text: "Desire to engage in creative activity" }, - { num: 481, text: "Awareness of the manifold possibilities open in the future" }, - { num: 594, text: "Pleased acknowledgment of husband's superior wisdom" }, - { num: 670, text: "Long-deserved peace" }, - { num: 888, text: "Desire to watch TV, no matter what's on" }, - { num: 443, text: "Self-accusatory depression" }, - { num: 72, text: "Vague unease about tomorrow" }, - { num: 158, text: "Acceptance of routine" }, - { num: 291, text: "Brief contentment with material possessions" }, - { num: 407, text: "Suppressed awareness of mortality" }, - { num: 531, text: "Calm readiness to consume" }, - { num: 816, text: "Desire to return to bed" }, - { num: 952, text: "Resigned compliance" }, - { num: 64, text: "Faint hope that things will improve" }, -]; diff --git a/penfield/src/pages/index.astro b/penfield/src/pages/index.astro deleted file mode 100644 index 9dedd26..0000000 --- a/penfield/src/pages/index.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -import { intros } from '../data/intros'; -import { moods } from '../data/moods'; -const epoch = Math.floor(Date.now() / 3600000); -const start = Math.floor(new Date('2026-01-22T14:00:00Z').getTime() / 3600000); -const t = epoch; // for mood selection -const ring = epoch - start; -const intro: { text: string } = intros[t % intros.length]; -const mood: { num: number, text: string } = moods[t % moods.length]; ---- -Penfield

Ring #{ring}.

{mood.num}. {mood.text}.

diff --git a/penfield/vercel.json b/penfield/vercel.json deleted file mode 100644 index b79cfde..0000000 --- a/penfield/vercel.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "installCommand": "pnpm install", - "buildCommand": "pnpm --filter @ily/penfield build", - "outputDirectory": "dist" -} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml deleted file mode 100644 index 4c70a74..0000000 --- a/pnpm-workspace.yaml +++ /dev/null @@ -1,3 +0,0 @@ -packages: - - 'www' - - 'penfield' diff --git a/www/public/changelog.txt b/public/changelog.txt similarity index 100% rename from www/public/changelog.txt rename to public/changelog.txt diff --git a/www/public/config.yaml b/public/config.yaml similarity index 100% rename from www/public/config.yaml rename to public/config.yaml diff --git a/www/public/cv.txt b/public/cv.txt similarity index 100% rename from www/public/cv.txt rename to public/cv.txt diff --git a/www/public/js/params.js b/public/js/params.js similarity index 100% rename from www/public/js/params.js rename to public/js/params.js diff --git a/www/public/man.txt b/public/man.txt similarity index 100% rename from www/public/man.txt rename to public/man.txt diff --git a/www/public/now.txt b/public/now.txt similarity index 100% rename from www/public/now.txt rename to public/now.txt diff --git a/www/public/stats.txt b/public/stats.txt similarity index 100% rename from www/public/stats.txt rename to public/stats.txt diff --git a/www/scripts/generate-stats.js b/scripts/generate-stats.js similarity index 82% rename from www/scripts/generate-stats.js rename to scripts/generate-stats.js index cf6cf5b..0987017 100644 --- a/www/scripts/generate-stats.js +++ b/scripts/generate-stats.js @@ -18,7 +18,6 @@ const posts = fs.existsSync(postsDir) let postWords = 0; for (const post of posts) { const content = fs.readFileSync(path.join(postsDir, post), 'utf-8'); - // Remove frontmatter const body = content.replace(/^---[\s\S]*?---/, ''); postWords += countWords(body); } @@ -41,20 +40,19 @@ const bookmarks = fs.existsSync(bookmarksFile) : []; // Guestbook count - read from built JSON file -const guestbookJsonFile = path.join(root, '.vercel/output/static/guestbook-count.json'); +const guestbookJsonFile = path.join(root, 'dist/client/guestbook-count.json'); let guestbookCount = 0; if (fs.existsSync(guestbookJsonFile)) { const data = JSON.parse(fs.readFileSync(guestbookJsonFile, 'utf-8')); guestbookCount = data.count; } -// Calculate totals (excluding stats.txt words for now, we'll add them after generating) -const totalPages = 1 + posts.length + txtFiles.length; // home + individual post pages + txt files +// Calculate totals +const totalPages = 1 + posts.length + txtFiles.length; // Read template from public/stats.txt and replace placeholders const template = fs.readFileSync(path.join(root, 'public/stats.txt'), 'utf-8'); -// First pass: generate stats without stats.txt word count let stats = template .replace('[PAGES]', totalPages.toString()) .replace('[POSTS]', posts.length.toString()) @@ -62,15 +60,13 @@ let stats = template .replace('[BOOKMARKS]', bookmarks.length.toString()) .replace('[GUESTBOOK]', guestbookCount.toString()); -// Count words in the stats file itself (before adding [WORDS]) const statsWords = countWords(stats.replace('[WORDS]', '0')); const totalWords = postWords + txtWords + statsWords; -// Final pass: replace [WORDS] with actual total stats = stats.replace('[WORDS]', totalWords.toString()); -// Write to Vercel output -const outputDir = path.join(root, '.vercel/output/static'); +// Write to build output +const outputDir = path.join(root, 'dist/client'); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } diff --git a/www/src/content.config.ts b/src/content.config.ts similarity index 100% rename from www/src/content.config.ts rename to src/content.config.ts diff --git a/www/src/env.d.ts b/src/env.d.ts similarity index 100% rename from www/src/env.d.ts rename to src/env.d.ts diff --git a/www/src/layouts/Layout.astro b/src/layouts/Layout.astro similarity index 100% rename from www/src/layouts/Layout.astro rename to src/layouts/Layout.astro diff --git a/www/src/lib/api.ts b/src/lib/api.ts similarity index 100% rename from www/src/lib/api.ts rename to src/lib/api.ts diff --git a/www/src/lib/consts.ts b/src/lib/consts.ts similarity index 100% rename from www/src/lib/consts.ts rename to src/lib/consts.ts diff --git a/www/src/lib/db.ts b/src/lib/db.ts similarity index 100% rename from www/src/lib/db.ts rename to src/lib/db.ts diff --git a/www/src/lib/format.ts b/src/lib/format.ts similarity index 100% rename from www/src/lib/format.ts rename to src/lib/format.ts diff --git a/www/src/lib/posts.ts b/src/lib/posts.ts similarity index 100% rename from www/src/lib/posts.ts rename to src/lib/posts.ts diff --git a/www/src/lib/rate-limit.ts b/src/lib/rate-limit.ts similarity index 100% rename from www/src/lib/rate-limit.ts rename to src/lib/rate-limit.ts diff --git a/www/src/lib/txt.ts b/src/lib/txt.ts similarity index 100% rename from www/src/lib/txt.ts rename to src/lib/txt.ts diff --git a/www/src/pages/404.astro b/src/pages/404.astro similarity index 100% rename from www/src/pages/404.astro rename to src/pages/404.astro diff --git a/www/src/pages/[slug].astro b/src/pages/[slug].astro similarity index 100% rename from www/src/pages/[slug].astro rename to src/pages/[slug].astro diff --git a/www/src/pages/admin.astro b/src/pages/admin.astro similarity index 54% rename from www/src/pages/admin.astro rename to src/pages/admin.astro index 66ff49c..32092e2 100644 --- a/www/src/pages/admin.astro +++ b/src/pages/admin.astro @@ -2,16 +2,9 @@ export const prerender = false; import { getPendingEntries, type GuestbookEntry } from '../lib/db'; -import { getAdminSession } from '../lib/auth'; import Layout from '../layouts/Layout.astro'; import { formatDate } from '../lib/format'; -const auth = await getAdminSession(Astro.request); -if (auth.status === 'error') return new Response('Auth not configured', { status: 500 }); -if (auth.status === 'unauthenticated') return Astro.redirect('/api/auth/signin'); -if (auth.status !== 'admin') return new Response('Forbidden', { status: 403 }); -const { session } = auth; - let entries: GuestbookEntry[] = []; try { entries = await getPendingEntries(); @@ -22,9 +15,6 @@ try {

guestbook admin

-

logged in as {session.user?.name} sign out

- -

{entries.length === 0 ? (

no pending entries

@@ -44,22 +34,6 @@ try { )}