Files
bass-foundry/website/README.md
T
nvrl 7e1776bb04
Check and Windows preview / check (anvil) (push) Successful in 49s
Check and Windows preview / check (crucible) (push) Successful in 48s
Check and Windows preview / check (knurl) (push) Successful in 40s
Check and Windows preview / check (lathe) (push) Successful in 41s
Check and Windows preview / check (patina) (push) Successful in 56s
Check and Windows preview / check (rivet) (push) Successful in 45s
Check and Windows preview / check (temper) (push) Successful in 43s
Check and Windows preview / check (weld) (push) Successful in 1m20s
Check and Windows preview / previews (push) Successful in 1m15s
Check and Windows preview / windows (push) Successful in 2m31s
feat(website): add the fl.narl.io site
Astro site for the suite: a home page with the plugin cards, install
steps, principles, the metalwork names and the ideas on the bench, one
page per plugin, and the Impressum and privacy policy. Plugin names,
versions, download links and editor previews come from the catalog, the
wrapper manifests and docs/*/assets at build time.

Served by unprivileged nginx in Docker behind Traefik on fl.narl.io,
the same setup as proton.narl.io: no access logs, CSP 'self', no
JavaScript, legal pages filled from the environment at start.
2026-11-06 11:30:12 +01:00

99 lines
4.9 KiB
Markdown

# Bass Foundry website
The site at [fl.narl.io](https://fl.narl.io): one static [Astro](https://astro.build) site
with a home page, one page per plugin and the legal pages. An unprivileged nginx container
serves it behind Traefik.
The site reads its plugin data from the repository. When a plugin is added or released, the
next build picks it up:
- names, descriptions and CLAP IDs come from `plugins/catalog.json`;
- versions come from `plugins/<plugin>/plugin/Cargo.toml`, and the download links point to
`<plugin>-v<version>` on Gitea;
- editor previews come from `docs/<plugin>/assets/editor.png`.
The site's own copy for each plugin (role, problem, highlights, where to load it, latency) is in
`src/data/plugins.ts`. The build fails if a catalog entry has no copy there. The "On the bench"
ideas are copied from `docs/ideas.md`, so update them by hand when that list changes.
Download links go to the release tag of the version in `Cargo.toml`. Deploy the site after the
release is published, not after the version bump, or the link for that plugin is dead until
the release exists.
The site sets no cookies, stores nothing in the browser and loads nothing from third parties.
Fonts, images and styles all come from the same server, there is no JavaScript, and nginx
writes no access logs. The privacy policy (`src/pages/datenschutz.astro`) says exactly this,
so keep the two in step.
## Development
```sh
cd website
npm ci
npm run dev # http://localhost:4321/
npm run build # astro check, then a static build into dist/
npm run preview
npm run og # re-renders public/og.png
```
`npm run og` sets its text in Roboto Condensed from `plugins/common/ui/assets`, so no font
needs to be installed. The logo is `public/favicon.svg` (copied to `src/assets/logo.svg`): a
riveted steel plate with a knurled saw wave.
The Impressum and the privacy policy contain `%%IMPRESSUM_…%%` placeholders. The container
fills them in when it starts, so the operator's name and address never end up in git.
## Running with Docker
The build context is the repository root, so the image can read the catalog, the versions and
the screenshots. `Dockerfile.dockerignore` keeps the context to those files and `website/`.
```sh
cd website
cp .env.example .env # fill in the Impressum details
docker compose up -d --build
curl -I http://127.0.0.1:8080/
```
| Variable | Required | Used for |
| ------------------- | -------- | -------------------------------------------------------------- |
| `SITE_URL` | build | Canonical links, sitemap, robots.txt, `og:image`. Rebuild to change. |
| `IMPRESSUM_NAME` | yes | Impressum and controller in the privacy policy |
| `IMPRESSUM_STREET` | yes | Street and number (no P.O. box) |
| `IMPRESSUM_CITY` | yes | Postcode and city |
| `IMPRESSUM_EMAIL` | yes | Contact address, written out as HTML entities |
| `IMPRESSUM_COUNTRY` | no | Defaults to `Deutschland` |
| `IMPRESSUM_PHONE` | no | Hides the phone line when empty |
| `HOSTER` | no | Names the hosting provider (Art. 28 GDPR); hidden when empty |
The container refuses to start while a required variable is missing, so the site cannot go
live without an Impressum. The values are escaped and applied to fresh copies of the two pages
on every start, so after changing `.env`, recreating the container (`docker compose up -d`) is
enough. The container listens on 8080 as user 101 with all capabilities dropped. `/healthz`
answers `ok` for health checks.
### Behind Traefik
`compose.override.yaml` puts the site on `fl.narl.io`: router labels, the external `narl`
network, the `websecure` entry point with the `https_resolver` certificate resolver, and
`ports: !reset []` so nothing is published on the host. Docker Compose reads the override file
automatically. TLS ends at Traefik. Redirects are relative, so they keep the proxy's scheme and
host.
**If Traefik writes access logs for this router, the privacy policy is wrong.** It promises no
access logs. Either turn them off for the router, or edit section 3 of `datenschutz.astro` (both
languages): what is logged, why, and for how long.
## Before going live
- **Legal texts.** The Impressum and the privacy policy are written for a private,
non-commercial project hosted in Germany. They are no substitute for legal advice. Update the
"Stand" date when you change them.
- **git.narl.io.** The privacy policy says that the downloads and the source code are on
git.narl.io and that its own privacy information applies there. If you run that Gitea
instance yourself, make sure it has that information.
## License
ISC, like the plugins. Roboto Condensed and Inter are under the SIL Open Font License.