No description
  • TypeScript 95%
  • Shell 3%
  • CSS 1.5%
  • Dockerfile 0.4%
  • HTML 0.1%
Find a file
2026-03-18 16:10:37 -04:00
docker/postgres it's not real 2026-03-18 16:10:37 -04:00
drizzle it's not real 2026-03-18 16:10:37 -04:00
ExampleSite starting 2026-03-18 00:17:32 -04:00
output/playwright it's not real 2026-03-18 16:10:37 -04:00
public starting 2026-03-18 00:17:32 -04:00
scripts it's not real 2026-03-18 16:10:37 -04:00
src it's not real 2026-03-18 16:10:37 -04:00
.dockerignore it's not real 2026-03-18 00:58:56 -04:00
.env.example starting 2026-03-18 00:17:32 -04:00
.eslintrc.json starting 2026-03-18 00:17:32 -04:00
.gitignore starting 2026-03-18 00:17:32 -04:00
DESIGN_GUIDANCE.md it's not real 2026-03-18 00:58:56 -04:00
docker-compose.yml it's not real 2026-03-18 16:10:37 -04:00
Dockerfile it's not real 2026-03-18 00:58:56 -04:00
drizzle.config.ts starting 2026-03-18 00:17:32 -04:00
ExampleSite.zip starting 2026-03-18 00:17:32 -04:00
FEATURE_MAP.md it's not real 2026-03-18 16:10:37 -04:00
GO_LIVE_CHECKLIST.md it's not real 2026-03-18 16:10:37 -04:00
IMPLEMENTATION_STATUS.md it's not real 2026-03-18 16:10:37 -04:00
MemorialLogo.png starting 2026-03-18 00:17:32 -04:00
Mirroring.md it's not real 2026-03-18 16:10:37 -04:00
next-env.d.ts starting 2026-03-18 00:17:32 -04:00
next.config.ts starting 2026-03-18 00:17:32 -04:00
NEXT_STEPS.md it's not real 2026-03-18 16:10:37 -04:00
nginx.memorial.conf starting 2026-03-18 00:17:32 -04:00
package-lock.json it's not real 2026-03-18 16:10:37 -04:00
package.json it's not real 2026-03-18 16:10:37 -04:00
postcss.config.js starting 2026-03-18 00:17:32 -04:00
README.md it's not real 2026-03-18 16:10:37 -04:00
ROADMAP.md it's not real 2026-03-18 16:10:37 -04:00
tailwind.config.ts it's not real 2026-03-18 16:10:37 -04:00
TESTING.md it's not real 2026-03-18 16:10:37 -04:00
tsconfig.json starting 2026-03-18 00:17:32 -04:00
tsconfig.tsbuildinfo it's not real 2026-03-18 16:10:37 -04:00
VISION.md it's not real 2026-03-18 16:10:37 -04:00

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

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, and Nature-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 .zip generation under data/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:

Local Setup

  1. Copy .env.example to .env
  2. Review the port values in .env
  • APP_PORT defaults to 3301
  • STATIC_PREVIEW_PORT defaults to 4301
  • POSTGRES_PORT defaults to 55432
  1. Start PostgreSQL:
docker compose up -d db
  1. Install dependencies:
npm install
  1. Apply the schema:
npm run db:push
  1. 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 workspace
  • db: PostgreSQL with persisted data under data/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:

  1. npm run docker:dev
  2. In a second terminal: docker compose exec web npm run db:push
  3. Open /submit or /admin/login

Notes:

  • the dev container is for local authoring/testing only
  • node_modules and .next are stored in Docker volumes so your bind mount stays clean
  • if package.json changes, rebuild with npm run docker:dev

The default admin login comes from:

  • ADMIN_EMAIL
  • ADMIN_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_modules is 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.

  • web runs the live-reload Next.js development server
  • db runs PostgreSQL
  • public memorial hosting should use generated static output rather than next start behind Docker
  • the production/runtime Dockerfile stage 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/raw
  • data/backups/database/zip

GitHub Pages Backup

To enable backup publishing, set these env vars:

  • GITHUB_PAGES_REPO
  • GITHUB_PAGES_BRANCH
  • GITHUB_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 typecheck
  • npm run lint
  • npm run build

Current Notes

  • Turnstile accepts dev-bypass outside 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/noindex option.
  • 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.