May 28, 2026
From idea to shipped, my AI-native engineering workflow
Typing was never the bottleneck. I ship fast by compressing the loop between an idea and verified, reviewed code, using spec-driven planning, parallel agents and verification gates rather than by generating more code faster.

When people hear "AI-native developer," they picture an autocomplete on steroids, code appearing faster than you can read it. That misses the point entirely. The speed I get from working with Claude Code has almost nothing to do with how fast characters land in a file. Typing was never the bottleneck. The bottleneck is the loop that runs from idea to design to implementation to the moment you actually know it works. Generating more code faster, with no change to that loop, just gives you more unverified code to debug later.
So the thing I optimize is the loop rather than the typing. I run a brainstorm → spec → plan → execute → verify cycle on every non-trivial piece of work. AI compresses each stage. It drafts the spec, breaks the plan into tasks, writes tests and implementation, and runs the checks. I stay the decision-maker at every gate, reviewing and rejecting and redirecting. The AI doesn't ship anything I haven't verified. This post is the honest version of how that works, with the receipts from this site as evidence.
1. The loop I actually run
The whole workflow is one cycle, run deliberately, at a granularity that matches the work. For a small fix I might run it in my head in thirty seconds. For a new feature or a whole site it becomes durable, written-down artifacts I can hand to an agent and audit afterwards. The five stages are always the same.
- Brainstorm. Interrogate the idea before any code exists. What are we actually building, for whom, and what is explicitly out of scope?
- Spec. Write down the design, meaning goals, success criteria, non-goals and the shape of the thing. A durable document rather than a chat message.
- Plan. Turn the spec into a numbered, task-by-task implementation plan with a testing strategy and conventions baked in.
- Execute. Work the plan one task at a time. Test first where it earns its keep, implement, commit. Small, reviewable steps.
- Verify. Run the tests, the build, the linter and the app, then review the diff. No claim of "done" without evidence.
1.1 Brainstorm first, design before code
The most expensive bug is the feature you built correctly but shouldn't have built at all. So the loop starts before any file is touched, with a brainstorm that exists to surface the real intent and kill ambiguity. What problem are we solving? Who is it for? What does "good" look like, measurably? And the question that saves the most time, what are we not doing?
This is where AI is genuinely useful in a way that has nothing to do with code generation. An agent that pushes back, asks the questions I'd skip, and forces me to name non-goals out loud is worth more at this stage than one that writes a thousand lines. A spec exists because design decided in conversation evaporates. Design written down can be reviewed, disagreed with and held to. The portfolio you're reading started as a design document rather than a folder of files.
Non-goals (v1): blog/CMS, multi-language, analytics dashboards, e-commerce, auth.
docs/superpowers/specs/2026-05-29-cjjutba-portfolio-design.md
That line is from the real spec for this site. Naming those non-goals up front is what kept v1 from sprawling. The blog that line excludes shipped later anyway, deliberately, as its own scoped piece of work with its own spec. Scope is a decision you make on purpose rather than a thing that happens to you.
1.2 Spec and plan, durable artifacts rather than chat history
Once the design is settled, it becomes two committed files. A spec covering what and why, and a plan covering how, step by step. These live in the repo, in version control, alongside the code they produced. They are not throwaway prompts. They are the source of truth an agent executes against and that I audit against afterwards. This site's docs/superpowers/ directory holds the real ones.
docs/superpowers/specs/2026-05-29-cjjutba-portfolio-design.mdis the design spec. Goals, success criteria, information architecture, positioning, and the honesty constraints that forbid fabricated metrics and fake testimonials.docs/superpowers/plans/2026-05-29-cjjutba-portfolio.mdis the implementation plan. Phased and task-by-task, with a testing strategy and a conventions section.docs/superpowers/specs/2026-05-29-blog-posts-toc-island-design.mdand its matching plan cover the blog and the floating table-of-contents you're using right now, scoped and planned separately from the main site.
Writing the plan is itself a forcing function. If a task can't be stated crisply with a clear way to verify it, the design isn't done yet, and that's far cheaper to discover in a markdown file than three hundred lines into the implementation. The plan also carries the boring conventions up front. Package manager, commit style, import aliases, and the rule that the build and linter must pass after every phase. Decisions made once, in writing, instead of re-litigated per file.
A spec and plan in the repo give an agent a stable target across a long session, context that survives compaction and restarts.
They give me an audit trail. I can diff what was built against what was agreed, and catch silent scope drift.
They are also honest documentation for whoever owns the code next. The artifacts ship with the product.
1.3 Execute task by task, with TDD and small commits
Execution is deliberately unglamorous. Work the plan one task at a time. Where logic has real behavior worth pinning down, a validation schema or a slug builder or a reading-time estimate, I write the test first, watch it fail, then implement until it's green. Where the work is purely visual I skip the brittle snapshot tests and run the app and look at it. The discipline is matching the verification to the work rather than testing for a coverage number.
A plan task is small and self-contained, with its own verification step. Here is the shape and granularity one takes. Note that the verification command is part of the task rather than an afterthought.
### Task 3: Reading-time estimate - [ ] Step 1: Write the failing test- [ ] Step 2: Run test to verify it fails Run: pnpm test src/lib/__tests__/reading-time.test.ts- [ ] Step 3: Implement until green Run: pnpm test src/lib/__tests__/reading-time.test.ts Expected: PASS.- [ ] Step 4: CommitEach completed task becomes one commit, in Conventional-Commits form, scoped to a single concern. That is not an aesthetic choice. It is what makes the history reviewable and reversible. This site was built in over 60 small commits at the time of writing, overwhelmingly feat: and fix:, with docs:, test:, style: and copy: for the rest. The cadence looks like this.
feat(blog): [slug] route + per-post OG image, index cards, sitemapfix(toc): focus sheet on open, hide island behind modal, ARIA cleanupfeat(toc): floating island + bottom-slide modal + scroll-spyfeat(blog): structured BlogPost content model + index helperstest: about + dark-mode popover/modal screenshots, about smoke + axefix(contact): check Resend send error (no more silent success) + log failuresA small commit is a small blast radius. If a change is wrong, I revert one thing, not a day's work. If a reviewer (me, or a client's engineer later) wants to understand a decision, the commit message and its diff tell the story. This is the part of "moving fast" that people underweight. Speed compounds when mistakes stay cheap.
2. Parallelism without chaos
Once the loop is tight, the obvious next lever is doing more than one thing at once. AI makes that tempting, since you can spin up several agents and watch them all work. Naive parallelism is how you get merge hell, half-finished features stepping on each other, and a verification step that can't tell you what actually changed. The trick is isolation. Parallel work only pays off when the streams genuinely don't touch.
2.1 Worktrees, isolation by default
When two pieces of work could collide, I give each its own git worktree, a separate working directory backed by the same repository, on its own branch. No stashing, no "wait, which branch am I on," and no half-applied changes bleeding across features. Each worktree is a clean room with its own files, its own running dev server if it needs one, and its own test runs.
# spin up an isolated workspace for a feature branchgit worktree add ../cjjutba-blog -b feat/blog # work, test, and commit there without touching the main checkout# when it's merged and done:git worktree remove ../cjjutba-blogThe payoff is psychological as much as technical. Because each stream is physically isolated, I can let an agent run inside one worktree without worrying it will corrupt work in progress somewhere else. Isolation is what makes parallelism safe as well as fast.
2.2 Subagents, fan-out for independent tasks
Inside a single piece of work, the same idea applies at the task level. When a plan has several tasks with no shared state and no ordering between them, I fan them out to subagents instead of grinding through them serially, one agent per task, each with a focused brief. This blog was built that way. The four posts are independent data files, so they were authored in parallel, each agent grounding its own post against its own source repo, then handed back for review and a single registration step.
The constraint that makes this work is the same one from worktrees, independence. Subagent fan-out shines for genuinely parallel work with separate files, separate concerns, and no task waiting on another's output. The moment tasks share state or have to happen in order, fan-out manufactures conflicts instead of saving time. Then I run them sequentially, in the order the plan specifies, on purpose.
It helps for independent tasks with no shared files or state, say four separate content files, or a feature and an unrelated bug fix in different directories. Isolate each in a worktree or a subagent and merge when each is independently green.
It hurts for tasks that touch the same module, depend on each other's output, or need a shared decision made first. Parallelizing those moves the work into a painful merge and muddies what the verification step is telling you.
The rule of thumb. If you can't describe two tasks without the word "after," they are not parallel. Sequence them.
3. Verification is the actual job
Here is the part that separates an AI-native workflow that ships reliable software from one that ships fast-looking liabilities. Generating code is the easy 80%. The job, the thing a client is actually paying for, is knowing the code does what it's supposed to do. Verification is the point of the whole exercise rather than a phase at the end. Everything before it exists so you can make a claim you can back up.
3.1 Evidence before claims
My standing rule, applied to myself and to every agent I run, is evidence before assertions. Nothing is "done," "fixed," or "passing" until I've run the command and read the output. Not "this should work", but the green test, the clean build and the rendered page. On this site that means a concrete, layered set of gates.
| Gate | What it proves | How it runs here |
|---|---|---|
| Unit tests | Logic behaves as specified | Vitest, covering schema validation, slug and TOC builders, reading-time and content invariants |
| Build | It actually compiles and type-checks | pnpm build must pass after every phase |
| Lint | No obvious correctness or style regressions | pnpm lint as a phase gate |
| E2E + a11y | Real pages render and are accessible | Playwright smoke tests + an automated axe accessibility pass |
| Diff review | The change matches the agreed plan | I read every diff before it's committed |
Tests catch the regressions. Review catches the things tests can't. An agent can write a passing test for the wrong behavior, or solve the stated problem while quietly breaking an unstated assumption. So the human review of the diff against the spec is not optional. It is where I confirm the code does the intended thing rather than merely a thing. That is the gate AI does not get to skip.
It declares victory without running anything. "This should fix it" is not evidence, and an unrun test is a hopeful comment.
It writes a test that asserts the buggy behavior, so the suite is green and wrong at the same time.
It silences errors to make output look clean, swallowing a failure path so a call appears to succeed. This exact bug shipped to this repo once and was caught in review. The contact form reported success even when the email send errored. The fix is in the history as fix(contact): check Resend send error (no more silent success) + log failures.
It confidently invents APIs, config keys, or version behavior that don't exist in the actual dependency. Grounding every claim against the real repo and the real docs is the only defense.
Every one of those failure modes is invisible if you trust the narration instead of the output. The whole discipline reduces to a single habit. Believe it works because you watched it work, never because something said so.
4. What this means if you're hiring me
The reason any of this matters, if you're considering working with me, is that it resolves a tension you have probably been told is unresolvable. Speed and rigor are not a trade-off here. The usual choice is a fast contractor who leaves you a fragile mess, or a careful shop that takes six months and a five-figure invoice to ship a v1. The loop above is how I deliver agency-quality output on a solo timeline, and the rigor is what makes it fast.
Where the speed comes from is specific rather than magic. AI compresses the time inside each stage of the loop, drafting the spec, breaking down the plan, writing tests and implementation, and running the checks. I stay the bottleneck on judgment, which is the part you want a human owning anyway. The net effect is a cycle that turns in weeks, not months. You see working, verified software early and often, and iterate against real feedback instead of waiting for a big reveal.
A scoped spec and plan up front, so we agree on what "done" means before I build it.
Working software early and often, in small reviewable increments rather than a six-month black box.
Tested, linted, accessible code that you own outright, with no lock-in and no tangle to inherit.
Honest verification, where every claim of "done" is backed by a result you can see rather than a status I narrated.
I would rather show you the number than assert it. Kernel, a Mac app I built with this loop, went from an empty repo to its ninth public release in eight days, code signed, notarized by Apple and updating itself. The commit history is public, so you can check every one of those days.
Eight days was my own product, scoped by me, with nobody else to agree with. A client build takes longer, because we settle the spec together first and you review the work as it lands. That is where "weeks, not months" comes from. If that is the way you want your software built, here is how we would work together.
Keep reading
All postsEngineering a compliance-grade SaaS, with multi-tenancy, RBAC and audit trails
May 22, 2026 · 14 min readHow I replaced a Belgian accounting practice's email-and-spreadsheet workflow with one type-safe API serving three role-scoped portals, carrying a full Belgian AML compliance module, 92+ RBAC permissions and an append-only audit trail underneath.
Build log, shipping this site with Next.js 16, Tailwind v4 and a monochrome design system
May 10, 2026 · 11 min readHow cjjutba.dev is put together. A no-radius monochrome design system, Next.js 16's sharp edges, two modals that share one pattern, and a content-as-data model with zero MDX. The post you're reading is the page it describes.