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>
60 lines
3.3 KiB
Markdown
60 lines
3.3 KiB
Markdown
# thiessen.io
|
|
|
|
Personal site of **Dennis Thiessen** — Staff Data, Analytics & AI Engineer (Bern, Switzerland).
|
|
|
|
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
|
|
|
|
Needs Node 22.23 or newer (see `.nvmrc`).
|
|
|
|
```bash
|
|
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
|
|
```
|
|
|
|
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 `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.
|