Toppen av klättringen, så här långt.
Sidan slutar här. Härifrån finns två vägar vidare.
Teknologier
Vad jag faktiskt har byggt med. Öppna en rad för att se vad som ligger under.
Språk
-
TypeScript / JavaScript jobb
- Zod
-
Python
- PyTorch
- PyMuPDF
- ebooklib
- Tesseract
- ffmpeg
- CustomTkinter
-
C#
- .NET 8
- ASP.NET Core
- Razor Pages
- ASP.NET Identity
- EF Core
-
Rust
- Tokio
- axum
- Dioxus
- zbus
- WebAssembly
- Argon2id
- XChaCha20-Poly1305
- zeroize
-
Bash
-
AppleScript
- iTerm2 automation
Frontend
-
Next.js jobb
- NextAuth
- next-intl
-
React jobb
- MUI jobb
- Recharts jobb
- ReactFlow
- framer-motion
-
Astro
-
Three.js
- GSAP
- postprocessing
-
Phaser 4
-
Web Audio API
- Strudel
-
Tailwind CSS
-
Chrome Extension (MV3)
Backend och data
-
PostgreSQL jobb
- Prisma
- PgTyped jobb
- Kysely
- pgvector
- pg-boss
-
Node.js jobb
- Pino
-
MongoDB
-
SQLite
-
FastAPI
- asyncpg
AI och språkmodeller
-
Claude Code
- Subagents
- Skills
- Hooks
- MCP
- Plugins
- Permission allowlists
- Skill calibration
-
Anthropic API
-
Ollama
-
RAG
- pgvector
- fastembed
- BM25
- lingua
- FastAPI
- Ollama
- Tailscale Funnel
- Microsoft.Extensions.AI
-
Text-to-speech
- Edge-TTS
- Piper
- Chatterbox
- VoxCPM2
- Qwen VoiceDesign
-
Microsoft.Extensions.AI
Plattform
-
Docker
- Docker Compose
-
Kubernetes jobb
- Helm
-
Azure jobb
- App Service
- Static Web Apps
- Functions
-
Vercel
-
GitHub Actions
- CodeQL
-
Testing jobb
- Jest
- Vitest
- Playwright
- pytest
- xUnit
- Stryker
- jest-axe
-
Observability
- OpenTelemetry
- Sentry
-
Packaging
- PyInstaller
- macOS .app bundle
- launchd
- Inno Setup
- Task Scheduler
-
Turborepo
-
Tailscale Funnel
HRM 27
- TypeScript / JavaScript
- Zod
- Next.js
- NextAuth
- next-intl
- React
- MUI
- ReactFlow
- PostgreSQL
- Prisma
- pg-boss
- Pino
- MongoDB
- Anthropic API
- Docker
- Docker Compose
- Helm
- Vercel
- GitHub Actions
- Testing
- Jest
- Playwright
- Stryker
- jest-axe
- Observability
- OpenTelemetry
- Sentry
Platform 16
- TypeScript / JavaScript
- Zod
- Next.js
- NextAuth
- next-intl
- React
- MUI
- framer-motion
- PostgreSQL
- Prisma
- Vercel
- Testing
- Jest
- Playwright
- jest-axe
- Turborepo
Portfolio 26
- TypeScript / JavaScript
- Astro
- Three.js
- GSAP
- postprocessing
- Tailwind CSS
- asyncpg
- Permission allowlists
- RAG
- pgvector
- fastembed
- BM25
- lingua
- FastAPI
- Docker
- Docker Compose
- Vercel
- GitHub Actions
- CodeQL
- Testing
- Vitest
- Playwright
- pytest
- Observability
- Sentry
- Tailscale Funnel
ReadLog 10
- TypeScript / JavaScript
- Next.js
- NextAuth
- React
- MUI
- PostgreSQL
- Prisma
- Vercel
- Testing
- Jest
ReadLog .NET 12
- .NET 8
- ASP.NET Core
- Razor Pages
- ASP.NET Identity
- EF Core
- SQLite
- Docker
- Azure
- App Service
- GitHub Actions
- Testing
- xUnit
AudiobookMaker 18
- Python
- PyTorch
- PyMuPDF
- ebooklib
- Tesseract
- ffmpeg
- CustomTkinter
- Text-to-speech
- Edge-TTS
- Piper
- Chatterbox
- VoxCPM2
- Qwen VoiceDesign
- GitHub Actions
- pytest
- Packaging
- PyInstaller
- Inno Setup
Spacepotatis 14
- TypeScript / JavaScript
- Zod
- Next.js
- NextAuth
- React
- Three.js
- GSAP
- Phaser 4
- Tailwind CSS
- PostgreSQL
- Kysely
- Vercel
- Testing
- Vitest
Strudel Patterns 4
- TypeScript / JavaScript
- Web Audio API
- Strudel
- Claude Code
claude-continue 9
- Python
- AppleScript
- iTerm2 automation
- GitHub Actions
- Packaging
- PyInstaller
- macOS .app bundle
- launchd
- Task Scheduler
PasswordManager 11
- TypeScript / JavaScript
- Rust
- Tokio
- axum
- WebAssembly
- Argon2id
- XChaCha20-Poly1305
- zeroize
- Chrome Extension (MV3)
- SQLite
- GitHub Actions
claude-agents 9
- Bash
- Claude Code
- Subagents
- Skills
- Hooks
- MCP
- Plugins
- Permission allowlists
- Skill calibration
Feedback Intelligence 15
- C#
- .NET 8
- Node.js
- SQLite
- RAG
- Ollama
- Microsoft.Extensions.AI
- Docker
- Azure
- Static Web Apps
- Functions
- GitHub Actions
- CodeQL
- Testing
- xUnit
jobb = använt i kundarbete. Resten kommer från mina egna produktionsprojekt.
-
Blickar uppåt
Tillgänglig nu. Öppen för ambitiösa full-stack-roller där både hantverk och tempo räknas. Nio solo-levererade projekt i år — bevis på båda.
-
Rust, och att kontrollera mitt eget arbete
Ett nytt språk och ett hårdare beviskrav kom samtidigt. Språket är Rust, plockat upp för en lösenordshanterare där hela den kryptografiska ytan bor i en enda crate som kompilerar både nativt och till WebAssembly. Kommandoradsvalvet, synkroniseringsservern, klienten i webbläsaren och Chrome-tillägget kör alla samma kod, i stället för fyra kopior som tyst glider isär.
Vanan var att vägra ta mitt eget ord för något. Parametrarna för nyckelderivering, nonce-strategin, vad den autentiserade krypterade texten är bunden till: var och en är ett nedskrivet beslut med en hotmodell bifogad, inklusive en tydlig lista över vad designen inte skyddar mot. Repot bär egna granskare för just den sista punkten: en går igenom besluten mot koden, en annan håller de uttalade säkerhetspåståendena mot vad kryptografin faktiskt gör. Ett påstående som ingen kontrollerar igen är bara en kommentar.
-
En crate, fyra klienter
Argon2id på 256 MiB och tre pass, XChaCha20-Poly1305 med en färsk nonce per post, och varje post bunden till sitt eget id och sin egen tidsstämpel så att två poster inte kan bytas ut under dig. Huvudlösenordet lämnar aldrig klienten, och synkroniseringsservern håller alltid bara krypterad text. Att låsa upp kostar omkring 430 ms, vilket är funktionen snarare än regressionen.
-
Trettio rundor, blint
Valet av finsk språkmodell för den lokala stacken avgjordes genom att rangordna trettio finska svar blint, bedömda av en modersmålstalare som inte kunde se vilken modell som skrev vad. Poro-2-8B placerade sig först i 26 av 30 och gick till produktion på det resultatet. Ett andra projekt körde samma siffror och avstod, eftersom rätt val beror på hur utdatan används. Att välja åt något håll på känsla hade gått snabbare och hade inte bevisat något.
Läs studien -
Oftast är buggen min
När svaren började koppla fel datum till min egen forskning var den bekväma förklaringen att en liten modell hallucinerade. Det gjorde den inte. Datumet föll bort vid prompt-gränsen innan modellen någonsin såg det. Tre tidigare försök att fixa det på modellsidan är nedskrivna som återvändsgränder, så nästa person som tittar inte behöver lägga ner en vecka som jag gjorde.
-
En mätning som inte ändrade något
En flerspråkig embedder såg ut som den självklara uppgraderingen för finsk retrieval. Uppmätt sida vid sida fick den redan driftsatta uppsättningen 0,810 mot kandidatens 0,762, så inget skeppades. Experimentet som talar emot din plan är lika mycket värt som det som bekräftar den, förutsatt att du skriver ner det ändå.
-
-
Mätte AI-arbetsflödet
Efter ett år av att hävda att arbetsflödet lönade sig körde jag A/B. Varje anpassad Claude Code-skill mätt mot sig själv kall — samma uppgift, delagent på, delagent av — på Sonnet, Opus och Haiku. 34 skills, 33 kalibrerade. Aggregerad besparing: +17 %, ~327K token över portföljen.
Det publicerade registret inkluderar skillsen som kostade MER än att gå kall. De är inte misslyckanden — de bär stringens som den kalla armen hoppade över (auditgrundlighet, protokolldisciplin, spec-djup). Värdet är fullständighet, inte komprimering. PDF:en går att ladda ner från contact-terminalen; varje siffra är spårbar till ett riktigt transkript.
-
2026 — byggåret
I juni 2026: nio projekt levererade solo på tolv månader — full-stack-webbappar, ett skrivbordsverktyg och en ReadLog-portning som körs live på Azure. Riktiga användare, riktig drift, fullt ägarskap från schema till deploy.
-
Triage före omdesign
När save-korruption slog till i Spacepotatis i maj 2026: serversideguard samma dag, audit-tabell dagen efter, arkitektonisk fix först efter en vecka av riktig data. Mitigera → observera → arkitektur.
-
AI-flöde som incheckad kod
Spacepotatis levererar en uppsättning Claude Code-skills i repot — kodgranskade och auditerade. ~3,13M token sparat under första året.
Metod -
Ingen verktygsinlåsning
AudiobookMaker kör tre TTS-motorer under en pipeline — Edge-TTS, Piper, Chatterbox. Användaren väljer per bok.
-
Mutationstestning > coverage
HRM kör Stryker på varje PR. 91,9 % radtäckning betyder att raderna kördes; mutationspoäng betyder att assertions faktiskt fångar buggar.
-
Fixa uppströms, inte lokalt
Diagnostiserade en minnesläcka djupt i Chatterboxs inferensbana; skickade två PR:ar uppströms till resemble-ai/chatterbox (#505, #510), båda öppna och bumpade av andra bidragsgivare.
-
Solo full-stack, inga köer
SQL, app-kod, CI, Vercel- och Azure-deployer, signerade Windows-installerare via GitHub Releases, OpenTelemetry — ägt från ände till ände över alla nio projekt.
-
-
AI-nativa arbetsflöden
Agentisk, AI-assisterad utveckling som en versionerad disciplin. Anpassade Claude Code-skills checkas in i repot som produktionsartefakter — varje skill lär agenten ett projektspecifikt recept (lägg till en fiende, släpp en databasmigration, granska sparpipelinen) så att den går rakt på sak istället för att grepa runt vid $X/token. Parprogrammering med parallella delagenter över oberoende delar, sedan syntes av resultaten.
Skillsen är versionshanterade, granskade (drift mellan en skill och koden den refererar till är en verklig kategori av buggar — drift fångas och åtgärdas), och behandlas som produktionsartefakter. Uppskattad besparing enbart i Spacepotatis: ~3,13 miljoner token per år. Snabbare leverans utan att sänka ribban.
Arbetsflödet har egna verktyg: claude-continue håller Claude Codes 5-timmarsfönster rygg mot rygg genom att läsa det aktiva fönstrets återställningstid och återuppta pausade sessioner i samma stund som nästa fönster öppnas — så att en lång autonom körning inte stannar av i gapet mellan fönster.
-
Att bli pappa
Tog ett steg tillbaka från heltidsarbete för familjen. Personliga projekt fortsatte i bakgrunden.
-
Kasvu Labs Oy
Två år av full-stack-arbete, i tre faser.
Först öppen data. Jag byggde ett TypeScript-verktyg som hämtar offentlig statistik och stöper om den, och det blev kvar i bruk på företaget efter att jag slutade. Det matade en app för ett kiosknätverk: försäljning per kiosk och per produkt, vem som ansvarade för vad, och en karta över Finland med varje kiosk lagd ovanpå kommunal ålders-, inkomst- och sysselsättningsdata. Frågan den besvarade var var det borde finnas fler kiosker, och var färre.
Sedan kundprojektet, där jag tog full-stack-ärenden från en kanban-tavla. Mestadels frontend: React-komponenter, MUI anpassad långt bortom sina standardinställningar, och skräddarsydda lösningar där inget färdigt passade. Ofta hela vägen också, en PgTyped-fråga, REST-endpointen för den, kopplingen och vyn ovanpå, med tester.
Jag ägde även de månatliga datauppdateringarna. Det fanns ingen direkt databasåtkomst, så jag gick in via Kubernetes-klustret och körde psql i en pod mot produktion.
Den sista fasen var ett medicinskt forskningsprojekt. Samma stack, samma form från ände till ände.
-
Järnhandel
24 år inom järnhandeln, mestadels i familjeföretaget. Inredning, renovering, verktyg, byggvaror — varje kategori, varje typ av kund. Den sortens jobb som lär dig vad användare faktiskt behöver innan du sätter en skärm mellan dig och dem.