Files
ccn/README.md
T

136 lines
6.6 KiB
Markdown

# 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.
## 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. |
| [`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. |
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
### 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.
> No Gitea button? Just clone this repo, `rm -rf .git`, and continue — the
> bootstrap script offers to re-initialise git for you.
### 2. Bootstrap
Clone the new repository, then from its root run:
```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 `<loc>` 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.
### 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.
### 4. Build & run
```sh
cd Services/Website
make site-run # watch + rebuild
# or
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.
## Maintaining the template itself
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:
| 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.