Implemented phase 1 for the POC prototype in the Website service.
This commit is contained in:
1 parent
6d7ab4bcba
commit
ea89ea892a
37 files changed
+4173
-43
No files matched your search
@@ -1,9 +1,10 @@
|
||||
# CCN Website
|
||||
The **CCN** public website service — a [Hummingbird](https://github.com/hummingbird-project/hummingbird) server that renders a static landing page and serves the site's static assets.
|
||||
The **CCN** public website service — a [Hummingbird](https://github.com/hummingbird-project/hummingbird) server that renders the CCN marketplace prototype and serves the site's static assets.
|
||||
|
||||
## Overview
|
||||
The service:
|
||||
- Serves the landing page at `GET /` (rendered once per supported language with [Elementary](https://github.com/elementary-swift/elementary) and cached), plus one prefixed route per non-default catalog language — `GET /nl` and so on (see [Language editions](#language-editions)).
|
||||
- Serves the public catalogue, rendered per request: search results at `GET /search` (filtered through its query parameters), a listing at `GET /listing/{slug}`, and a seller's shop at `GET /shop/{slug}`; an unknown slug gets the not-found page (see [Catalogue](#catalogue)).
|
||||
- Negotiates each request's language from the `lang` query parameter, the leading path segment, then its `Accept-Language` header, against the languages in the `WebsiteLibrary` String Catalog, falling back to the default (`en`) — asked for only where the answer is used, the bare landing route and the not-found page; pages are served from the per-language cache with `Content-Language` and `Vary: Accept-Language` headers.
|
||||
- Builds every page on the shared `Page` scaffolding from `Infrastructure`, which assembles the document head around the page's own markup: the viewport declaration, the optional `description` summary and `rel="canonical"` link, the Open Graph / Twitter link-preview tags, the JSON-LD structured-data script, and the optional analytics tracker (see [Page metadata](#page-metadata)).
|
||||
- Answers a liveness check at `GET /health` with a static JSON payload, and a readiness check at `GET /health/ready` that reports whether the database is reachable (`200` ready / `503` unavailable).
|
||||
@@ -46,6 +47,7 @@ LogRequestsMiddleware
|
||||
→ NotFoundMiddleware (negotiates the language, renders the not-found page on .notFound)
|
||||
→ FileMiddleware (serves Resources/Static)
|
||||
RootController (GET / → landing page, language negotiated; GET /<lang> → its other editions)
|
||||
CatalogueController (GET /search, GET /listing/{slug}, GET /shop/{slug} → rendered per request)
|
||||
HealthController (GET /health → liveness, GET /health/ready → readiness)
|
||||
```
|
||||
|
||||
@@ -58,6 +60,14 @@ The screens follow the **CCN marketplace** design canvas:
|
||||
- **Shared frame**: `SiteHeader`, `SiteFooter`, and the `SiteLayout` a page wraps its `content` in, under `Sources/Library/Internal/Components`.
|
||||
- **Paths**: `String.Route` lists every screen's path; screens not built yet answer with the not-found page.
|
||||
|
||||
### Catalogue
|
||||
- **Data**: `Persistence`'s `CatalogueRepository` reads the shops and listings; the in-memory backend is migrated and seeded with demo data at launch.
|
||||
- **Landing page**: rendered once and cached, so its listing rows are a snapshot taken at launch (`HomeListings`).
|
||||
- **Search and shop**: `SearchParameters` turns the query string into a `ListingFilter` and builds every link that changes it — filter pills, tabs, pagination — so the screens work as plain `GET` forms and links. Searches default to listings shipping from the EU.
|
||||
- **Gated actions**: buy, offer, message, save, and follow link to the sign-in path with a `return` parameter; the sign-in screen itself is not built yet.
|
||||
- **Covers**: listings have no photos yet, so `Cover` draws a placeholder from the listing's lettering and tone.
|
||||
- **Scripts**: `js/shared.js` only submits the sort select on change and opens the filter rail on older desktop browsers; everything works without it.
|
||||
|
||||
### Page metadata
|
||||
Each page conforms to `Infrastructure`'s `Page` protocol and supplies only its `title`, `content`, `stylesheets`, and `scripts`; the protocol assembles the document around them and renders the head in a fixed order: the viewport declaration, the `analytics` origin preconnect hint, the `summary`, the `canonicalURL` link, the `socialCard` tags, the `structuredData` script, the `analytics` tracker script, then the page `metadata` and the stylesheet links. The body is the content followed by the script tags.
|
||||
|
||||
@@ -260,7 +270,7 @@ Unlike a direct `swift run`, these targets inherit the exported `.env` values (s
|
||||
The service persists data through Fluent and selects its backend at runtime with `database.driver`.
|
||||
|
||||
### In-memory (default)
|
||||
With no configuration, the service uses an ephemeral in-memory SQLite database. It is created and **migrated on startup** every launch, so `swift run Website` and `docker compose up` work with no external database — ideal for local development and tests.
|
||||
With no configuration, the service uses an ephemeral in-memory SQLite database. It is created, **migrated, and seeded with the demo catalogue** on every launch, so `swift run Website` and `docker compose up` work with no external database — ideal for local development and tests.
|
||||
|
||||
### PostgreSQL
|
||||
Set `DATABASE_DRIVER=postgres` and the connection values (`DATABASE_HOST`, `DATABASE_NAME`, `DATABASE_USERNAME`, `DATABASE_PASSWORD`, …). Unlike the in-memory backend, PostgreSQL is **not** migrated on boot — a shared database is migrated out of band so multiple instances never race:
|
||||
|
||||
Reference in new issue
Block a user