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>
3.3 KiB
thiessen.io
Personal site of Dennis Thiessen — Staff Data, Analytics & AI Engineer (Bern, Switzerland).
Built with Astro 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).
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.