Commit Graph
111 Commits
Author SHA1 Message Date
javier 6c66ea74cc Localization support for the Website service (#10)
This PR contains the work done to introduce server-side localization support to the **Website** service so the landing and error pages are served in the visitor's negotiated language, backed by a new reusable Localization package.

To provide further details about the work:

* Created the _Localization_ package — a bundle-bound `Localize` method and a `LanguageList` type.
* Language negotiation — `NegotiateLanguage` method picks the best supported language from the request's _Accept-Language_ header (falling back to the default); the `LocalizationMiddleware` middleware resolves it per request and stores it on a new `LocalizedRequestContext` / `WebsiteRequestContext` context.
* Localized responses — `LocalizedHTMLCollectionResponse` pre-renders each page once per language and caches the bytes (with `Content-Language` + `Vary: Accept-Language`), reused by the  `RootController` controller and `NotFoundMiddleware` middleware.
* The `CachedHTMLResponse` response gained custom-header support.
* Localized pages — the `IndexPage` and `ErrorPage` pages now resolve their strings via `Localize` method;
* Added `Localizable.xcstrings` catalogs.
* Wired the `LocalizationMiddleware` middlewaer into the router.

Reviewed-on: rock-n-code/loud-amsterdam#10
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-29 23:08:36 +00:00
javier 847058d642 Optimizations for the Website service (#9)
This PR contains the work done to provide optimizations to the current service, such as a health-check endpoint, pre-renders static HTML pages, and hardens the error page's CSP.

To provide further details about the work:

* Added the `HealthController` controller serving GET `/health` with a static JSON payload.
* Added the `CachedHTMLResponse` response, which renders a static HTMLDocument to bytes once and reuses them per request (no Content-Length, so responses stay compressible).
* Integrated the response into the `RootController` and the  `NotFoundMiddleware` middleware to avoid re-rendering on hot paths.
* Added a `RouterMethods.addRoutes(_:)` extension and switched the router in App+build to use it.
* Moved the inline style from the `ErrorPage` page into a dedicated style file so the CSP needs no inline-style escape hatch.
* Fixed the `IndexPage` page path inconsistencies.
* Written the `README` file.

Reviewed-on: rock-n-code/loud-amsterdam#9
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-28 14:18:04 +00:00
javier 6b6389cb0f Security header setup for the Website service (#8)
This PR contains the work done to add a `SecurityHeadersMiddleware` middleware that stamps hardened security-related HTTP headers onto every response.

To provide further details about the work:

* Implemented the `SecurityHeadersMiddleware` middleware, which precomputes headers once from a `Configuration` object and applies them to every response:
  * _Content-Security-Policy_,
  * _X-Content-Type-Options_,
  * _X-Frame-Options_,
  * _Referrer-Policy_,
  * _Permissions-Policy_,
  * _Strict-Transport-Security_ (optional).
* Integrated this middleware into the router (near the top of the chain), reading each value from configuration with hardened defaults.
* The _Strict-Transport-Security_ has no default value — omitted unless explicitly set, so it stays off in plain-HTTP during development and on only behind TLS.
* Added security-header constants keys and values.

Reviewed-on: rock-n-code/loud-amsterdam#8
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-28 11:35:54 +00:00
javier 7c18cd9ec0 Response compression for the Website service (#7)
This PR contains the work done to add response compression to the Website service by registering the `ResponseCompressionMiddleware` middleware so responses are compressed when the client advertises support and the body exceeds a minimum size.

To provide further details about the work done:

* Added the **HummingbirdCompression** package dependency.
* Integrated the `ResponseCompressionMiddleware` middleware into the router, ahead of the not-found and static file middleware.
* Made the `minimum-response-size-to-compress` threshold configurable, with a default.

Reviewed-on: rock-n-code/loud-amsterdam#7
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-28 06:15:05 +00:00
javier 6c1a0f713b Static file caching for the Website service (#6)
This PR contains the work done to add cache-control headers to static file responses by configuring the `FileMiddleware` middleware to tag served static files with *Cache-Control* directives, tuned per media type.

To provide further details about the work done:

* Added a cache control that sets per-type policies: text assets (CSS/JS) get public, max-age, must-revalidate; images get public, max-age; everything else gets a default public, max-age.
* Files stay validated via `ETag/Last-Modified` header.
* Made the max-age values configurable, with defaults, via new cache constants.

Reviewed-on: rock-n-code/loud-amsterdam#6
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-28 05:49:32 +00:00
javier a621ada0bf HTML rendering support for the Website service (#5)
This PR contains the work done to replace the use of static _HTML_ files with type-safe HTML rendered server-side via **Elementary** through **Hummingbird**.

To provide further details about the work done:

* Added the **Elementary** dependencies.
* Added the `IndexPage` and `ErrorPage` pages, ported from the old HTML boilerplate; removed the static files.
* Added the `RootController` controller serving GET / using the `IndexPage` page, wired into the router.
* Reworked the `NotFoundMiddleware` middleare to render `ErrorPage` page directly; non-notFound errors still propagate.
* the `FileMiddleware` middleware no longer searches for any static `index.html` file.
* Simplified the `StaticFile` enumeration, dropped unused constants and now-unnecessary throws.

Reviewed-on: rock-n-code/loud-amsterdam#5
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-28 05:07:19 +00:00
javier f5f14eb97c File not found middleware for the Website service (#4)
This PR contains the work done to add a `NotFoundMiddleware` middleware to the Website service so requests matching neither a route nor a static file return a custom 404.html page with a 404 Not Found status. Also enables index.html fallback so the landing page is served at the site root.

To provider further details about the work done:
* NotFoundMiddleware — intercepts the `.notFound` error from the  `FileMiddleware` middleware and serves the preloaded error page with the correct content type; all other errors propagate. Falls back to a minimal body if the file is missing.
* Router — wires the `NotFoundMiddleware` middleware ahead of the `FileMiddleware` and enables searchForIndexHtml.
* Package — adds the **Hummingbird** product to the Library target.
* Tooling — sets a custom working directory in the Xcode scheme; removes the unused `pkg-deps` target from the `Makefile` file.

Reviewed-on: rock-n-code/loud-amsterdam#4
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-27 12:16:50 +00:00
javier 7542bc595f Static file serving support for the Website service (#3)
This PR contains the work done to support the static files serving for the **Website** service, and also included the essential boilerplate assets from the **HTML5 boilerplate** project.

To provide further details about the work done:

* Serving: Added the `FileMiddleware` middlewqare to the router; `path`, `server name`, and `log level` now read from config with defaults.
* Library: Added the `StaticFile` enumeration with a `contentType` property, plus typed config-key/value constants and the `Configuration` dependency on WebsiteCore.
* Assets: Added the **HTML5 boilerplate** (HTML, CSS, JS, icons, manifest, robots) to the *Resources/Static* folder.
* Docker: Stage the Resources directory as read-only.
* Tests: Added a test plan, and a shared Xcode scheme.

Reviewed-on: rock-n-code/loud-amsterdam#3
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-27 10:59:32 +00:00
javier 08b210e7c6 Website service target setup (#2)
This PR contains the work done to add and setup the *Website* service target, a **Hummingbird** server app, into the Xcode project as a SwiftPM package with full support for containerization and driven by a `Makefile` file.

To provide further details about the work done:

* Swift package — SwiftPM manifest with a Website executable, related library, and test targets; depends on **hummingbird** and **swift-configuration**.
* Containerization — Multi-stage `Dockerfile` producing a static-linked release build with jemalloc, running as a non-root user on port 8080. Production and local-dev `docker-compose` files included.
* Configuration — `.env.local` template (with `.env` git-ignored) and `.dockerignore`/`.gitignore` entries.
* Makefile — Self-documenting operational commands:
  * pkg — SwiftPM: _build, release, test, clean, reset, deps, outdated, update_
  * img — Docker lifecycle: _build, mount, unmount, release_

Notes

* New service only — no changes to existing code; nothing else in the repo is affected.
* App logic is currently scaffolding; this PR establishes the service structure, build, and deployment tooling.

Reviewed-on: rock-n-code/loud-amsterdam#2
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-27 02:26:33 +00:00
javier a15271772e Xcode project setup (#1)
This PR contains the work done to setup the *Xcode* project, with its `.gitignore` and `.swift-format` files.

Reviewed-on: rock-n-code/loud-amsterdam#1
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-06-26 21:08:28 +00:00
javier e3e278dacb Initial Commit 2026-06-26 15:44:05 +02:00