From 6ecc20987fde2c933594ec56f6805b3feeddfad1 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Thu, 20 Aug 2026 01:10:37 +0200 Subject: [PATCH] Updated the README file in the repository root. --- README.md | 126 +++++++++++++++++++++++++++++------------------------- 1 file changed, 68 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index a415db4..1790d21 100644 --- a/README.md +++ b/README.md @@ -1,97 +1,97 @@ # Website Template -This repository is a **template** for the platform's websites. It ships as a -complete, buildable reference site whose identity is the neutral placeholder -**`Site`** / **`site`**. You generate a real site from it in two steps: create -a fresh repository, then run the bootstrap script to stamp in your site's -display name, slug, and canonical URL. +A **template** for the platform's websites, shipping as a complete, buildable +reference site under the placeholder identity **`Site`** / **`site`**. Generating +a real site takes two steps: create a fresh repository, then run the bootstrap +script to stamp in the display name, slug, and canonical URL. ## What's in here | Path | Role | | --- | --- | -| [`Services/Website`](Services/Website/README.md) | The Hummingbird website service — the executable, the pages, the static assets, and the Docker/Compose deployment. Its README is the operational reference. | -| [`Packages/Infrastructure`](Packages/Infrastructure/README.md) | Shared Hummingbird toolkit: declarative routing, the hardened middlewares, the `Page`/`Asset` scaffolding, and the pre-rendered localized responses. | +| [`Services/Website`](Services/Website/README.md) | The Hummingbird website service — executable, pages, static assets, Docker/Compose deployment. Its README is the operational reference. | +| [`Packages/Infrastructure`](Packages/Infrastructure/README.md) | Shared Hummingbird toolkit: declarative routing, the hardened middlewares, the `Page`/`Asset` scaffolding, the head-metadata types (`SocialCard`, `StructuredData`, `Analytics`), and the pre-rendered localized responses. | | [`Packages/Localization`](Packages/Localization/README.md) | String Catalog lookups, `Accept-Language` negotiation, and the catalog-derived language list. | -| [`Packages/Persistence`](Packages/Persistence/README.md) | The Fluent data layer: driver selection, migration registration, and the readiness probe. | +| [`Packages/Persistence`](Packages/Persistence/README.md) | The Fluent data layer: driver selection (in-memory SQLite or PostgreSQL), migration registration, and the readiness probe. | | [`Packages/Utility`](Packages/Utility/README.md) | Dependency-free helpers shared across the services. | | `Site.xcodeproj` | The umbrella Xcode project (renamed to your site by bootstrap). | | `Scripts/bootstrap` | The generator. Rewrites placeholders, then deletes itself. | | `Makefile` | Bootstrap convenience only (`make bootstrap`); removed by the script. | All four packages are **vendored**, not fetched: the service depends on them by -relative path, so each generated repository owns its own copy. That is -deliberate — a generated site is fully self-contained and can diverge freely. -The trade-off is that engine fixes are propagated to existing sites by hand (or -by re-generating and porting content). +relative path, so every generated repository owns its copy and can diverge +freely. The trade-off is that engine fixes reach existing sites only by hand. ## Requirements - Swift 6.3 toolchain (every manifest is `swift-tools-version:6.3`). -- Docker — optional, for the containerized run/deploy workflow. -- The Hummingbird CLI (`hb`) — optional, only for `make site-run`. +- Docker — optional: the containerized run/deploy workflow, the local PostgreSQL + instance (`make db-mount`), and the asset-optimization preview. +- Hummingbird CLI (`hb`) — optional, only for `make site-run`. -See [the service README](Services/Website/README.md) for configuration keys, -persistence, testing, and deployment. +Configuration keys, persistence, testing, and deployment are documented in +[the service README](Services/Website/README.md). ## Generating a new site ### 1. Create a repository from this template -On Gitea, mark this repository as a template once (repository **Settings → -Template → “Template” checkbox**). New sites are then created with the -**“Use this template”** button, which produces a fresh repository with its own -history — no template commits carried over. +On Gitea, mark this repository as a template once (**Settings → Template → +“Template”**); new sites then come from the **“Use this template”** button, each +with its own history. -> No Gitea button? Just clone this repo, `rm -rf .git`, and continue — the -> bootstrap script offers to re-initialise git for you. +> No Gitea button? Clone this repo, `rm -rf .git`, and continue — bootstrap +> offers to re-initialise git. ### 2. Bootstrap -Clone the new repository, then from its root run: +From the new repository's root: ```sh make bootstrap # or: ./Scripts/bootstrap ``` -You'll be asked for: - | Prompt | Example | Rewrites | | --- | --- | --- | | **Site display name** (PascalCase) | `Loud` | Server name (`LoudWebsite`), `Loud.xcodeproj`, README title. | | **Project slug** (lowercase) | `loud-ams` | Container owner, database name/user, Compose project name. | | **Canonical site URL** (scheme + host) | `https://loud.amsterdam` | The `Sitemap:` reference in `robots.txt` and the `` entry in `sitemap.xml`. | -The canonical URL defaults to the reserved placeholder `https://site.example.com`; -leaving it there is allowed (the script warns), so you can bootstrap before the -domain is decided and set it later in the two crawler files. - -The script rewrites the placeholder occurrences in place, renames -`Site.xcodeproj`, optionally starts a fresh git history, and then removes -itself along with this file and the root `Makefile`. It refuses to run outside -the repository root, and validates the URL before touching anything — a -rejected value leaves the tree untouched, so it is safe to re-run. - -Accepting the default display name (`Site`) is supported: the rename is skipped -and the placeholders simply stay in place. +- The URL defaults to the reserved `https://site.example.com`; leaving it is + allowed (the script warns) and can be corrected later in the two crawler files. +- Keeping the default display name `Site` is allowed too: the Xcode rename is + skipped and the placeholders stay in place. +- The script refuses to run outside the repository root and validates the URL + before writing, so a rejected value leaves the tree untouched. +- It rewrites in place, renames `Site.xcodeproj`, optionally starts a fresh git + history, then deletes itself, this file, and the root `Makefile`. ### 3. Fill in the content -Bootstrap leaves reminders, but in short: - 1. **Copy & localization** — `Services/Website/Sources/Library/Catalogs/Localizable.xcstrings` (English only out of the box) and the landing / 404 pages under `Services/Website/Sources/Library`. 2. **Static assets** — `Services/Website/Resources/Static` (CSS, JS, favicon, icons). The manifest's `name` / `short_name` are empty and are not rewritten by bootstrap. 3. **Head metadata** — the pages ship no `summary`, `canonicalURL`, `socialCard`, or - `structuredData`, so there is no meta description, no link preview, and no JSON-LD - until you supply them. See - [Page metadata](Services/Website/README.md#page-metadata). -4. **Secrets** — set a real `DATABASE_PASSWORD` in a git-ignored - `Services/Website/.env` (the committed `.env.local` is an example only). -5. **Domain models** — the `Persistence` package ships a sample - `ExampleRecord` / `ExampleRepository`; replace it when you add real data. + `structuredData`: no meta description, no link preview, no JSON-LD until you + supply them. See [Page metadata](Services/Website/README.md#page-metadata). +4. **Analytics** — the cookieless [Umami](https://umami.is) tracker ships **off** + (`analytics.websiteID` is empty, so no third-party script is requested). + Enabling it, in order: point `String.Analytics.origin` at the instance you + report to, allow that origin in `security.contentSecurityPolicy` (`.env.local` + already does; `docker-compose.yml` falls back to a `'self'`-only policy), then + set `ANALYTICS_WEBSITE_ID`. `ANALYTICS_DOMAINS` limits which hosts report; + `ANALYTICS_RECORDER` opts into the session recorder. See + [Analytics](Services/Website/README.md#analytics). +5. **Secrets** — set a real `DATABASE_PASSWORD` in a git-ignored + `Services/Website/.env`; the committed `.env.local` is an example and defaults + the password to the slug. +6. **Domain models** — replace the `Persistence` package's sample `ExampleRecord` + / `ExampleRepository`. The default driver is in-memory SQLite, migrated on + every boot; a real site sets `DATABASE_DRIVER=postgres` and migrates out of + band (`swift run Website --database-migrate`). See + [Persistence](Services/Website/README.md#persistence). ### 4. Build & run @@ -105,31 +105,41 @@ make site-mount # docker compose up --build ## What bootstrap does NOT change - Organisation (`Röck+Cöde VoF`) and Xcode `DEVELOPMENT_TEAM` — shared across all sites. -- The package architecture, middleware, security headers, and persistence layer. -- The generic `website` image name and `Makefile` command names (`site-run`, `site-mount`, …). -- The four `Packages/*/README.md` files — no rewrite line covers them, so whatever - site name they mention ships as-is into every generated repository. +- The package architecture, middlewares, security headers, and persistence layer + (PostgreSQL, behind the in-memory SQLite default). +- The analytics origin: `String.Analytics.origin` and the `Content-Security-Policy` + in `.env.local` that allows it both name the platform's shared Umami instance. + Tracking stays off until a site sets `ANALYTICS_WEBSITE_ID`. +- The generic `website` image name and the `Makefile` target names (`site-run`, + `site-mount`, …). +- The four `Packages/*/README.md` files and the package sources — no rewrite line + covers them, so whatever site name they carry ships as-is. `Packages/Persistence`'s + PostgreSQL integration test defaults its `POSTGRES_TEST_*` credentials to `site`. ## Maintaining the template itself -Edit and test the reference site directly — it builds and its tests pass with -the `Site` / `site` placeholders in place: +Edit and test the reference site directly — it builds and its tests pass with the +`Site` / `site` placeholders in place: ```sh (cd Services/Website && make pkg-test) # the service's own two test targets (cd Packages/Infrastructure && swift test) # and likewise for each vendored package ``` -Keep the placeholders intact so the bootstrap script's targeted replacements -keep matching. They are: +No external infrastructure is needed: `Packages/Persistence`'s PostgreSQL +integration test skips itself unless `POSTGRES_TEST_HOST` is set. To run it, +start the database (`cd Services/Website && make db-mount`), then +`POSTGRES_TEST_HOST=127.0.0.1 swift test`. + +Keep the placeholders intact so the bootstrap rewrites keep matching: | Placeholder | Appears in | | --- | --- | | `Site` | Xcode project name and `project.pbxproj`, the service README title | | `SiteWebsite` | `String+Constants.swift`, `.env.local`, `docker-compose.yml`, the service README | -| `site` | `String+Constants.swift` defaults, `HOST_OWNER` / `DATABASE_*` in `.env.local` and Compose, the `site-platform` Compose project, the `Makefile` `db-shell` fallbacks | +| `site` | `String+Constants.swift` defaults, `HOST_OWNER` / `DATABASE_*` in `.env.local` and both Compose files, the `site-platform` Compose project, the `Makefile` `db-shell` fallbacks | | `https://site.example.com` | `Resources/Static/robots.txt`, `Resources/Static/sitemap.xml` | -If you introduce a new site-specific value, give it a placeholder from this set -and add a matching rewrite line in `Scripts/bootstrap` — a value that no rewrite -covers ships verbatim into every generated site. +A new site-specific value needs a placeholder from this set and a matching +rewrite line in `Scripts/bootstrap`; anything else ships verbatim into every +generated site.