How yorknouse/website works
1. Overall shape
This repo is a mixed legacy-and-migration codebase for the Nouse website. It contains:
- a legacy PHP CMS/runtime under html/
- a newer Next.js admin/backend app in edit-backend/
- a newer Astro public site in readers-frontend/
- Docker and ops assets for running the full stack locally and in production.
2. Request routing and edge
Caddy sits in front of Apache to terminate SSL and proxy traffic. Apache still owns most URL routing for the legacy PHP site, which is why the project explicitly avoids a conventional application router. The Docker setup and docker-compose.yml are the main runtime boundary for the whole system.
3. Legacy PHP application
The old CMS is organized around html/admin, html/default, and html/common.
- html/admin is the editorial/admin dashboard
- html/default is the public site entrypoint
- html/common holds shared PHP classes, templates, and helpers
The admin side uses page-rendered Twig templates plus jQuery-triggered API calls for mutations, rather than a single SPA-style UI.
4. New admin/backend application
edit-backend/ is the modern TypeScript replacement path. It uses Next.js App Router with:
- server-rendered admin pages under src/app/(app)
- auth flows under src/app/(auth)
- JSON APIs under src/app/api/*
This app exposes both admin-facing endpoints and “frontend” content endpoints, so it acts as the central API layer for newer clients.
5. Public reader site
readers-frontend/ is the new public-facing site, built with Astro and some embedded SolidJS components. It renders pages such as articles, authors, editions, categories, search, and static informational pages. It is structured as a content consumer, pulling data from backend APIs rather than owning content state itself.
6. Primary data store
MySQL is the core system of record. The newer backend uses Prisma (edit-backend/prisma/schema.prisma, migrations, seed data) to model and access the database. The legacy PHP code also interacts with the same underlying database directly, so both generations of the app share the same content/data boundary.
7. Cache and supporting state
The new backend has explicit cache and Redis modules (src/lib/cache.ts, src/lib/redis.ts), indicating some read-heavy endpoints or session/state helpers are cached outside MySQL. This matters for architecture because many public-content reads are served from API layers that likely avoid hitting the database every time.
8. Media and file upload flow
Uploaded assets are handled through signed uploads to object storage rather than being stored in the app containers. The backend exposes endpoints for:
- generating upload signatures
- completing uploads
- resolving file URLs
The repo’s Backblaze B2 / S3 setup and cors.json show that object storage is an external dependency for user avatars, article media, and other files.
9. Authentication and permissions
Authentication is split across generations:
- the new backend uses NextAuth-style routes plus OAuth/authorise/token endpoints
- the legacy PHP side has its own auth helpers in html/common and admin auth pages
The admin area also includes user management, suspension, permissions, and audit-log functionality, so authorization is a meaningful subsystem rather than a thin login gate.
10. Scheduled and background work
There are cron-style jobs in both stacks:
- PHP cron scripts under html/cron
- TypeScript cron scripts under edit-backend/scripts
- Docker-side cron helpers in docker/cron-minute.sh and docker/job-cron
These handle maintenance tasks such as updating article read summaries and other periodic backend work.
11. Operational and observability stack
The repo includes production support for Grafana and Netdata, both provisioned via Docker configs. Grafana dashboards are predeclared as JSON and wired to MySQL, while Netdata provides host/service monitoring. The readme also mentions phpMyAdmin access for database administration.
12. Deployment and rebuild path
Deployments are container-based, with separate Dockerfiles for the PHP, Astro, and React/Next-style apps. There is also a webhook-driven rebuild flow used by the admin side to trigger image rebuilds and restart services when static or generated pages need refreshing. That makes “build/redeploy” part of the content publishing workflow, not just an ops concern.
Main entry points: mysql.conf MySQL · docker-compose.yml Compose stack · route.ts Backend APIs · Dockerfile.php-df Apache/PHP
Components 21
Ops & runtime
Container, proxy, and observability boundary for the whole stack.
- Caddy · Terminates SSL and proxies traffic into the stack.
docker/caddy/Caddyfile - Apache/PHP · Legacy HTTP and PHP serving layer behind the edge proxy.
Dockerfile.php-df - Compose stack · Main container boundary coordinating the full local/production stack.
docker-compose.yml - Grafana · Preconfigured dashboards and datasource provisioning for metrics and DB views.
docker/grafana/dashboards/home.json - Netdata · Host/service monitoring configuration for runtime health.
docker/netdata/config/netdata.conf
Legacy PHP site
Older CMS/runtime that still serves the main site and admin flows.
- Legacy admin · Editorial/admin interface for the older site generation.
html/admin/index.php - Legacy site · Public site entrypoint and legacy URL handling.
html/default/index.php - Shared PHP · Common PHP config, auth, classes, and shared templates.
html/common/config.php - Legacy API · Mutation endpoints for articles, comments, permissions, files, and rebuilds.
html/admin/api/apiHead.php - PHP cron · Legacy scheduled maintenance and article summary updates.
html/cron/updateArticlesReadsSummary.php
Next backend
Modern TypeScript admin and API layer.
- Next app · Modern Next.js App Router application for admin and auth flows.
edit-backend/src/app/(app)/page.tsx - Backend APIs · Central API layer for admin, auth, upload, and frontend-content endpoints.
edit-backend/src/app/api/frontend/articles/route.ts - Backend lib · Shared backend services for auth, cache, Prisma, Redis, S3, and content logic.
edit-backend/src/lib/prisma.ts - Prisma model · Database schema, migrations, and seed data for the newer backend.
edit-backend/prisma/schema.prisma - TS cron · TypeScript maintenance and periodic backend jobs.
edit-backend/scripts/cron.ts
Reader site
New public-facing Astro frontend.
- Astro site · Public reader experience built with Astro and embedded SolidJS components.
readers-frontend/src/pages/index.astro - Reader UI · Shared Astro and SolidJS building blocks for article, navbar, search, and listing pages.
readers-frontend/src/components/Navbar.astro - Reader pages · Page routes for articles, authors, editions, categories, search, and static pages.
readers-frontend/src/pages/articles/[year]/[month]/[day]/[slug].astro
Shared data
Database, cache, and object storage dependencies used across generations.
- MySQL · Shared relational database used by both legacy PHP and the new backend.
docker/mysql/mysql.conf - Redis · Backend cache and lightweight state store.
edit-backend/src/lib/redis.ts - Object storage · External file storage for signed uploads, avatars, and article media.
edit-backend/src/lib/s3.ts
Connections 26
- Compose stack → Caddy: runs · Compose provisions the edge proxy.
- Compose stack → Apache/PHP: runs · Compose provisions the legacy PHP runtime.
- Compose stack → Grafana: runs · Compose provisions observability services.
- Compose stack → Netdata: runs · Compose provisions host monitoring.
- Caddy → Apache/PHP: proxies · SSL edge routes traffic to Apache and the legacy app.
- Apache/PHP → Legacy admin: serves · Apache hosts the admin CMS.
- Apache/PHP → Legacy site: serves · Apache hosts the public PHP site.
- Legacy admin → Shared PHP: uses · Admin pages share common PHP auth/config/helpers.
- Legacy site → Shared PHP: uses · Public site reuses shared PHP runtime pieces.
- Legacy admin → Legacy API: calls · Admin UI triggers legacy mutation endpoints.
- Legacy API → MySQL: reads/writes · Legacy admin endpoints persist directly to MySQL.
- Shared PHP → MySQL: queries · Shared PHP code reads the same database boundary.
- PHP cron → MySQL: updates · Legacy cron jobs maintain content-derived summaries.
- Next app → Backend APIs: uses · Server-rendered pages depend on backend endpoints and shared services.
- Backend APIs → Backend lib: calls · API routes are implemented through backend service modules.
- Backend lib → Prisma model: models · Prisma defines the backend database schema layer.
- Prisma model → MySQL: maps to · Prisma persists the new backend model into MySQL.
- Backend lib → Redis: caches · Backend services use Redis for cache/state.
- Backend APIs → Object storage: uploads · Signed upload and URL endpoints integrate with object storage.
- TS cron → MySQL: maintains · Backend cron jobs perform periodic database work.
- Astro site → Reader UI: composes · Astro pages are built from shared UI components.
- Astro site → Reader pages: routes · Reader site page structure covers content routes.
- Astro site → Backend APIs: fetches · Public pages consume backend frontend APIs.
- Reader UI → Backend APIs: fetches · Interactive components query the backend for content and search data.
- Grafana → MySQL: observes · Dashboards are wired to database metrics and views.
- Netdata → Compose stack: monitors · Netdata monitors the containerized runtime.