# 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.