From ad7fa6f966de7a190927f052ca6a3796042bc1a8 Mon Sep 17 00:00:00 2001 From: Adrian Altner Date: Mon, 30 Mar 2026 16:04:48 +0200 Subject: [PATCH] Update content licenses and footer information; enhance contact and privacy policy pages --- CLAUDE.md | 67 +++++++++++++++++++++++++------------ LICENSE | 7 ++-- src/components/Footer.astro | 2 +- src/pages/contact.astro | 16 ++++----- src/pages/imprint.md | 8 ++--- src/pages/privacy-policy.md | 2 +- 6 files changed, 61 insertions(+), 41 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 630bbb6..086dd38 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,36 +2,46 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +## Prerequisites + +Node.js >= 22. Package manager is pnpm (enforced via `preinstall` script). Husky pre-commit hook runs `pnpm check`. + ## Commands ```bash -npm run dev # Start dev server (localhost:4321) -npm run build # astro check + build + copy-sw (use this to verify changes) -npm run check # Type check + Biome lint -npm run check:fix # Type check + Biome lint with auto-fix -npm run stylelint # Lint CSS/Astro styles -npm run stylelint:fix # Fix style issues +pnpm dev # Start dev server (localhost:4321) +pnpm build # astro check + build + copy-sw (use this to verify changes) +pnpm build:production # Production build (skips astro check, uses --mode production) +pnpm check # Type check + Biome lint +pnpm check:fix # Type check + Biome lint with auto-fix +pnpm stylelint # Lint CSS/Astro styles +pnpm stylelint:fix # Fix style issues +pnpm generate:icons # Regenerate PWA icon assets ``` -There are no automated tests. Verification is done via `npm run build` (0 errors required) and the preview MCP tools. +There are no automated tests. Verification is done via `pnpm build` (0 errors required) and the preview MCP tools. ## Architecture -Astro 6 site running in SSR mode (Node.js standalone adapter) with static output for most routes. TypeScript strict mode. Path alias `@/*` → `src/*`. +Astro 6 site running in SSR mode (Node.js standalone adapter) with static output for most routes. Pure Astro components — no React/Vue/Svelte. TypeScript strict mode (`astro/tsconfigs/strictest`). Path alias `@/*` → `src/*`. -**Formatter/linter:** Biome (not ESLint/Prettier). Run `check:fix` after larger edits. +**Formatter/linter:** Biome (not ESLint/Prettier). Run `check:fix` after larger edits. Biome config disables some rules for `.astro` files (`useConst`, `useImportType`, `noUnusedVariables`, `noUnusedImports`). + +**Markdown plugins:** `remarkObsidianLinks` (custom, `src/lib/remark-obsidian-links.mjs`) for `[[wiki-link]]` syntax, `rehypeExternalLinks` for `target="_blank"` on external links. ### Content Collections (`src/content.config.ts`) -Five collections defined with Zod schemas: +Seven collections defined with Zod schemas: -| Collection | Path | Notes | -|---|---|---| -| `blog` | `src/content/blog/` | Posts with series support (`seriesParent`, `seriesOrder`), tags, category ref, syndication URLs | -| `categories` | `src/content/categories/` | Referenced by blog posts | -| `notes` | `src/content/notes/` | Short-form with optional cover image | -| `links` | `src/content/links/` | Curated external links | -| `collections_photos` | `src/content/photos/collections/` | Photo collections; photos stored as JPG + JSON sidecar files in `img/` subdirs | +| Collection | Loader | Path | Notes | +|---|---|---|---| +| `blog` | glob | `src/content/blog/posts/` | Series support (`seriesParent`, `seriesOrder`), tags, category ref, syndication URLs | +| `categories` | glob | `src/content/blog/categories/` | Referenced by blog posts | +| `notes` | glob | `src/content/notes/` | Short-form with optional cover image | +| `links_json` | file | `src/content/links/links.json` | JSON file with auto-generated IDs (`json/date/slug`) | +| `projects` | glob | `src/content/projects/project/` | Portfolio items with optional URL/GitHub links | +| `projects_categories` | glob | `src/content/projects/categories/` | Referenced by projects | +| `collections_photos` | glob | `src/content/photos/collections/` | Matches `**/index.{md,mdx}`; photos as JPG + JSON sidecar files in `img/` subdirs | ### Key Routing Patterns @@ -39,22 +49,35 @@ Five collections defined with Zod schemas: - `/og/blog/[...slug].png` — OG images generated server-side via Satori (`src/lib/og.ts`) - `/rss/blog.xml`, `/rss/notes.xml`, `/rss/links.xml`, `/rss/photos.xml` — Separate RSS feeds per content type - `/photos/collections/[...slug]` — Nested photo collections with breadcrumb navigation +- `/projects/[...slug]`, `/projects/category/[...slug]` — Project portfolio +- `/tags/[slug]` — Cross-content-type tag pages +- `/archives/` — Timeline of all content +- `/api/webmentions.json` — Webmention data endpoint ### Lib Utilities (`src/lib/`) - `collections.ts` — Photo collection helpers: `collectionSlug()`, `buildCollectionPhotos()`, `buildBreadcrumbs()`, `getChildCollections()` - `og.ts` — OG image generation using Satori (`buildArticleVNode`, `renderOgImage`) -- `webmentions.ts` — Fetch and filter webmentions from webmention.io +- `webmentions.ts` — Fetch and filter webmentions from webmention.io (includes Mastodon/Bluesky validation) - `photo-albums.ts` — Photo album organisation utilities +- `links.ts` — Link collection helpers +- `remark-obsidian-links.mjs` — Custom remark plugin for Obsidian-style `[[links]]` ### Scripts (`scripts/`) -- `mastodon-syndicate.js` — Scans `src/content/blog` and `src/content/notes` for posts without a `syndication` field, posts to Mastodon, writes the status URL back to frontmatter. Env vars: `MASTODON_BASE_URL`, `MASTODON_ACCESS_TOKEN`, `MASTODON_VISIBILITY`, `MASTODON_DRY_RUN`, `MASTODON_LIMIT` -- `publish-posts.sh` — Full deploy orchestration: rsync content to VPS → rebuild container → send webmentions → run mastodon-syndicate +- `mastodon-syndicate.mjs` — POSSE: scans blog/notes for posts without `syndication` field, posts to Mastodon, writes status URL back to frontmatter. Env vars: `MASTODON_BASE_URL`, `MASTODON_ACCESS_TOKEN`, `MASTODON_VISIBILITY`, `MASTODON_DRY_RUN`, `MASTODON_LIMIT` +- `vision.ts` — Uses Claude Vision API to auto-generate EXIF sidecars + metadata for photo collections. Requires `ANTHROPIC_API_KEY` +- `publish-all.sh` — Full deploy orchestration: rsync content to VPS → rebuild container → send webmentions → run mastodon-syndicate. Per-collection variants: `publish-blog.sh`, `publish-notes.sh`, `publish-links.sh`, `publish-photos.sh`, `publish-projects.sh` +- `new-post.sh`, `new-note.sh` — Content scaffolding templates +- `copy-sw.js` — Post-build service worker copy ### IndieWeb / Syndication -Blog posts support POSSE via `mastodon-syndicate.js`. After posting, the Mastodon status URL is written to frontmatter as `syndication: ["https://..."]`. The `SyndicationLinks` component reads this and renders `u-syndication` microformat links. Webmentions are fetched at build time from webmention.io and displayed via `WebMentions.astro`. +Blog posts support POSSE via `mastodon-syndicate.mjs`. After posting, the Mastodon status URL is written to frontmatter as `syndication: ["https://..."]`. The `SyndicationLinks` component renders `u-syndication` microformat links. Webmentions are fetched at build time from webmention.io and displayed via `WebMentions.astro`. + +### Deployment + +Multi-stage container build (`Containerfile`): Node 22 with pnpm for build, Node 22 slim for runtime. Runs `node dist/server/entry.mjs` on port 4321. Orchestrated via `compose.yml`. Deploy scripts rsync content to VPS and rebuild the container. --- @@ -78,7 +101,7 @@ Blog posts support POSSE via `mastodon-syndicate.js`. After posting, the Mastodo ### 4. Verification Before Done - Never mark a task complete without proving it works -- Run `npm run build` — must complete with 0 errors +- Run `pnpm build` — must complete with 0 errors - Use preview MCP tools to visually verify UI changes ### 5. Demand Elegance (Balanced) diff --git a/LICENSE b/LICENSE index aef6e46..7cf3270 100644 --- a/LICENSE +++ b/LICENSE @@ -26,7 +26,8 @@ SOFTWARE. All content in `src/content/` and `public/` — including but not limited to articles, notes, and photographs — is licensed under -[Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)](https://creativecommons.org/licenses/by-sa/4.0/). +[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/). -You are free to share and adapt the content, as long as you give appropriate -credit and distribute your contributions under the same license. +You are free to share and adapt the content for non-commercial purposes, as long +as you give appropriate credit and distribute your contributions under the same +license. diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 3a158ef..6096c7c 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -8,7 +8,7 @@ const { dark } = Astro.props;