Skip to content

the climb

Experience

Scroll up the mountain. Each marker is a step from base camp to where I stand today.

  1. 1998–2022 foundation

    Hardware retail

    24 years in hardware retail, mostly at the family business. Decor, renovation, tools, construction — every category, every kind of customer. The kind of job that teaches you what users actually need before you ever put a screen between you and them.

    • Customer service
    • Family business
    • 24 years
  2. 2022–2024 work

    Kasvu Labs Oy

    First paid programming role. Node.js backend, React frontend, working with large sets of open data. Full-stack development, UI design, database management on Azure, product maintenance.

    • Node.js
    • React
    • Open data
    • PostgreSQL
    • Azure
  3. 2024–2025 life

    Becoming a father

    Stepped back from full-time work for family. Personal projects kept moving in the background.

  4. 2025–2026 craft

    AI-native workflows

    Agentic, AI-assisted development as a versioned discipline. Custom Claude Code skills check into the repo as production artifacts — each one teaches the agent a project-specific recipe (add an enemy, ship a database migration, audit the save pipeline) so it goes straight to the work instead of grepping around at $X/token. Pair-programming with parallel subagents on independent slices, then synthesizing the results.

    The skills are version-controlled, audited (drift between a skill and the code it references is a real category of bug — drift gets caught and corrected), and treated as production artifacts. Estimated saving: ~3.13M tokens/year on Spacepotatis alone. Shipping faster without lowering the bar.

    The workflow has its own tooling: claude-continue keeps Claude Code's 5-hour usage windows back-to-back, reading the active window's reset time and resuming paused sessions the moment the next one opens — so a long autonomous run doesn't stall in the gap between windows.

    • Agentic dev
    • Custom skills
    • Subagents
    • claude-continue
    • Versioned workflow
    • Velocity
  5. 2026 project

    The 2026 build

    As of June 2026: nine projects shipped solo in twelve months — full-stack web apps, a desktop tool, and a ReadLog port running live on Azure. Real users, real ops, full ownership from schema to deploy.

    1. Triage before redesign

      When save-corruption hit Spacepotatis in May 2026: server-side guard same day, audit table next day, architectural fix only after a week of real data. Mitigate → observe → architect.

    2. AI workflow as checked-in code

      Spacepotatis ships a catalog of Claude Code skills inside the repo — code-reviewed and audited. ~3.13M tokens saved in their first year.

      Methodology
    3. No tool lock-in

      AudiobookMaker runs three TTS engines under one pipeline — Edge-TTS, Piper, Chatterbox. User picks per book.

    4. Mutation testing > coverage

      HRM runs Stryker on every PR. 91.9% line coverage means the lines ran; the mutation score means the assertions actually catch bugs.

    5. Fix upstream, not locally

      Diagnosed a memory leak deep in Chatterbox's inference path; sent two PRs upstream to resemble-ai/chatterbox (#505, #510), both open and bumped by other contributors.

    6. Solo full-stack, no queues

      SQL, app code, CI, Vercel and Azure deploys, signed Windows installers via GitHub Releases, OpenTelemetry — owned end to end across all nine projects.

    • 9 repos
    • Real users
    • Next.js
    • Astro
    • Three.js
    • Phaser 4
    • Python
    • C#/.NET
    • Azure
    • Turborepo
  6. 2026 craft

    Measured the AI workflow

    After a year of claiming the workflow paid off, I ran the A/B. Every custom Claude Code skill measured against itself going cold — same task, sub-agent on, sub-agent off — across Sonnet, Opus, and Haiku. 34 skills, 33 calibrated. Aggregate save: +17%, ~327K tokens across the portfolio.

    The published registry includes the skills that cost MORE than going cold. Those aren't failures — they encode rigor the cold arm skipped (audit thoroughness, protocol discipline, spec depth). The value is completeness, not compression. The PDF is downloadable from the contact terminal; every number is traceable to a real transcript.

    • A/B calibrated
    • 34 skills
    • Published PDF
    • Honest accounting
    • Sonnet · Opus · Haiku
  7. 2026 craft

    Rust, and checking my own work

    A new language and a harder standard of evidence, arriving together. The language is Rust, picked up for a password manager where the entire cryptographic surface lives in one crate that compiles both natively and to WebAssembly. The command-line vault, the sync server, the in-browser client and the Chrome extension all run that same code, rather than four copies quietly drifting apart.

    The habit was declining to take my own word for anything. The key-derivation parameters, the nonce strategy, what the authenticated ciphertext is bound to: each one is a written decision with a threat model attached, including a plain list of what the design does not protect against. The repository carries auditors of its own for that last part: one walks the decision records against the code, another holds the stated security claims up against what the cryptography actually does. A claim nobody re-checks is just a comment.

    1. One crate, four clients

      Argon2id at 256 MiB and three passes, XChaCha20-Poly1305 with a fresh nonce per entry, and every record bound to its own id and timestamp so two entries cannot be swapped underneath you. The master password never leaves the client and the sync server only ever holds ciphertext. Unlocking costs about 430 ms, which is the feature rather than the regression.

    2. Thirty rounds, blind

      Choosing the Finnish language model for the local stack was settled by ranking thirty Finnish answers blind, scored by a native speaker who could not see which model wrote which. Poro-2-8B placed first in 26 of 30 and went to production on that result. A second project ran the same numbers and passed on it, because the right call depends on how the output gets consumed. Picking either way by feel would have been faster and would have proved nothing.

      Read the study
    3. Usually the bug is mine

      When answers started attaching the wrong dates to my own research, the comfortable story was that a small model was confabulating. It was not. The date was being dropped at the prompt boundary before the model ever saw it. Three earlier attempts to fix it on the model side are written down as dead ends, so the next person to look does not spend the week I did.

    4. A measurement that changed nothing

      A multilingual embedder looked like the obvious upgrade for Finnish retrieval. Measured head to head, the setup already deployed scored .810 against the candidate’s .762, so nothing shipped. The experiment that argues against your plan is worth as much as the one that confirms it, provided you write it down either way.

    • Rust
    • WebAssembly
    • Argon2id
    • XChaCha20-Poly1305
    • Zero-knowledge
    • Threat model in the repo
  8. Now now

    Looking up

    Available now. Open to ambitious full-stack roles where craft and velocity both matter. Nine solo-shipped projects this year — proof of both.

    • Available
    • Remote / Finland