Building software
that matters.
I'm Matej — a software mechanicI highly identify as mechanic with high inspiration from linked blog based in Slovenia with 15+ years of experience building web platforms, e-commerce systems, and AI-powered tools. Currently at PROGMBH d.o.o., working across the full stack.

The book shelf
Thoughts on design, technology, free time, and a little philosophy.
#020 v11 What survives a port is the asset
The same repo holds the API twice — NestJS and a Spring Boot port serving one hand-written contract. What transferred unchanged between them is where the engineering actually lives.
#019 v11 Staging should run NODE_ENV=production
NODE_ENV is a semantics switch that libraries branch on, not a deployment tier. Set it to staging and your rehearsal runs different code paths than the show.
#018 v11 Every knob is a promise
The retry policy is three hardcoded constants, and the decision record says why: a config option promises that every value works. Unused knobs are debt, not flexibility.
#017 v11 Refresh on the publisher's clock
The weather source publishes on a ~25-minute cycle, so the refresh cron fires at :27 — cache freshness is a property of the upstream's rhythm, not of your TTL.
#016 v11 Validate 86 fields to serve 6
The API returns six fields per station but validates the upstream's entire shape. Drift in the eighty fields you ignore is the earliest warning about the six you depend on.
#015 v11 Missing is not zero
One weather station reports no temperature at all. Encode that as 0 or drop the key, and every consumer inherits the bug — absence belongs in the contract, typed.
#014 v11 Generated specs drift away from review
Doc generation doesn't stop code and contract from disagreeing — it decides which one drifts unreviewed. The artifact a stakeholder approved should be the one the code chases.
#013 v11 Undocumented decisions get made twice
My test folder got migrated twice — same move, same commit message, days apart. An agent session starts with no memory, and an unwritten decision is just an accident it feels free to fix.
#012 v11 The AI plan is for keeping, not following
I had the model write its full project plan, committed it, and added a rule to never follow it. The unedited default is what makes judgment visible.
#010 v9 Disposable by default
Vibe coding versus agentic engineering is sold as a skill tier. It is really a per-artifact call: most agent output is disposable, and verification only pays once an output crosses the boundary where a second reader has to trust it.
#011 v11 Ship the answer with the question
The brief's openapi.yaml was missing, so I committed my own. A question that ships with its answer turns authoring into a veto — and never blocks.
#009 v8 Pattern shopping
Pattern catalogs read forward — name, then move, then constraint. Engineering runs the other way. Reading them as curriculum produces moves imported from a vocabulary rather than earned from a failure.
#008 v7 Rule drift
Osmani's ratchet — every mistake becomes a rule — is the accretion move. The second move is consolidation: rules that live in one canonical file cannot drift, and most harness write-ups skip it.
#007 v6 Thinking in code
For ambiguous problems, writing the code is where the thinking happens — not a transcription step after the thinking has finished. The medium and the thought go together.
#006 v6 Judgement-shaped problems
Most production 'agents' are integrations in costume. The test is where the if/else lives — in code, or in inference.
#005 v5 LLM catch
LLMs write perfect plans, detailed specifications, and complete architectures. Nobody ever builds any of it.
#004 v4 Asking is not enough
Most LLM workflows fail not because the model gets it wrong, but because nobody defined what right looks like before calling it.
#003 v3 Prompts as pipelines
Prompt engineering is not the art of writing one better prompt — it is the discipline of breaking the work into phases that can fail independently.
#002 v2 Boring software
The best software is the kind where nothing happens. Everything was planned, written, tested, and deployed — and it just works.
#001 v1 On simplicity
Simplicity is not the absence of complexity — it is the resolution of it.
#000 v6 Return value
Most blog posts get published because the writer wrote them. This blog is built around a different test — would the reader keep it?