Rebuild the site as a terminal-style agent on Astro
My Gatsby Deployment pipeline / build-and-deploy (push) Successful in 1m4s

Replace the single Gatsby page with a dark, terminal-style agent that answers
questions about Dennis's work from one curated knowledge base. There is no
model and no network call, so answers cannot be invented. A plain "Classic
view" and an optional light theme sit one click away.

Site
- Terminal UI (React island): typed answers, tool-call lines, slash commands,
  autocomplete, history, deep links, a short /oncall game
- Content focused on what recruiters scan for; personal and employer-internal
  details are left out
- No profile photo anywhere, including the new link-preview card and icons
- Corrected facts from the old page (dates, titles, tenses, skill tiers)

Tooling
- Migrate Gatsby 5 to Astro 7 (Node 22.23+); builds in about 1 second
- Self-host fonts, so visitors make no request to third parties
- Link-preview card, favicon set, web manifest and a service-worker clean-up
  for returning visitors
- Deploy workflow builds with npm ci on Node 22 and uploads dist/
- Track package-lock.json

Quality
- Tests for routing and for markup injection from visitor input
- A content guard scans every reachable answer; the list of things that must
  never be published lives in a git-ignored local file

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
dennisthiessenandClaude Sonnet 5.5 committed 2026-10-25 22:45:25 +01:00
1 parent 8817235310
commit 61465cc67e
40 files changed
+8625 -480

No files matched your search

+42 -10
View File
@@ -2,26 +2,58 @@
Personal site of **Dennis Thiessen** — Staff Data, Analytics & AI Engineer (Bern, Switzerland).
Built with [Gatsby](https://www.gatsbyjs.com/) 5 and React 18. Single-page, Swiss-minimal design; styles are plain CSS in `src/assets/style.css` (no preprocessor).
Built with [Astro](https://astro.build/) and one React island. The home page is a dark, terminal-style
agent that answers questions about Dennis's work, stack and projects, with a plain page one click away
("Classic view") and an optional light theme. Styles are plain CSS in `src/assets/style.css`
(no preprocessor). Fonts are self-hosted, so visitors make no request to any third party, and the site
uses no analytics.
The content is deliberately focused on what recruiters scan for: current role, headline stack,
what was delivered at each employer and at what scope, education, and contact. Personal, private and
employer-internal details are left out on purpose. `npm test` checks every answer the terminal can give
against a list of things that must never be published; the specifics live in `test/banned.private.json`,
which is git-ignored so the list itself never leaks.
## How the agent works
There is no language model and no network call. Every answer is generated in the browser from one
curated knowledge base, so nothing can be invented.
| Path | Role |
| ---------------------- | ------------------------------------------------------------------------------ |
| `src/data/profile.mjs` | The only place facts live: roles, skills (by how they were used), projects |
| `src/agent/engine.mjs` | Command parser, intent matcher and answer builder. Pure functions, no DOM |
| `src/agent/oncall.mjs` | The short `/oncall` choose-your-path scene |
| `src/components/` | `Terminal` (input, typing effect), `blocks` (answer renderers), `Classic`, `Shell` |
| `src/layouts/Base.astro` | Document shell: fonts, icons, theme script |
| `src/pages/` | `index.astro` (head tags, share card, JSON-LD) and `404.astro` |
| `public/` | Static files copied as-is: share card, icons, web manifest |
| `test/` | Routing tests and a content guard (see below) |
To change what the site says, edit `src/data/profile.mjs`. Skills carry a tier (`now`, `before`, `ai`,
`poc`, `study`); a skill that is not listed is answered with "not in his listed stack" via `NON_CLAIMS`.
Deep links work: `thiessen.io/#/projects`, `#/experience bosch`, `#classic`.
## Develop
```bash
npm install --legacy-peer-deps
npx gatsby develop # http://localhost:8000
```
## Build
Needs Node 22.23 or newer (see `.nvmrc`).
```bash
npx gatsby build # output in ./public
npm install
npm run dev # http://localhost:4321
npm test # node's built-in test runner, no extra dependencies
npm run build # static site in ./dist
npm run preview # serve ./dist locally
```
Use Node 20 (see `.nvmrc`).
After changing `public/icons/icon-512.png`, regenerate the favicon, touch icon and manifest with
`node scripts/make-icons.mjs`.
## Deploy
Pushing to `master` triggers the Gitea Actions workflow in
`.gitea/workflows/workflow.yaml`, which builds the site and rsyncs `public/`
`.gitea/workflows/workflow.yaml`, which builds the site and rsyncs `dist/`
to the web server over SSH. It relies on these repository secrets:
`SSH_PRIVATE_KEY`, `SSH_KNOWN_HOSTS`, `DEPLOY_USER`, `DEPLOY_HOST`, `DEPLOY_PATH`.
The rsync does not delete files that are no longer part of the site.