d6acf85252370c9faee50328644bca2b879a6f77
The snapshot was set from buildSiteContentForSave(form) which runs normalizeSiteContentForAdmin and rebuilds study objects, producing a JSON string that never matched the raw form state. isDirty therefore stayed true permanently after every save. Fix by capturing JSON.stringify(form) before the fetch and using that as the snapshot, so isDirty correctly clears on success. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Siteforge
This project is a React + TypeScript portfolio app built with Vite.
It is designed to showcase two categories of work:
- Websites
- Apps
The app now supports:
- Dynamic cards generated from a project data source
- Built vs Hosted filters
- A dedicated About page route for each project
- An admin editor route to update cards and About pages
- A per-project README summary block on each project page
- Embedded Spotify podcast player on the home section
Run locally
npm install
npm run dev:full
dev:full starts both:
- Vite frontend (
http://localhost:5173) - Admin content API (
http://localhost:4173)
Build for production
npm run build
Run in container
Pull image directly:
docker pull ghcr.io/nmemmert/siteforge:latest
docker run -d --name siteforge-app -p 4173:4173 -v ./data:/app/data ghcr.io/nmemmert/siteforge:latest
Run with Docker Compose:
docker compose pull
docker compose up -d
Admin auth:
- Set
ADMIN_PASSWORDon the server/container to protect/adminand admin stats/maintenance endpoints. - Without
ADMIN_PASSWORD, admin login is disabled until configured. - Optional: set
CACHE_PURGE_WEBHOOK_URLto enable one-click cache purge from Admin Operations. - Optional: set
DEPLOY_WEBHOOK_URLto enable one-click deploy trigger from Admin Operations. - Optional: set
BUILD_COMMIT,BUILD_NUMBER, andDEPLOYED_ATto display deployment status in Admin.
The app will be available at http://localhost:4173.
Persistent admin saves:
- Admin updates are written to
data/admin-content.json. - Admin drafts are written to
data/admin-content-draft.json. - Built-in page hit stats are written to
data/hit-stats.json. - Detailed visitor analytics are written to
data/visitor-stats.json. - Backup snapshots are written to
data/backups/. - Uploaded admin assets are stored in
data/uploads/and served at/uploads/*. docker-compose.ymlmounts./datainto the container at/app/data.- This keeps all admin-managed data after container restarts/rebuilds/updates.
Where to edit content
- Project domain data and ownership:
src/data/projects.ts - Portfolio rendering logic:
src/App.tsx - Portfolio UI styles:
src/App.css - Global theme variables:
src/index.css
Routes
- Site home:
/ - Start Here:
/start-here - Questions:
/questions - Privacy:
/privacy - Terms:
/terms - Admin editor:
/admin - Admin draft preview:
/preview
Admin editing
- Open
/adminto edit homepage content, links, archived studies, Q&A moderation, and analytics. - Use Operations to manage SEO metadata, sitemap paths, legal page text, redirect rules, and podcast highlights.
- Use Operations to upload/delete hosted image assets for use in content and social cards.
- Use Save Draft, Preview Draft, and Publish Draft for a safer publish workflow.
- Saved edits are written to
data/admin-content.jsonthrough the API server. - Built-in stats in
/admininclude page hits plus visitor details (IP, country/state/county/city, returning visitors, and recent visitor log). - Site Stats in
/adminincludes a Bible Questions inbox sourced from contact form submissions marked as Bible Question. - Analytics cookies are consent-based. Visitors can accept or decline tracking from the site banner.
- Admin now includes maintenance actions: Export JSON, Backup Now, Prune Old Data, and Clear Analytics.
- Admin also supports restoring from a backup snapshot from
/admin. - The server creates startup + daily backup snapshots and retains recent backups automatically.
- Operations can trigger optional Purge Cache and Trigger Deploy webhooks.
Deployment note:
- To keep Admin saves working on the internet, deploy with the Node API (
server.js) and writable server storage fordata/.
Titus study download gate:
- The site now gates Titus study downloads behind a name/email form.
- Default source file is
A_Study_of_Titus.pdfin the project root. - Override source path with
TITUS_STUDY_FILE(relative to project root or absolute). - Override downloaded filename with
TITUS_STUDY_DOWNLOAD_NAME. - When the form checkbox is left enabled (default), contacts are synced to Resend using the same contact sync flow as the contact form.
Useful container commands:
docker compose logs -f
docker compose down
Update to latest image:
docker compose pull
docker compose up -d
Notes
- The current project cards are sample placeholders.
- Most metadata was scanned from live pages.
- Skywatch currently uses a manual fallback description due to a
401response during automated scan.
Description
Languages
TypeScript
47%
JavaScript
26.6%
CSS
15%
HTML
10.9%
Shell
0.4%