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 The Hummingbird website service — the executable, the pages, the static assets, and the Docker/Compose deployment. Its README is the operational reference.
Packages/Infrastructure Shared Hummingbird toolkit: declarative routing, the hardened middlewares, the Page/Asset scaffolding, and the pre-rendered localized responses.
Packages/Localization String Catalog lookups, Accept-Language negotiation, and the catalog-derived language list.
Packages/Persistence The Fluent data layer: driver selection, migration registration, and the readiness probe.
Packages/Utility 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 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:

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 & localizationServices/Website/Sources/Library/Catalogs/Localizable.xcstrings (English only out of the box) and the landing / 404 pages under Services/Website/Sources/Library.
  2. Static assetsServices/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.
  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

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:

(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.

S
Description
Comics Community NL official marketplace
https://comicscommunity.nl
Readme
748 KiB
Languages
Swift 96%
Dockerfile 1.5%
CSS 1.4%
Makefile 1.1%