diff --git a/README.md b/README.md index 1fa7fe0..a415db4 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,37 @@ 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: -generate a fresh repository, then run the bootstrap script to stamp in your -site's name and slug. +**`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. ## What's in here | Path | Role | | --- | --- | -| `Services/Website` | The Hummingbird website service (the engine + placeholder content). | -| `Packages/Localization`, `Packages/Persistence` | Reusable packages, **vendored** into every site — each generated repo owns its own copy. | +| [`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. | +| [`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/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. | -The engine is intentionally copied into each site rather than shared as a -remote dependency: a generated site is fully self-contained and can diverge -freely. Engine fixes are propagated to existing sites by hand (or by -re-generating and porting content). +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). + +## 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`. + +See [the service README](Services/Website/README.md) for configuration keys, +persistence, testing, and deployment. ## Generating a new site @@ -54,19 +68,29 @@ 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`. +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. ### 3. Fill in the content Bootstrap leaves reminders, but in short: 1. **Copy & localization** — `Services/Website/Sources/Library/Catalogs/Localizable.xcstrings` - and the landing / 404 pages under `Services/Website/Sources/Library`. + (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. **Secrets** — set a real `DATABASE_PASSWORD` in a git-ignored +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). -4. **Domain models** — the `Persistence` package ships a sample +5. **Domain models** — the `Persistence` package ships a sample `ExampleRecord` / `ExampleRepository`; replace it when you add real data. ### 4. Build & run @@ -83,10 +107,29 @@ make site-mount # docker compose up --build - 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. ## Maintaining the template itself Edit and test the reference site directly — it builds and its tests pass with -the `Site` / `site` placeholders in place. Keep the placeholders intact so the -bootstrap script's targeted replacements keep matching; if you introduce a new -site-specific value, add a matching rewrite line in `Scripts/bootstrap`. +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: + +| 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 | +| `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. diff --git a/Scripts/bootstrap b/Scripts/bootstrap index 34a1120..9660f1e 100755 --- a/Scripts/bootstrap +++ b/Scripts/bootstrap @@ -8,7 +8,7 @@ # # Run once, from the repository root: # -# ./Tools/bootstrap +# ./Scripts/bootstrap # or: make bootstrap # # It is idempotent only in the sense that it self-destructs: once run, the # placeholders are gone and the script (and its scaffolding) are deleted.