Blog
Notes on shipping software.
Three slash commands that earn their keep
Most Claude Code features go unused — people never leave chat. /review, /security-review, and /init pay for themselves on day one, but each has a misuse that turns it into theater. The tool is free; the habit is the cost.
#claude-code#ai#developer-tools#practiceDon't accept slop on the first pass
The AI's summary of what it did isn't the same as what it did. The summary feels like the artifact. The diff is the artifact — and the only review that holds up six months later is the one done against the diff, not the recap.
#claude-code#ai#developer-tools#practiceVerify before recommending: when the AI cites, you grep
The most dangerous AI output isn't wrong — it's outdated. Claude confidently cites a flag removed last quarter, a renamed function, a path that no longer exists. Treat every named symbol as a hypothesis. Grep before you act.
#claude-code#ai#developer-tools#practicePlan before code: the trap of "just write it"
Claude will write code from any vague prompt — usually in the wrong shape, which you only notice 300 lines in. The fix is one sentence: plan first. The value isn't the plan; it's the disagreement it surfaces while still free to fix.
#claude-code#ai#prompting#developer-tools#practiceThe negative-space prompt
You ask Claude for a one-line fix and get a refactor, three new tests, a renamed file, and an explanatory comment. The fix is to scope with negatives — name the lane the assistant should not enter, and the rest of the prompt stays short.
#claude-code#ai#prompting#developer-toolsThe CLAUDE.md that actually changes behavior
Most CLAUDE.md files describe the project. Stack, folders, build commands — things Claude can derive in two ls calls. The files that actually change behavior have three rule types: negative, incident-rooted, taste-with-a-why.
#claude-code#ai#prompting#developer-toolsThe bug that lived in the gap between two services
Two services computed 'sold' two different ways. The admin got a 409 Conflict that made no sense from either seat. The bug wasn't in either service — it was in the gap between them, and a contract test stops the next one.
#microservices#debugging#distributed-systems#war-storyWhy we passed EntityManager as a parameter
A stock-drift bug nobody could reproduce locally. The fix was a function signature change — stop injecting EntityManager into NestJS singletons, pass it per-request instead.
#nestjs#typescript#concurrency#dependency-injection#war-storyHiring managers read your build choices, not your About page
Every technical decision in furevikstrand.cloud was also a hiring signal — three-tier degradation, a self-hosted dashboard, a shared code path. None of it shows on a CV; all of it shows in the repo and the live site.
#hiring#careeradvice#portfolio#softwareengineeringI built my own analytics to see what visitors ask my chat
/admin is a server-rendered, basic-auth gated Next.js page that reads chat events from MySQL — 13 panels covering traffic and chat, including a misses queue that turns spotted gaps into shipped answers in about 30 seconds.
#admin#analytics#selfhosted#privacy#mysql#nextjsAn AI chat that doesn't break when the API key expires
Three tiers of graceful degradation — Claude, Ollama, and a pure-TypeScript keyword matcher — keep the chat working even if my API balance hits zero or my LLM server goes offline.
#chat#claude#ollama#typescript#nextjs