Initial commit: personal homepage with live Harbor registry
build / image (push) Failing after 15s

- Linktree-style homepage with photo, social links, and self-hosted
  services (container registry, Git server)
- Registry pages rendered on demand from Harbor via a live content
  collection, cached in memory (60s fresh, 10min stale-while-revalidate)
- Pinned registry images (PINNED_IMAGES) shown first with a star
- Node standalone server with security headers; self-contained server
  build so the Docker image ships no node_modules
- Gitea workflow building multi-arch images for Flux

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-29 10:23:02 +02:00
co-authored by Claude Opus 5.5
commit 7b670010b1
33 changed files with 5004 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
// @ts-check
import { defineConfig, envField, memoryCache } from 'astro/config';
import node from '@astrojs/node';
// https://astro.build/config
export default defineConfig({
// Used for canonical URLs (and the sitemap/RSS once the blog lands).
// Note: .env is not loaded into process.env for this file; pass it via the environment.
site: process.env.SITE_URL,
trailingSlash: 'always',
prefetch: { defaultStrategy: 'hover', prefetchAll: true },
// Static pages stay prerendered; the registry pages opt into on-demand rendering.
adapter: node({ mode: 'standalone' }),
// No page reads query params, so ignore them in cache keys (`?x=random` can't bypass the cache).
cache: { provider: memoryCache({ query: { include: [] } }) },
// Bundle runtime deps into the server build so the image needs no node_modules.
vite: { ssr: { noExternal: ['marked'] } },
env: {
// All `secret` so they are read from the server environment at runtime, never inlined at build.
schema: {
HARBOR_URL: envField.string({ context: 'server', access: 'secret', optional: true, url: true }),
HARBOR_REGISTRY_HOST: envField.string({ context: 'server', access: 'secret', optional: true }),
HARBOR_PROJECTS: envField.string({ context: 'server', access: 'secret', optional: true }),
HARBOR_USERNAME: envField.string({ context: 'server', access: 'secret', optional: true }),
HARBOR_PASSWORD: envField.string({ context: 'server', access: 'secret', optional: true }),
},
},
});