- TypeScript 95%
- Shell 3%
- CSS 1.5%
- Dockerfile 0.4%
- HTML 0.1%
| docker/postgres | ||
| drizzle | ||
| ExampleSite | ||
| output/playwright | ||
| public | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .eslintrc.json | ||
| .gitignore | ||
| DESIGN_GUIDANCE.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| drizzle.config.ts | ||
| ExampleSite.zip | ||
| FEATURE_MAP.md | ||
| GO_LIVE_CHECKLIST.md | ||
| IMPLEMENTATION_STATUS.md | ||
| MemorialLogo.png | ||
| Mirroring.md | ||
| next-env.d.ts | ||
| next.config.ts | ||
| NEXT_STEPS.md | ||
| nginx.memorial.conf | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.js | ||
| README.md | ||
| ROADMAP.md | ||
| tailwind.config.ts | ||
| TESTING.md | ||
| tsconfig.json | ||
| tsconfig.tsbuildinfo | ||
| VISION.md | ||
Memorial Service
Moderated child memorial obituary application built with Next.js, PostgreSQL, Drizzle, local disk publication, GitHub Pages backup publishing, and family export archives.
The intended deployment model is:
- use Docker or the host machine for a live-reload authoring/admin environment during development
- publish generated memorials as static artifacts
- host the public memorial output statically, not as a long-running public Node app
Product note:
- this memorial system is intended to be folded into
henzi.org, not launched as a separate standalone branded public site - the database is an internal authoring/moderation tool; the canonical public result should be static memorial files
Documentation
- VISION.md
- DESIGN_GUIDANCE.md
- FEATURE_MAP.md
- Mirroring.md
- IMPLEMENTATION_STATUS.md
- ROADMAP.md
- GO_LIVE_CHECKLIST.md
- TESTING.md
- NEXT_STEPS.md
What Is Implemented
- Public memorial submission flow at
/submit - Client-side photo upload plus crop framing
- Writing prompts and live authoring preview
- Four curated obituary template options based directly on the ExampleSite directions:
Ethereal & Soft,Classic & Timeless,Whimsical & Bright, andNature-Inspired - Structured service cards and memorial gathering sections
- ExampleSite-inspired builder flow with a compact authoring rail and a larger live memorial preview while editing
- Single-photo memorial layouts with graceful no-photo fallbacks
- Admin login seeded from env credentials
- Admin submission queue and detail review
- Approve, reject, unpublish, and republish actions
- Publication snapshots stored in PostgreSQL
- Static memorial package generation on approval
- Primary publication artifact generation under
data/generated/memorials - GitHub Pages backup publishing hook
- Family export
.zipgeneration underdata/exports - Public memorial route with mobile-friendly share, QR, and export actions
- Local asset and export serving routes for development/runtime fallback
Current Status
See IMPLEMENTATION_STATUS.md for a repo-based breakdown of what is COMPLETE, PARTIAL, and TODO.
Use:
- ROADMAP.md for phased remaining work
- GO_LIVE_CHECKLIST.md for launch-readiness tracking
Local Setup
- Copy
.env.exampleto.env - Review the port values in
.env
APP_PORTdefaults to3301STATIC_PREVIEW_PORTdefaults to4301POSTGRES_PORTdefaults to55432
- Start PostgreSQL:
docker compose up -d db
- Install dependencies:
npm install
- Apply the schema:
npm run db:push
- Start the app:
npm run dev
Docker Dev
If you want Docker to run the live-reload dev app and database together:
npm run docker:dev
This starts:
web: Next.js in development mode with source files bind-mounted from your local workspacedb: PostgreSQL with persisted data underdata/postgres
Live edits to files in the repo should reload in the browser at:
http://localhost:${APP_PORT}
Typical first-run steps in Docker dev:
npm run docker:dev- In a second terminal:
docker compose exec web npm run db:push - Open
/submitor/admin/login
Notes:
- the dev container is for local authoring/testing only
node_modulesand.nextare stored in Docker volumes so your bind mount stays clean- if
package.jsonchanges, rebuild withnpm run docker:dev
The default admin login comes from:
ADMIN_EMAILADMIN_PASSWORD
The admin user is created or refreshed automatically the first time the login route runs.
Local Test Server
Run the full local authoring/moderation stack:
npm run local:test
This script will:
- start PostgreSQL with Docker Compose
- install dependencies if
node_modulesis missing - apply the current schema with
npm run db:push - run the app on
APP_PORT
If you want to preview the generated static memorial output the way a hosted static site would serve it:
npm run local:static
That serves data/generated on STATIC_PREVIEW_PORT so published memorials are reachable at:
http://localhost:<STATIC_PREVIEW_PORT>/memorials/<slug>/
Reset Local Test Data
Wipe memorial test content while keeping admin access:
npm run local:reset
For a full local database wipe and rebuild:
npm run local:reset:hard
See TESTING.md for the full end-to-end test flow and cleanup guidance.
Important Paths
- Local uploads:
data/uploads - Generated primary memorials:
data/generated/memorials - Generated backup-site worktree:
data/github-pages-worktree - Export archives:
data/exports - Database backups:
data/backups/database - SQL migrations:
drizzle
Docker Usage
Docker Compose is for local development, not public production hosting.
webruns the live-reload Next.js development serverdbruns PostgreSQL- public memorial hosting should use generated static output rather than
next startbehind Docker - the production/runtime
Dockerfilestage is optional and not the recommended public deployment target
Database Backups
Create a new timestamped database archive and zip it:
npm run backup:db
Zip the latest raw database dump, or pass a specific .dump file:
npm run backup:db:zip
./scripts/zip-db-backup.sh ./data/backups/database/raw/memorial_service-YYYYMMDD-HHMMSS.dump
Backup output directories:
data/backups/database/rawdata/backups/database/zip
GitHub Pages Backup
To enable backup publishing, set these env vars:
GITHUB_PAGES_REPOGITHUB_PAGES_BRANCHGITHUB_PAGES_BASE_URL
If they are missing, the app still publishes the primary memorial and records the backup target as skipped/failed.
Build Checks
npm run typechecknpm run lintnpm run build
Current Notes
- Turnstile accepts
dev-bypassoutside production so the form is usable locally. - Rate limiting is currently in-memory and should move to Redis or durable storage later.
- Primary static memorials are generated on disk for static/Nginx-style serving.
- The Next.js app is for authoring, moderation, and local/private operation; it is not the intended public hosting model.
- The public memorial experience is expected to support device-native mobile sharing when available, with a fallback for devices/browsers that do not expose the Web Share API.
- Families must be able to download an export archive of the published memorial so they are not locked into the live site.
- The four active memorial templates now use distinct compositions instead of one shared layout with color swaps; the same four-template structure is used in live preview and static publication.
- The product is being refocused toward a stricter static-first preservation model, including GitHub backup, Wayback archival planning, and a future
Mark as private/noindexoption. - The existing candle interaction is now under review as likely launch de-scope because it adds runtime interactivity to a product that wants static publication to be the core experience.
- The next likely milestone is a temporary Henzi-hosted pilot page so invited users can try the builder and give feedback before broader rollout.