<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: BLNCraft</title>
    <description>The latest articles on DEV Community by BLNCraft (@blncraft).</description>
    <link>https://dev.to/blncraft</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3924862%2Fd702bad0-22ff-48a3-b4b1-bc5edfcc23d6.png</url>
      <title>DEV Community: BLNCraft</title>
      <link>https://dev.to/blncraft</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blncraft"/>
    <language>en</language>
    <item>
      <title>3 Files Every AI-Assisted Project Needs Before You Write a Line of Code</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Fri, 29 May 2026 23:06:11 +0000</pubDate>
      <link>https://dev.to/blncraft/3-files-every-ai-assisted-project-needs-before-you-write-a-line-of-code-4k4d</link>
      <guid>https://dev.to/blncraft/3-files-every-ai-assisted-project-needs-before-you-write-a-line-of-code-4k4d</guid>
      <description>&lt;p&gt;Most developers think of project setup as: install dependencies, configure TypeScript, set up linting.&lt;/p&gt;

&lt;p&gt;That is the wrong order. The AI-native setup order is different, and skipping it means your AI assistant works against your project instead of with it.&lt;/p&gt;

&lt;p&gt;Here are the three files that should exist before you write a line of application code.&lt;/p&gt;




&lt;h2&gt;
  
  
  File 1: CLAUDE.md (the instruction layer)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; is a markdown file at your project root that Claude Code loads as a system prompt prefix on every session. Think of it as the briefing document your AI assistant reads before touching your codebase.&lt;/p&gt;

&lt;p&gt;A minimal &lt;code&gt;CLAUDE.md&lt;/code&gt; for a new project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project: My SaaS App&lt;/span&gt;

&lt;span class="gu"&gt;## Stack&lt;/span&gt;
Next.js 15, TypeScript strict, Prisma + PostgreSQL, Tailwind CSS

&lt;span class="gu"&gt;## Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; No &lt;span class="sb"&gt;`any`&lt;/span&gt; types. No unvalidated JSON.parse().
&lt;span class="p"&gt;-&lt;/span&gt; Auth via NextAuth.js. Never roll custom auth.
&lt;span class="p"&gt;-&lt;/span&gt; DB access only in &lt;span class="sb"&gt;`src/services/`&lt;/span&gt; — never in route handlers directly.
&lt;span class="p"&gt;-&lt;/span&gt; Run &lt;span class="sb"&gt;`npm run typecheck`&lt;/span&gt; before declaring a fix done.

&lt;span class="gu"&gt;## Deploy&lt;/span&gt;
Vercel. Main branch auto-deploys. Staging on &lt;span class="sb"&gt;`preview`&lt;/span&gt; branches.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ten lines. That is enough to prevent 80% of the decisions where the AI would otherwise guess wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why write this before any code?&lt;/strong&gt; Because when you write it after, you are describing what you accidentally built rather than what you intended. The instruction layer should drive the codebase, not document it retroactively.&lt;/p&gt;




&lt;h2&gt;
  
  
  File 2: .cursorrules (the tool layer)
&lt;/h2&gt;

&lt;p&gt;If you use Cursor, &lt;code&gt;@.cursorrules&lt;/code&gt; loads into Cursor's context. It is similar to &lt;code&gt;CLAUDE.md&lt;/code&gt; but optimized for Cursor's behavior — shorter, more rule-focused, less narrative.&lt;/p&gt;

&lt;p&gt;The key difference from &lt;code&gt;CLAUDE.md&lt;/code&gt;: &lt;code&gt;CLAUDE.md&lt;/code&gt; can afford to be contextual ("we use Prisma because our team knows it"). &lt;code&gt;@.cursorrules&lt;/code&gt; should be purely prescriptive ("never write raw SQL; use Prisma query builders").&lt;/p&gt;

&lt;p&gt;Keep them in sync. If you update the auth pattern in one, update the other. Two source-of-truth files with the same content that drift apart are worse than one. &lt;/p&gt;

&lt;p&gt;A clean pattern: have &lt;code&gt;CLAUDE.md&lt;/code&gt; be the canonical source. In &lt;code&gt;.cursorrules&lt;/code&gt;, reference it and add only Cursor-specific formatting rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Project context: see CLAUDE.md at repo root.

Additional Cursor rules:
&lt;span class="p"&gt;-&lt;/span&gt; Auto-import from absolute paths, not relative.
&lt;span class="p"&gt;-&lt;/span&gt; Prefer named exports over default exports.
&lt;span class="p"&gt;-&lt;/span&gt; Format with Prettier on save — do not manually align anything.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four lines. Everything else lives in &lt;code&gt;CLAUDE.md&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  File 3: README.md (the onboarding layer)
&lt;/h2&gt;

&lt;p&gt;This one surprises people. The README is not for human readers — it is for your AI assistant's cold-start.&lt;/p&gt;

&lt;p&gt;When you open a new Cursor session or start a new Claude Code chat, the AI does not remember anything from yesterday. The README is the document it will read first if you paste it in, and it is what future agents (or you, in three months) will read to understand how the project works.&lt;/p&gt;

&lt;p&gt;A README that serves as an AI onboarding document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Quick context&lt;/span&gt;
SaaS app for indie devs. Subscription billing via Stripe, auth via NextAuth.js,
database via Prisma + PostgreSQL on Neon.

&lt;span class="gu"&gt;## Local setup&lt;/span&gt;
npm install &amp;amp;&amp;amp; cp .env.example .env.local &amp;amp;&amp;amp; npx prisma migrate dev

&lt;span class="gu"&gt;## Project structure&lt;/span&gt;
src/
  app/          Next.js App Router pages
  services/     Business logic — no HTTP here
  components/   React components — no data fetching here
  lib/          Utilities and config

&lt;span class="gu"&gt;## Common tasks&lt;/span&gt;
Run dev: npm run dev
Run types: npm run typecheck
Run tests: npm test
Deploy: push to main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No fluff. No marketing copy. Just: what is this, how do I start it, what is where.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why all three, before any code
&lt;/h2&gt;

&lt;p&gt;These three files form a triangle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CLAUDE.md&lt;/code&gt; tells the AI &lt;strong&gt;what matters&lt;/strong&gt; (the stakes, the patterns, the non-negotiables)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.cursorrules&lt;/code&gt; tells the AI &lt;strong&gt;how to behave&lt;/strong&gt; (the mechanical rules, the formatting, the import conventions)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;README.md&lt;/code&gt; tells the AI &lt;strong&gt;what exists&lt;/strong&gt; (the structure, the commands, the mental model)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When all three are in place before you write application code, you are building inside a defined context. The AI works with your decisions instead of making its own.&lt;/p&gt;

&lt;p&gt;When none of them are in place, you are doing vibe coding in the wrong direction — the AI is building something, and you are figuring out what it is as you go.&lt;/p&gt;




&lt;h2&gt;
  
  
  The shortcut
&lt;/h2&gt;

&lt;p&gt;Setting these three files up for a new project takes 20-30 minutes if you are doing it from scratch. Doing it for 12 different tech stacks (Next.js SaaS, Express + JWT, FastAPI, Discord Bot, Chrome Extension, and more) takes considerably longer.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://blncraft.gumroad.com/l/vibe-coder-kit" rel="noopener noreferrer"&gt;Vibe Coder Kit&lt;/a&gt; packages 12 production-configured starters where all three files are already in place and consistent with the actual codebase. You clone, run the setup command, and your AI assistant is already briefed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The test
&lt;/h2&gt;

&lt;p&gt;At the end of your next project setup, ask: "If a new developer (or a new AI session) opened this repo with no context, could they figure out what it is, how to run it, and how to work in it?"&lt;/p&gt;

&lt;p&gt;If the answer is yes, you have done the setup right.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;BLN Craft builds developer tools for AI-native workflows. Find us at &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;blncraft.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>cursor</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>5 .cursorrules Antipatterns Killing Your AI Productivity</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Fri, 29 May 2026 23:01:44 +0000</pubDate>
      <link>https://dev.to/blncraft/5-cursorrules-antipatterns-killing-your-ai-productivity-gpl</link>
      <guid>https://dev.to/blncraft/5-cursorrules-antipatterns-killing-your-ai-productivity-gpl</guid>
      <description>&lt;p&gt;Your &lt;code&gt;.cursorrules&lt;/code&gt; file is probably not working the way you think it is.&lt;/p&gt;

&lt;p&gt;Not because Cursor is broken — but because most &lt;code&gt;.cursorrules&lt;/code&gt; setups make the same five mistakes. Here is what they are and how to fix them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake 1: One file, everything in it
&lt;/h2&gt;

&lt;p&gt;The most common &lt;code&gt;.cursorrules&lt;/code&gt; antipattern is the monolith: one file at the project root, 300 lines long, covering TypeScript conventions AND API auth patterns AND deployment notes AND "always write clean code."&lt;/p&gt;

&lt;p&gt;The problem: Cursor loads this file into every context, regardless of what you are editing. When you are fixing a CSS bug, your SQL query rules are burning token budget for nothing. When context gets long, older rules get compressed out — which means your most important constraints are the ones most likely to disappear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Split into scoped rule files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;.&lt;span class="n"&gt;cursorrules&lt;/span&gt;                  &lt;span class="c"&gt;# 50 lines: project overview, stack, non-negotiables
&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;/&lt;span class="n"&gt;api&lt;/span&gt;/.&lt;span class="n"&gt;cursorrules&lt;/span&gt;          &lt;span class="c"&gt;# Auth patterns, error format, rate limiting
&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;/&lt;span class="n"&gt;components&lt;/span&gt;/.&lt;span class="n"&gt;cursorrules&lt;/span&gt;   &lt;span class="c"&gt;# Component conventions, state patterns  
&lt;/span&gt;&lt;span class="n"&gt;scripts&lt;/span&gt;/.&lt;span class="n"&gt;cursorrules&lt;/span&gt;          &lt;span class="c"&gt;# Env handling, idempotency, logging
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file loads only when files in that directory are open. Your total in-context rule budget stays tight.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake 2: Vague constraints
&lt;/h2&gt;

&lt;p&gt;"Write clean, readable code."&lt;br&gt;
"Keep functions small."&lt;br&gt;
"Follow best practices."&lt;/p&gt;

&lt;p&gt;These are not rules. They are aspirations. The AI already knows what "best practices" means — and it will apply its own interpretation, not yours.&lt;/p&gt;

&lt;p&gt;Rules need to be specific enough to fail. If you cannot imagine a concrete code sample that violates the rule, the rule is too vague to enforce.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vague:&lt;/strong&gt; "Handle errors properly."&lt;br&gt;
&lt;strong&gt;Specific:&lt;/strong&gt; "All async functions must have a try/catch. Errors must be logged via &lt;code&gt;logger.error()&lt;/code&gt; before rethrowing. Never swallow errors silently."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vague:&lt;/strong&gt; "Use descriptive variable names."&lt;br&gt;
&lt;strong&gt;Specific:&lt;/strong&gt; "Boolean variables must start with &lt;code&gt;is&lt;/code&gt;, &lt;code&gt;has&lt;/code&gt;, &lt;code&gt;should&lt;/code&gt;, or &lt;code&gt;can&lt;/code&gt;. No single-letter names outside of loop indices."&lt;/p&gt;

&lt;p&gt;The second versions are automatable. The first versions are vibes.&lt;/p&gt;


&lt;h2&gt;
  
  
  Mistake 3: No project structure context
&lt;/h2&gt;

&lt;p&gt;The AI does not know your project layout unless you tell it. This leads to imports from wrong paths, new files dropped in wrong directories, and helper functions duplicated because the AI didn't know one already existed.&lt;/p&gt;

&lt;p&gt;Add a compact directory map early in your &lt;code&gt;.cursorrules&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Project structure:
src/
  api/          # Express routes + middleware
  services/     # Business logic (no HTTP)
  models/       # Prisma schema types
  utils/        # Pure functions, no side effects
  types/        # Shared TypeScript interfaces
tests/          # Mirrors src/ structure
scripts/        # One-off automation, not imported by app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eight lines. Enough to save the AI from putting a database call in a route handler because it didn't know &lt;code&gt;services/&lt;/code&gt; exists.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake 4: Rules that contradict the codebase
&lt;/h2&gt;

&lt;p&gt;If your &lt;code&gt;.cursorrules&lt;/code&gt; says "never use &lt;code&gt;any&lt;/code&gt; types" but your codebase has 200 &lt;code&gt;any&lt;/code&gt; type usages, the rule is fighting the existing code. The AI gets conflicting signals: the rule says one thing, the examples in the codebase say another. The examples usually win.&lt;/p&gt;

&lt;p&gt;Your rules should describe what the code already does, not what you wish it did.&lt;/p&gt;

&lt;p&gt;If there is a gap — you want to adopt a new pattern but your codebase isn't there yet — say so explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Migration in progress: we are removing `any` types.
# New code must not use `any`. Existing `any` usages will be fixed incrementally.
# Do not add new `any` even when refactoring old code.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives the AI a clear mandate without creating a contradiction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake 5: Duplicating rules across tools without a source of truth
&lt;/h2&gt;

&lt;p&gt;If you use Cursor + Claude Code, you end up with &lt;code&gt;.cursorrules&lt;/code&gt; and &lt;code&gt;CLAUDE.md&lt;/code&gt; saying the same things in slightly different ways. Then one gets updated and the other doesn't. Then they contradict each other. Then neither is trusted.&lt;/p&gt;

&lt;p&gt;The fix is a single authoritative source with tool-specific adaptations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep your core project rules in &lt;code&gt;CLAUDE.md&lt;/code&gt; (it is the most structured format and is loaded by Claude Code as a system prompt prefix).&lt;/li&gt;
&lt;li&gt;Have &lt;code&gt;.cursorrules&lt;/code&gt; import or reference the same core rules, adding only Cursor-specific formatting/behavior.&lt;/li&gt;
&lt;li&gt;When you update the rules, update the source — not each tool's file separately.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For greenfield projects, starting with a production-configured starter that already has both files wired up correctly saves this setup cost entirely. The &lt;a href="https://blncraft.gumroad.com/l/vibe-coder-kit" rel="noopener noreferrer"&gt;Vibe Coder Kit&lt;/a&gt; includes 12 starters (Next.js SaaS, Express + JWT, FastAPI, Discord Bot, and more) where &lt;code&gt;.cursorrules&lt;/code&gt; and &lt;code&gt;CLAUDE.md&lt;/code&gt; are already synchronized and match the actual codebase structure.&lt;/p&gt;




&lt;h2&gt;
  
  
  The test for a good rules file
&lt;/h2&gt;

&lt;p&gt;Read each rule and ask: "Could a developer violate this rule while genuinely trying to follow it?" If yes, the rule is too ambiguous. Make it specific enough that violations are unambiguous.&lt;/p&gt;

&lt;p&gt;Then count your lines. If your &lt;code&gt;.cursorrules&lt;/code&gt; is over 100 lines, split it. If it is under 20, you probably have not captured your real conventions yet.&lt;/p&gt;

&lt;p&gt;Short. Specific. Scoped. Consistent with the codebase.&lt;/p&gt;

&lt;p&gt;Those four constraints will make your AI coding setup work the way the demos promise.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;BLN Craft builds developer tools for AI-native workflows. Find us at &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;blncraft.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>5 CLAUDE.md Patterns That Make AI Actually Follow Your Rules</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Fri, 29 May 2026 22:58:36 +0000</pubDate>
      <link>https://dev.to/blncraft/5-claudemd-patterns-that-make-ai-actually-follow-your-rules-3kj1</link>
      <guid>https://dev.to/blncraft/5-claudemd-patterns-that-make-ai-actually-follow-your-rules-3kj1</guid>
      <description>&lt;p&gt;Have you ever set up a CLAUDE.md file, dropped in 200 lines of rules, and then watched the AI completely ignore half of them anyway?&lt;/p&gt;

&lt;p&gt;You are not alone. The irony of writing instructions for AI coding assistants is that the same productivity trap applies to you: more rules ≠ better results.&lt;/p&gt;

&lt;p&gt;Here are five patterns that actually work, learned from managing production CLAUDE.md setups across a dozen project starters.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The 800-token rule
&lt;/h2&gt;

&lt;p&gt;The biggest CLAUDE.md mistake is treating it like documentation. It is not documentation. It is a &lt;strong&gt;system prompt prefix&lt;/strong&gt; — and system prompts have a working memory budget.&lt;/p&gt;

&lt;p&gt;A rough heuristic: keep your primary CLAUDE.md under 800 tokens (~600 words). Beyond that, context compression pushes older rules out when long files are open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to cut:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rationale paragraphs ("we do this because...")&lt;/li&gt;
&lt;li&gt;Historical context ("we used to use X but now...")&lt;/li&gt;
&lt;li&gt;Anything that is obvious from the codebase itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rule goes in CLAUDE.md. The rationale goes in a comment in the relevant file, or nowhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Use glob-scoped rules, not one giant file
&lt;/h2&gt;

&lt;p&gt;Claude Code supports scoped CLAUDE.md files — rules in &lt;code&gt;src/api/CLAUDE.md&lt;/code&gt; apply only when files under &lt;code&gt;src/api/&lt;/code&gt; are open. Use this.&lt;/p&gt;

&lt;p&gt;A frontend rule about "never use inline styles" has no business loading when the AI is working in your Express routes. A backend rule about "always use parameterized queries" does not need to be in context when fixing a CSS animation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical layout:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLAUDE.md              # project-wide: stack, deploy process, critical invariants
src/api/CLAUDE.md      # API-specific: auth patterns, error formats, rate limiting
src/web/CLAUDE.md      # Frontend-specific: component conventions, state patterns
scripts/CLAUDE.md      # Automation: env var handling, idempotency requirements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file stays under 300 tokens. Total loaded at any time: ~600 tokens. Still under budget.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. One concern per rule
&lt;/h2&gt;

&lt;p&gt;Compound rules fail silently. When you write:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Functions should be small, pure, and well-named, with explicit return types and no side effects unless they are in service files."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;...the AI picks the parts it agrees with and ignores the rest. This is not a model quality problem — it is a parsing problem. Compound sentences create ambiguity about which clause is the constraint and which is the suggestion.&lt;/p&gt;

&lt;p&gt;Split every compound rule into atomic statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Functions&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Max 30 lines. Extract helpers if exceeded.
&lt;span class="p"&gt;-&lt;/span&gt; Explicit return types on all exported functions.
&lt;span class="p"&gt;-&lt;/span&gt; No side effects except in &lt;span class="sb"&gt;`*Service.ts`&lt;/span&gt; and &lt;span class="sb"&gt;`*Repository.ts`&lt;/span&gt; files.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three lines, three enforceable constraints, zero ambiguity.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Negative rules outperform positive rules
&lt;/h2&gt;

&lt;p&gt;"Use Zod for all schema validation" is a positive rule. It tells the AI what to do, but not how strongly you mean it.&lt;/p&gt;

&lt;p&gt;"Never use &lt;code&gt;any&lt;/code&gt; types. Never use untyped &lt;code&gt;JSON.parse()&lt;/code&gt; without a Zod schema." — these are negative rules. They draw a hard line.&lt;/p&gt;

&lt;p&gt;In practice, AI assistants weight prohibitions more heavily than recommendations. This is because prohibitions reduce the valid solution space (easier to enforce) while recommendations just add a preference (easier to deprioritize under other pressures).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reframe your positive rules as negative rules where you can:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Positive&lt;/th&gt;
&lt;th&gt;Negative&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Use environment variables for all config&lt;/td&gt;
&lt;td&gt;Never hardcode URLs or credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write tests for all public functions&lt;/td&gt;
&lt;td&gt;Never ship a new exported function without a test file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use the existing logger&lt;/td&gt;
&lt;td&gt;Never call &lt;code&gt;console.log&lt;/code&gt; directly in production code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The negative framing also makes violations easy to grep for.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Pair CLAUDE.md with a production-configured starter
&lt;/h2&gt;

&lt;p&gt;The best CLAUDE.md is one that describes a codebase that already follows its own rules. When the starter project has ESLint configured, TypeScript strict mode on, and the folder structure already in place — the CLAUDE.md rules are reinforced by the code itself.&lt;/p&gt;

&lt;p&gt;This is why project starters are worth spending time on. If your starter has &lt;code&gt;any&lt;/code&gt; types everywhere and no linting, your CLAUDE.md rule against &lt;code&gt;any&lt;/code&gt; is fighting the existing codebase instead of aligning with it.&lt;/p&gt;

&lt;p&gt;We built the &lt;a href="https://blncraft.gumroad.com/l/vibe-coder-kit" rel="noopener noreferrer"&gt;Vibe Coder Kit&lt;/a&gt; specifically for this: 12 production-configured starters (Next.js SaaS, Express + JWT, Node CLI, Chrome Extension, Discord Bot, FastAPI, and more) where the CLAUDE.md rules match what the code already does. Zero setup, immediate AI alignment.&lt;/p&gt;




&lt;h2&gt;
  
  
  The one-line takeaway
&lt;/h2&gt;

&lt;p&gt;CLAUDE.md files fail the same way most documentation fails: they get long, stale, and comprehensive when they should be short, current, and opinionated.&lt;/p&gt;

&lt;p&gt;Short. Scoped. Atomic. Negative where possible. Backed by a codebase that already follows the rules.&lt;/p&gt;

&lt;p&gt;That is the setup that makes vibe coding actually work.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;BLN Craft builds developer tools for AI-native workflows. Follow us at &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;blncraft.com&lt;/a&gt; for more.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>You Don't Need Microservices Yet: A Reality Check for Devs</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Wed, 27 May 2026 07:04:54 +0000</pubDate>
      <link>https://dev.to/blncraft/you-dont-need-microservices-yet-a-reality-check-for-devs-3c5m</link>
      <guid>https://dev.to/blncraft/you-dont-need-microservices-yet-a-reality-check-for-devs-3c5m</guid>
      <description>&lt;p&gt;You spent three years building a distributed system. Kubernetes clusters, service meshes, inter-service gRPC calls, a dedicated message broker — and your user base is 200 people, 40 of whom are your coworkers testing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture Trap
&lt;/h2&gt;

&lt;p&gt;There's a well-worn path in software engineering that goes something like this: you read about how Netflix decomposed their monolith, you watch a conference talk about event-driven architecture, and suddenly your SaaS for managing yoga class bookings has seventeen services, a Kafka cluster, and three on-call rotations.&lt;/p&gt;

&lt;p&gt;This isn't a hot take. It's a recurring diagnosis. Developers — especially good ones — are pattern-matchers. We see sophisticated solutions to hard problems and we want to apply them. The trouble is, microservices aren't a &lt;em&gt;better&lt;/em&gt; way to build software. They're a specific solution to a specific set of scaling and team-coordination problems that most applications will never have.&lt;/p&gt;

&lt;p&gt;Netflix had thousands of engineers and hundreds of millions of users before they went full microservices. Your B2B dashboard tool does not have that problem. It has a different problem: it needs to ship features, fast, without a distributed tracing setup just to debug why a user can't log in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Monolith Actually Looks Like in 2024
&lt;/h2&gt;

&lt;p&gt;The word "monolith" has been so thoroughly dragged through the mud that developers treat it like a slur. But a well-structured monolith isn't a big ball of mud — it's a modular application with clear internal boundaries that happens to deploy as a single unit.&lt;/p&gt;

&lt;p&gt;Here's a straightforward Node.js/Express monolith structure that scales comfortably to hundreds of thousands of users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app.ts — entry point, clean and boring&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./modules/users/user.routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;billingRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./modules/billing/billing.routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notificationRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./modules/notifications/notification.routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/billing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;billingRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/notifications&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notificationRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Server running on port 3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/modules/users/user.service.ts — a self-contained module&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../lib/db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../notifications/notification.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BillingService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../billing/billing.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;billingService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BillingService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;billingService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BillingService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// All of this happens in one process, one transaction, one deployment.&lt;/span&gt;
    &lt;span class="c1"&gt;// No network calls. No distributed transactions. No saga pattern.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;billingService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeBillingRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendWelcomeEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getUserById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what's &lt;em&gt;not&lt;/em&gt; here: no message queues to coordinate the billing and notification steps, no distributed tracing to figure out why the welcome email failed, no separate deployment pipelines per service. If something breaks, your stack trace tells you exactly where. Your rollback is one command.&lt;/p&gt;

&lt;p&gt;The modules are still cleanly separated. If you ever genuinely need to extract &lt;code&gt;NotificationService&lt;/code&gt; into its own service — because your notification volume is overwhelming the main app, or because a separate team owns it — you can. The internal boundaries are already there. You're paying none of the distributed systems tax until you actually need to.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Costs Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;When someone pitches microservices, the conversation is usually about scalability and team autonomy. Fair points, eventually. But the costs are almost never foregrounded honestly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operational complexity compounds.&lt;/strong&gt; Every service you add is a new thing that can fail in production, a new set of logs to aggregate, a new deployment pipeline to maintain. At five services you're fine. At twenty you need a platform engineering team whose entire job is keeping the infrastructure running for the product engineers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed transactions are genuinely hard.&lt;/strong&gt; In the monolith example above, &lt;code&gt;createUser&lt;/code&gt; runs billing and notification in sequence. If billing fails, you throw an error, nothing is committed, the user doesn't exist. In a microservices world, you've got eventual consistency, saga patterns, compensation transactions, and a whole new class of bugs where the user exists in one service but not another.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local development gets painful fast.&lt;/strong&gt; Running &lt;code&gt;npm run dev&lt;/code&gt; is great. Running &lt;code&gt;docker-compose up&lt;/code&gt; for twelve services, waiting for them all to be healthy, and then realizing service seven has a port conflict is a productivity graveyard. Junior devs especially get slowed down enormously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging requires infrastructure.&lt;/strong&gt; In a monolith, you add a &lt;code&gt;console.log&lt;/code&gt; and you're done. In microservices, you need distributed tracing (Jaeger, Zipkin, Datadog APM) just to follow a request through the system. That tooling is powerful, but it's also expensive and takes real time to set up correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Microservices Actually Make Sense
&lt;/h2&gt;

&lt;p&gt;This isn't a microservices hit piece. There are legitimate reasons to decompose a system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Independent scaling needs.&lt;/strong&gt; Your video transcoding workload needs 10x the compute of your API layer and runs on completely different hardware profiles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team boundaries at scale.&lt;/strong&gt; Once you have 50+ engineers, Conway's Law means your architecture should reflect your org structure. Separate teams genuinely benefit from deployment independence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wildly different tech requirements.&lt;/strong&gt; Your ML inference pipeline wants Python and GPUs. Your API wants Node. They genuinely shouldn't be the same process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance isolation.&lt;/strong&gt; Your payment processing code needs to live in a PCI-compliant environment that the rest of your app doesn't touch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If none of these apply to you right now, you don't need microservices. You need a better-organized monolith and maybe a read replica on your database.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Migration Path That Isn't Premature
&lt;/h2&gt;

&lt;p&gt;If you're starting fresh or refactoring, here's the approach that keeps your options open without paying distributed systems costs upfront:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build a modular monolith.&lt;/strong&gt; Strong internal module boundaries, dependency injection, no circular imports between modules. Treat each module as if it &lt;em&gt;could&lt;/em&gt; become a service, but don't make it one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a job queue early.&lt;/strong&gt; Not Kafka — something like BullMQ backed by Redis. This handles async workloads (emails, webhooks, report generation) without splitting your codebase. One deployment, async processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch your metrics, not your ambitions.&lt;/strong&gt; Set up basic APM. Only split a service when you have concrete evidence that a specific part of the system is causing problems — response time degradation, resource contention, deployment coupling that's actually slowing teams down.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract one service as an experiment before extracting many.&lt;/strong&gt; The operational overhead of service number two is enormous relative to one. Service number five is marginal. Feel the actual cost before committing the architecture.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Ship the Thing
&lt;/h2&gt;

&lt;p&gt;The best architecture is the one that lets you move fast now while not painting you into a corner for later. A well-structured monolith with clear module boundaries does exactly that. It's boring, it's pragmatic, and it ships.&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;BLN Craft&lt;/a&gt;, we build dev tools for developers who want to move faster without setting their architecture on fire first. If you're tired of infrastructure getting in the way of building, come take a look.&lt;/p&gt;

&lt;p&gt;Now go delete a Kubernetes cluster you didn't need.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>How AI Image Generation Is Quietly Eating Developer Workflows in 2026</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Tue, 26 May 2026 14:02:22 +0000</pubDate>
      <link>https://dev.to/blncraft/how-ai-image-generation-is-quietly-eating-developer-workflows-in-2026-46je</link>
      <guid>https://dev.to/blncraft/how-ai-image-generation-is-quietly-eating-developer-workflows-in-2026-46je</guid>
      <description>&lt;p&gt;You spent three years perfecting your pixel-art aesthetic. Congratulations — a neural network can now replicate it in 400 milliseconds.&lt;/p&gt;

&lt;p&gt;That's not a threat. That's actually the most interesting development in developer tooling this year, and if you're not thinking about how AI image and video generation slots into your build pipeline, you're leaving both time and money on the table.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Irony Is the Point
&lt;/h2&gt;

&lt;p&gt;Here's the 2026 situation: we are living through peak retro-aesthetic obsession — lo-fi pixel art, CRT shaders, chunky 8-bit sprites — at the exact same moment that AI image generation has crossed the uncanny valley and landed squarely in "indistinguishable from real" territory. Midjourney v7, Stable Diffusion XL successors, and a wave of API-first generators have made photorealistic content generation a commodity.&lt;/p&gt;

&lt;p&gt;For indie devs and small studio teams, this convergence is genuinely useful. You no longer need a motion designer on retainer to produce onboarding videos, asset variations, or marketing visuals. You need an API key, a prompt strategy, and about 45 minutes to wire it up.&lt;/p&gt;

&lt;p&gt;The tools that have reached serious adoption — like the generation platforms hitting millions of users in 2026 — tend to share a few traits: advanced editing, session-scoped privacy (assets auto-deleted after use), and programmatic access. Those aren't luxury features anymore. They're table stakes.&lt;/p&gt;

&lt;p&gt;Let's talk about how to actually use this in a dev context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wiring an AI Image Generation API Into Your Node Pipeline
&lt;/h2&gt;

&lt;p&gt;Most generation APIs follow the same basic pattern: POST a prompt and config, poll or receive a webhook with the result URL, download and store the asset. Here's a clean TypeScript implementation that works with any OpenAI-compatible image endpoint (swap the base URL for your provider of choice):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs/promises&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;GenerationOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;style&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;GenerationResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;localPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;generatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GenerationOptions&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GenerationResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;photorealistic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;outputDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./generated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.your-image-provider.com/v1/images/generate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;response_format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IMAGE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Download and persist locally — don't rely on ephemeral provider URLs&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`asset-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;.png`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;localPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;responseType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;arraybuffer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;localPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;generatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;generateImage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A Berlin street at dusk, neon reflections on wet cobblestones&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cinematic photography, 35mm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./assets/generated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`✓ Saved to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things worth noting here. First, always download and store the asset yourself — provider URLs are frequently ephemeral, especially on platforms with session-scoped deletion. Second, appending style descriptors to the prompt programmatically means you can run the same base prompt through multiple style passes in a loop without touching your prompt logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating Asset Variant Generation With a Bash Script
&lt;/h2&gt;

&lt;p&gt;If you're building a game, a marketing site, or anything that needs multiple visual variants of the same concept, doing this manually is exactly the kind of work you should automate. Here's a shell script that takes a base prompt and generates variants across a list of style modifiers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="nv"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IMAGE_API_KEY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;API_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.your-image-provider.com/v1/images/generate"&lt;/span&gt;
&lt;span class="nv"&gt;BASE_PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s1"&gt;'a developer working late in a Berlin apartment'&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;OUTPUT_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./generated-variants"&lt;/span&gt;

&lt;span class="nv"&gt;STYLES&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;
  &lt;span class="s2"&gt;"pixel art, 16-bit retro"&lt;/span&gt;
  &lt;span class="s2"&gt;"photorealistic, cinematic lighting"&lt;/span&gt;
  &lt;span class="s2"&gt;"watercolor illustration"&lt;/span&gt;
  &lt;span class="s2"&gt;"cyberpunk neon aesthetic"&lt;/span&gt;
  &lt;span class="s2"&gt;"minimalist flat design"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUTPUT_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;STYLE &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;STYLES&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;FULL_PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE_PROMPT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;STYLE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;SAFE_STYLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STYLE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;' ,'&lt;/span&gt; &lt;span class="s1"&gt;'__'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;OUTFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/variant_&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SAFE_STYLE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%s&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.png"&lt;/span&gt;

  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"→ Generating: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FULL_PROMPT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nv"&gt;RESPONSE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$API_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;prompt&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FULL_PROMPT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;width&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: 1024, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;height&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: 1024, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;response_format&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

  &lt;span class="nv"&gt;IMAGE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESPONSE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import sys, json; print(json.load(sys.stdin)['data'][0]['url'])"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

  curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUTFILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"✓ Saved: &lt;/span&gt;&lt;span class="nv"&gt;$OUTFILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;All variants generated in &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it as: &lt;code&gt;bash generate-variants.sh "a developer working late in a Berlin apartment"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You'll get five variants in under two minutes. Now pipe that into your asset build step, your Figma import workflow, or your CI/CD pipeline if you're generating OG images dynamically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Takeaways for Dev Teams
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Treat generation as a build step, not a manual task.&lt;/strong&gt; If you're hand-prompting images for every release, you're doing it wrong. Codify your prompts, version them in your repo, and run generation as part of your asset pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Session-scoped privacy matters for client work.&lt;/strong&gt; Platforms that auto-delete generated content after a session aren't just a marketing bullet point — they're genuinely relevant when you're generating assets for client projects under NDA. Know what your provider's data retention policy is before you use it professionally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Style-as-parameter is a design system concept now.&lt;/strong&gt; You can maintain a &lt;code&gt;styles.json&lt;/code&gt; config that maps your brand's visual language to prompt modifiers. Swap the style config per project. This is essentially a visual design token system for AI generation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The pixel-art irony is actually useful.&lt;/strong&gt; Generating a photorealistic base image and then applying a pixel-art post-process shader in your game engine or CSS gives you the best of both worlds: AI-quality composition and layout, retro aesthetic on top. This is a real technique people are shipping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Video is 6-12 months behind image in API maturity.&lt;/strong&gt; Most video generation APIs are still in closed beta or have rate limits that make them impractical for automated pipelines. Build your image workflow now; the video equivalent will slot in with minimal refactoring when it's ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;We're at a strange inflection point. The tools for generating realistic visual content are mature enough to be boring infrastructure, but most development teams are still treating them as novelty. The teams that will move fastest in the next 18 months are the ones that have already automated their asset generation and are spending their creative energy on the 10% that automation can't touch.&lt;/p&gt;

&lt;p&gt;Berlin-style honesty: the AI image generation hype cycle peaked about 18 months ago. What we have now is the boring, productive aftermath — commodity APIs, reasonable pricing, and enough stability to actually build on. That's the best time to start.&lt;/p&gt;




&lt;p&gt;BLN Craft builds developer tools for people who'd rather be shipping than configuring. If that sounds like you, come find us at &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;blncraft.com&lt;/a&gt; — we're always working on something that helps developers move faster without the usual nonsense.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>tooling</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Jira Is Turing-Complete (And You've Been Coding in It)</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Mon, 25 May 2026 07:06:21 +0000</pubDate>
      <link>https://dev.to/blncraft/jira-is-turing-complete-and-youve-been-coding-in-it-4h9l</link>
      <guid>https://dev.to/blncraft/jira-is-turing-complete-and-youve-been-coding-in-it-4h9l</guid>
      <description>&lt;p&gt;You didn't realize it, but the last time you built a Jira workflow, you wrote a program. A bad one, probably — no version control, no tests, no linter — but a program nonetheless.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Truth About Jira
&lt;/h2&gt;

&lt;p&gt;Jira started as a bug tracker. A humble list of things that were broken, assigned to people who would fix them. That was 2002. Fast-forward to today and Jira is a sprawling automation engine with conditional branching, state machines, persistent storage, and event-driven triggers. It has, without anyone really intending it to, crossed the threshold into Turing completeness.&lt;/p&gt;

&lt;p&gt;This isn't a hot take for engagement. Nicolas Seriot &lt;a href="https://seriot.ch/computation/jira.html" rel="noopener noreferrer"&gt;actually explored this&lt;/a&gt; — demonstrating that Jira's workflow and automation system is expressive enough to simulate computation. And once you see it, you can't unsee it.&lt;/p&gt;

&lt;p&gt;The implications are weird and worth unpacking.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Turing Completeness Actually Means (Briefly)
&lt;/h2&gt;

&lt;p&gt;A system is Turing complete if it can simulate any computation given enough time and memory. The classic examples are Rule 110, Conway's Game of Life, and — now, apparently — your company's sprint board.&lt;/p&gt;

&lt;p&gt;The key ingredients: conditional logic, state that persists, and the ability to loop. Jira has all three:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workflows&lt;/strong&gt; are finite state machines. Statuses are states. Transitions are edges. Guards on transitions are conditionals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom fields&lt;/strong&gt; are persistent memory. You can read them, write them, and branch on their values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automations&lt;/strong&gt; are event-driven triggers with branching logic, field updates, and the ability to create or modify issues — including triggering further automations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point is the kicker. Automations can trigger automations. You have recursion. Or at least iteration. You're cooked.&lt;/p&gt;

&lt;h2&gt;
  
  
  You've Already Written Jira Programs
&lt;/h2&gt;

&lt;p&gt;Here's a concrete example. Say you build a workflow where:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A ticket enters &lt;strong&gt;In Review&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;An automation checks a custom field &lt;code&gt;review_pass_count&lt;/code&gt; (integer)&lt;/li&gt;
&lt;li&gt;If it's less than 2, it increments the field and transitions the ticket back to &lt;strong&gt;In Progress&lt;/strong&gt; with a comment&lt;/li&gt;
&lt;li&gt;If it's 2 or more, it transitions to &lt;strong&gt;Done&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's a loop with a counter. That's a &lt;code&gt;while&lt;/code&gt; loop. In Jira.&lt;/p&gt;

&lt;p&gt;In pseudocode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;review_pass_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;review_pass_count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;In Progress&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;review_pass_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Done&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Jira automation that implements this looks roughly like the following when exported as JSON (Jira Cloud lets you import/export automation rules as JSON):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trigger"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FIELD_VALUE_CHANGED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"configuration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"toStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"In Review"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"conditions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISSUE_FIELDS_CONDITION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"configuration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"conditions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cf[10042]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"operator"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LESS_THAN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EDIT_ISSUE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"configuration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"fieldId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cf[10042]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{issue.cf[10042] + 1}}"&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TRANSITION_ISSUE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"configuration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"transitionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"11"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is real. This works. You just programmed a loop in a project management tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State Machine Is Already There
&lt;/h2&gt;

&lt;p&gt;Workflows are the part of Jira most developers ignore because they're "an admin thing." They shouldn't be. A Jira workflow is literally a directed graph — statuses as nodes, transitions as edges. That's a state machine, which is the foundation of a huge portion of real software: parsers, network protocols, UI components, game logic.&lt;/p&gt;

&lt;p&gt;Here's a simple TypeScript representation of what your Jira workflow actually is under the hood:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backlog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Transition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;action&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;workflowTransitions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Backlog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;review_pass_count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Review&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;review_pass_count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;review_pass_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;review_pass_count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Progress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;workflowTransitions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;guard&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exactly what Jira is doing internally. Your workflow configuration &lt;em&gt;is&lt;/em&gt; this code. It's just stored in a database and executed by their engine instead of a JavaScript runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  So What Do We Do With This Information?
&lt;/h2&gt;

&lt;p&gt;A few things, practically speaking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Version control your Jira automations.&lt;/strong&gt;&lt;br&gt;
If you accept that automations are code, they deserve version control. Export automation JSON regularly and commit it to a repo. Yes, this is tedious. So is debugging a production automation that someone silently changed three months ago.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Document your workflow logic like you'd document code.&lt;/strong&gt;&lt;br&gt;
Workflow screens in Jira are visual but not readable. Screenshot them, export them, and write a README explaining the intent. Future-you (or a new teammate) will need it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Resist the urge to build complex logic inside Jira.&lt;/strong&gt;&lt;br&gt;
Just because you &lt;em&gt;can&lt;/em&gt; build a loop counter in Jira doesn't mean you should. If your automation JSON exceeds ~50 lines, consider whether a real webhook + a small serverless function is more maintainable. It almost certainly is. Use Jira for state, use code for logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Use the API to inspect what you've built.&lt;/strong&gt;&lt;br&gt;
Jira's REST API lets you pull workflow schemes and automation rules programmatically. If you're inheriting a Jira instance, this is how you audit it without clicking through 47 admin screens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-u&lt;/span&gt; your@email.com:YOUR_API_TOKEN &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://your-domain.atlassian.net/rest/api/3/workflowscheme"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="s1"&gt;'.[].name'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns the names of all workflow schemes in your instance. A starting point for understanding what kind of program you've accidentally inherited.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Deeper Point
&lt;/h2&gt;

&lt;p&gt;Jira being Turing complete isn't a party trick. It's a symptom of a broader pattern: the tools we use to &lt;em&gt;manage&lt;/em&gt; software are becoming as complex as the software they manage. Notion has formulas. Airtable has scripts. GitHub Actions is clearly a programming language (a bad one). The line between "configuration" and "code" has dissolved.&lt;/p&gt;

&lt;p&gt;This means two things. First, developers should stop delegating tool configuration entirely to project managers and admins — there is code in there, and it deserves engineering attention. Second, the next time someone asks why your sprint velocity is down, you can honestly say you've been debugging a distributed state machine with no observability tooling.&lt;/p&gt;

&lt;p&gt;That's a real answer.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;BLN Craft builds developer tools for people who want to ship faster and think more clearly about their systems. If that sounds like you, check out what we're working on at &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;blncraft.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devtools</category>
      <category>automation</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The AI Dev Stack That Actually Works in 2026</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Sat, 23 May 2026 09:42:33 +0000</pubDate>
      <link>https://dev.to/blncraft/the-ai-dev-stack-that-actually-works-in-2026-5ffn</link>
      <guid>https://dev.to/blncraft/the-ai-dev-stack-that-actually-works-in-2026-5ffn</guid>
      <description>&lt;h1&gt;
  
  
  The AI Dev Stack That Actually Works in 2026
&lt;/h1&gt;

&lt;p&gt;It's 2026. Your team has been shipping with Claude for two years. You've watched Cursor go from "interesting VSCode fork" to table stakes. You've automated half your n8n workflows. And you've probably noticed something: the hype was real, but the execution gap is brutal.&lt;/p&gt;

&lt;p&gt;Most devs are still treating AI like a search engine that types code. They're not. The actual shift in 2026 isn't "AI writes your code." It's "AI &lt;em&gt;executes&lt;/em&gt; your intent when configured correctly." And that configuration—the rules, the prompts, the workflow definitions—is where the real work lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Changed Since 2024
&lt;/h2&gt;

&lt;p&gt;Two years ago, the pitch was simple: "Describe what you want, Claude builds it." Turns out, that's not how humans and machines actually work together at scale.&lt;/p&gt;

&lt;p&gt;What's different now:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Rules beat prompts.&lt;/strong&gt; A well-written Cursor rule or CLAUDE.md file beats a 500-word system prompt. Rules are composable, versionable, and don't get lost in conversation history. Teams that invested in rule libraries in 2024 are 3x faster than teams still winging it with ad-hoc prompts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Workflows are the moat.&lt;/strong&gt; Raw model capability plateaued. Claude 3.7 isn't drastically smarter than 3.5. But n8n workflows—the ones that chain API calls, validate outputs, retry intelligently, and feed results back into your system—those workflows are where DevX and ROI collide. Every workflow you automate is one less human context-switch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Integration maturity matters.&lt;/strong&gt; Cursor's deep LSP integration, Claude Code's reasoning-first approach, and n8n's ability to handle state and error recovery. The stack that wins in 2026 isn't the one with the smartest model. It's the one with the tightest integration between editor, reasoning engine, and automation layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack That Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Cursor + Claude.md / Cursor Rules&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Your source of truth for how AI should behave in your codebase. Not in Slack. Not in some shared notion doc. In version control, alongside your code.&lt;/p&gt;

&lt;p&gt;Here's what a production Cursor rule looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# You are a TypeScript/React specialist optimizing for performance and accessibility.&lt;/span&gt;
&lt;span class="gh"&gt;# Context: This is a design system for healthcare applications.&lt;/span&gt;

&lt;span class="gu"&gt;## Core Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; All components must pass axe accessibility audit
&lt;span class="p"&gt;-&lt;/span&gt; Prefer Signals over Context for state when tree depth &amp;gt; 3
&lt;span class="p"&gt;-&lt;/span&gt; CSS modules for styling; no inline styles
&lt;span class="p"&gt;-&lt;/span&gt; All async operations must have cancellation tokens

&lt;span class="gu"&gt;## Code Patterns&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`useCallback`&lt;/span&gt; only for event handlers passed to children (avoid memoization overhead)
&lt;span class="p"&gt;-&lt;/span&gt; Never re-export from index files; use explicit imports
&lt;span class="p"&gt;-&lt;/span&gt; Test files live alongside source; suffix with &lt;span class="sb"&gt;`.test.ts`&lt;/span&gt;

&lt;span class="gu"&gt;## When to Use Claude&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Refactoring: Always. Especially migrations (e.g., Tailwind → CSS Modules)
&lt;span class="p"&gt;-&lt;/span&gt; New features: Only after requirements are concrete
&lt;span class="p"&gt;-&lt;/span&gt; Debugging: Only after you've checked the obvious stuff

&lt;span class="gu"&gt;## When NOT to Use Claude&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Architectural decisions: These are human calls
&lt;span class="p"&gt;-&lt;/span&gt; Security logic: Review manually, always
&lt;span class="p"&gt;-&lt;/span&gt; Package selection: You own the tradeoff analysis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That rule lives in your repo. Every new contributor reads it. Cursor reads it. Claude reads it. Consistency emerges without Slack discussions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;n8n for the Workflows That Compound&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Not every automation is worth building. But certain ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code quality gates that run on every PR&lt;/li&gt;
&lt;li&gt;Feedback loops that train your Cursor/Claude configuration&lt;/li&gt;
&lt;li&gt;Integration glue (Slack → Jira → GitHub → metrics)&lt;/li&gt;
&lt;li&gt;Polling and retry logic (the stuff that's boring to write but critical to scale)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a real n8n workflow JSON snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nodes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trigger: GitHub PR Created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webhook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"typeVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"github-pr-hook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"httpMethod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Run Code Quality Check"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"n8n-nodes-base.http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"typeVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.claude.ai/v1/messages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"predefined"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"authType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bearer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"sendBody"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"bodyParameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-3-5-sonnet-20241022"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"max_tokens"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2048"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are a code reviewer. Check for security flaws, performance issues, and accessibility problems."&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;role&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Review: {{ $node.&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Trigger: GitHub PR Created&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;.json.body.pull_request.diff_url }}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}]"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Post Result to GitHub"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"n8n-nodes-base.githubTrigger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"typeVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;750&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Code Review: {{ $node.&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Run Code Quality Check&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;.json.body.content[0].text }}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow runs on every PR, calls Claude, and posts findings to GitHub. No humans in the loop (initially). Humans review the findings. The workflow improves.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Devs Get Wrong
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. No Cursor rules or CLAUDE.md.&lt;/strong&gt; They improvise. Every session is a negotiation. This scales to chaos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Building workflows from scratch.&lt;/strong&gt; There are 350 common patterns. Why reinvent? We ship pre-built n8n templates for: PR review, documentation generation, test case creation, dependency updates, and more. (We literally built this at BLN Craft.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Treating the AI as a oracle, not a tool.&lt;/strong&gt; The teams winning in 2026 use Claude/Cursor for &lt;em&gt;execution&lt;/em&gt;, not ideation. Architects still design. Devs still understand the problem. AI automates the repetitive parts—the parts that are easy to specify, hard to write, and easy to verify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Ignoring error handling in workflows.&lt;/strong&gt; A workflow that fails silently is worse than no workflow. Add retry logic, fallbacks, and alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Start
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write your first Cursor rule.&lt;/strong&gt; Spend 30 minutes. Commit it. Share it with your team. Iterate based on what works.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pick one workflow to automate.&lt;/strong&gt; Not the hardest one. The most repetitive one. The one that feels like busy work. Automate it in n8n.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Measure.&lt;/strong&gt; How much time did you save? Did quality improve? Did it introduce new bugs? Adjust.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We ship production-ready rules and 350+ workflow templates at &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;blncraft.com&lt;/a&gt; for this exact setup. The CLAUDE.md + Cursor Rules Production Pack ($49) has templates you can fork. The n8n AI Workflow Templates ($79) cover most of the patterns we mentioned.&lt;/p&gt;

&lt;p&gt;The AI dev stack in 2026 isn't mysterious. It's rules-based, versionable, integrated, and measurable. Build it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; Head to &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;blncraft.com&lt;/a&gt;, grab the Cursor rules pack, and run them in your next PR review. Let us know what breaks. That's how we all get smarter.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cursor</category>
      <category>automation</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Ship n8n Workflows 10x Faster (Stop Building From Scratch)</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Sat, 23 May 2026 09:41:19 +0000</pubDate>
      <link>https://dev.to/blncraft/ship-n8n-workflows-10x-faster-stop-building-from-scratch-38gl</link>
      <guid>https://dev.to/blncraft/ship-n8n-workflows-10x-faster-stop-building-from-scratch-38gl</guid>
      <description>&lt;p&gt;You're staring at a blank n8n canvas. Again.&lt;/p&gt;

&lt;p&gt;Your client needs an AI workflow that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ingests data from three different sources&lt;/li&gt;
&lt;li&gt;Processes it through an LLM&lt;/li&gt;
&lt;li&gt;Handles errors gracefully&lt;/li&gt;
&lt;li&gt;Logs everything to their data warehouse&lt;/li&gt;
&lt;li&gt;Runs on a schedule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds straightforward, right? Except it's 2 AM, you've already burned three hours debugging node configurations, and you're still not sure if your error handling is bulletproof enough for production.&lt;/p&gt;

&lt;p&gt;This is the n8n tax. Not the tool's fault—it's powerful and genuinely flexible. But that flexibility comes with a cost: every workflow starts from zero. Every integration needs careful node setup. Every edge case feels like you're inventing it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Cost of Building n8n Workflows from Scratch
&lt;/h2&gt;

&lt;p&gt;Here's what developers don't talk about enough: workflow automation looks simple until it isn't. You'll spend 70% of your time on the same boring stuff:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuration boilerplate.&lt;/strong&gt; Setting up HTTP nodes with proper auth headers, pagination logic, and retry strategies. Setting up database connections with connection pooling. Handling API rate limits. None of this is complex—it's just... tedious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error handling patterns.&lt;/strong&gt; What happens when an API times out? When a webhook fails? When your LLM call costs $50 by accident? You need guards. You need observability. You need to think through failure modes that everyone else already solved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integration wiring.&lt;/strong&gt; Getting Slack → OpenAI → Google Sheets to play nicely together involves remembering node syntax, parameter naming conventions, and data transformation quirks. It's not hard, but it's easy to get wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing in production.&lt;/strong&gt; Because n8n doesn't have a great local testing story, you end up running workflows and watching logs. Finding a bug means updating the workflow, redeploying, and trying again.&lt;/p&gt;

&lt;p&gt;Multiply this by every client project, every AI automation you ship, and you've lost weeks of your life to problems that have already been solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Battle-Tested Workflow Templates Actually Solve
&lt;/h2&gt;

&lt;p&gt;A good template isn't just a starting point—it's a working implementation with the boring stuff already handled. You copy it, swap three values, and you're running in production.&lt;/p&gt;

&lt;p&gt;Let's be specific. Here's what a real HTTP → AI → Database workflow template needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nodes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"n8n-nodes-base.httpRequest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.example.com/data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oAuth2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"User-Agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"n8n-automation/1.0"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"retryOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"maxRetries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"delayBase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"delayMultiplier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"n8n-nodes-base.openAi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gpt-4-turbo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Analyze this data: {{ $json.body }}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"errorHandling"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"continueOnFail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"raiseOnError"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there's more. Here's the actual wiring that stops most people:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"n8n-nodes-base.postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;650&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"executeQuery"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INSERT INTO ai_results (id, input, output, created_at) VALUES ($1, $2, $3, NOW()) RETURNING id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"queryParameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{ $json.body.id }}, {{ $json.body.input }}, {{ $json.choices[0].message.content }}"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"credentials"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postgres-prod"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See what just happened? We connected three different systems with proper error handling, credential management, and data transformation. That's roughly 2 hours of debugging and documentation reading compressed into 10 minutes of copy-paste.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 350-Template Shortcut
&lt;/h2&gt;

&lt;p&gt;Now imagine having this for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;50+ AI automation patterns&lt;/strong&gt;: LLM-powered data processing, content generation, summarization, classification, RAG pipelines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API integration templates&lt;/strong&gt;: Slack, Discord, Telegram, email, webhooks—all with proper auth and error handling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database operations&lt;/strong&gt;: PostgreSQL, MongoDB, Airtable, Google Sheets—with transaction handling and bulk operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data transformation workflows&lt;/strong&gt;: CSV processing, JSON transformation, PDF extraction, image processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring &amp;amp; observability&lt;/strong&gt;: Error alerting, execution logging, cost tracking, performance metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced patterns&lt;/strong&gt;: Fan-out/fan-in, conditional branching, parallel processing, queue management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each template is:&lt;/p&gt;

&lt;p&gt;✓ &lt;strong&gt;Production-ready.&lt;/strong&gt; Handles errors, retries, timeouts, and edge cases.&lt;br&gt;
✓ &lt;strong&gt;Documented.&lt;/strong&gt; Clear parameter setup with inline comments.&lt;br&gt;
✓ &lt;strong&gt;Customizable.&lt;/strong&gt; Built to be forked and adapted, not dogmatic.&lt;br&gt;
✓ &lt;strong&gt;Real-world tested.&lt;/strong&gt; From actual client work, not theoretical exercises.&lt;/p&gt;

&lt;p&gt;You're not learning n8n syntax by trial and error anymore. You're learning it by reading working code. You're shipping faster because 80% of the tedium is already handled.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Math
&lt;/h2&gt;

&lt;p&gt;If you save 2 hours per workflow (conservative estimate), and you ship 10 workflows a year, that's 20 hours recovered. At a typical developer rate, that's $3,000–5,000 in reclaimed time annually.&lt;/p&gt;

&lt;p&gt;The templates cost $79.&lt;/p&gt;

&lt;p&gt;I'm not going to pretend this is purely utilitarian—the real win is in how it feels. You're not wrestling with boilerplate. You're architecting solutions. You're thinking about the problem, not about node configuration syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Start
&lt;/h2&gt;

&lt;p&gt;You can grab the full 350-template pack at &lt;a href="https://blncraft.gumroad.com/l/kgcfeh" rel="noopener noreferrer"&gt;https://blncraft.gumroad.com/l/kgcfeh&lt;/a&gt; ($79)—or start with the free samples at blncraft.com to get a feel for what's inside.&lt;/p&gt;

&lt;p&gt;The best template is the one you actually use. The second-best template is the one you started from.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Your AI Code Generator Keeps Hallucinating (And How to Fix It)</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Sat, 23 May 2026 09:39:20 +0000</pubDate>
      <link>https://dev.to/blncraft/why-your-ai-code-generator-keeps-hallucinating-and-how-to-fix-it-31ic</link>
      <guid>https://dev.to/blncraft/why-your-ai-code-generator-keeps-hallucinating-and-how-to-fix-it-31ic</guid>
      <description>&lt;p&gt;In the world of software development, having an AI that generates code often sounds like a dream. Yet, when the dream AI starts hallucinating more than a psychedelic mushroom trip, things get ugly fast. As a developer, you want your AI to help, not hinder, your path to production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Trouble with LLM Hallucinations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When working with AI systems like Claude or Cursor, one major issue developers encounter is the puzzling phenomenon of AI 'hallucinations'. This isn’t your AI taking a lay-down for a mid-morning nap; it's when your AI starts generating code that seems credible but is completely bogus. It’s akin to having a developer who’s confident but terribly wrong (we’ve all been there, right?).&lt;/p&gt;

&lt;p&gt;The frustration builds when you realize these hallucinations increase debugging time, reduce code reliability, and ultimately delay shipping your software. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why AI Hallucinations Happen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core of these problems stems from the AI's attempt to infer and generate outputs without a clear understanding of the context or incorrect rules configurations. Sadly, default configurations sometimes don't cut it. They leave gaps through which hallucinations comfortably sneak in.&lt;/p&gt;

&lt;p&gt;Many developers fail to provide their AI with precise guidelines, thinking the AI is smart enough to interpret all contexts—spoiler alert, it's not. A lack of structured rules within your AI framework leads to the AI filling in the blanks with optimistic guesses that can lead to failure.&lt;/p&gt;

&lt;p&gt;Let's explore some typical faux pas with the AI code generation and how to dodge them effectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Illustrating the AI Misunderstandings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you are using a language model to generate a REST API endpoint. You want to create a user profile feature using the AI, expecting it to give you a well-formed function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Unreliable AI Output&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/user/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getUserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// AI hallucinated function&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI might create 'getUserProfile', which doesn't exist or call non-existent data fetching logic. The hallucinated function above gets thrown in the mix—sounds credible but is impractical without prior setup.&lt;/p&gt;

&lt;p&gt;To prevent such blunders, you might want to define strict rules for your AI about expected functions and data flows.&lt;/p&gt;

&lt;p&gt;In another scenario, manipulating an array of numbers is required to calculate their average. Your expectation is straightforward but the AI, alas, might see it differently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AI hallucination&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculateAverage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// What is numbers.count()?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code appears fine at a shallow glance, but that mysterious 'numbers.count()' isn't part of any recognizable API. This mistake is symptomatic of missing configuration rules guiding the AI’s thought process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution: Configuring AI with Production-Ready Rules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Deploying AI in production requires more than just throwing data at it and hoping for the best. This is where the &lt;strong&gt;CLAUDE.md + Cursor Rules Production Pack&lt;/strong&gt; steps in. These are not just another set of rules but a battle-tested configuration pack that mitigates hallucinations significantly, aiding your AI in shipping reliable code with fewer headaches.&lt;/p&gt;

&lt;p&gt;By incorporating precise and structured rules into your AI’s configuration, you guide it to follow established patterns, reducing the risk of fabricating logic and functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Reliable AI Code Generation Example&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchUserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Actual data fetching logic&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/user/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchUserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach puts your AI on the right track, providing it the necessary context and APIs to generate solutions beyond the dreams of imaginary functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrap-up: Why Proper AI Configuration Changes the Game&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Investing time in proper rule configuration could be the difference between agile deployments and a quagmire of debug sessions. &lt;strong&gt;CLAUDE.md + Cursor Rules Production Pack&lt;/strong&gt; gives you a leg-up on configuring AI, allowing you to harness the power of AI confidently while keeping reigns on the spontaneous bursts of wrong code.&lt;/p&gt;

&lt;p&gt;Grab the full pack at &lt;a href="https://blncraft.gumroad.com/l/claude-cursor-rules-pack" rel="noopener noreferrer"&gt;BLN Craft on Gumroad&lt;/a&gt; ($49) — or start with the free sample at &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;BLN Craft&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A small investment now can save countless hours in the future.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Why Every Developer's Honest: The Lies AI Won't Catch</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Fri, 22 May 2026 07:05:34 +0000</pubDate>
      <link>https://dev.to/blncraft/why-every-developers-honest-the-lies-ai-wont-catch-1154</link>
      <guid>https://dev.to/blncraft/why-every-developers-honest-the-lies-ai-wont-catch-1154</guid>
      <description>&lt;h3&gt;
  
  
  Secrets We Hide: An Open Confession
&lt;/h3&gt;

&lt;p&gt;Developers, it’s time we admit it: we’ve all got our secret coding fibs. While AI might impress us with code-suggesting wizardry, it still won't put our little white lies on blast. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Nature of Our Little Secrets
&lt;/h3&gt;

&lt;p&gt;This isn't about the big stuff. We're talking about those minor missteps we sweep under the keyboard: like claiming to understand Regex while heartily consulting Stack Overflow or setting up that ‘temporary’ fix a little too permanently. Why does this matter? Because it's part of our nature and shapes our work in significant ways.&lt;/p&gt;

&lt;p&gt;Imagine you're maintaining a legacy codebase. Rewriting it line by line, you tell yourself, "I won’t get tangled in this web again." Yet, two weeks later, there you are, embracing that very web while whispering, "This is temporary, honest." AI might help refactor code or offer suggestions but achieving genuine honesty in coding? That's still a human endeavor. &lt;/p&gt;

&lt;h3&gt;
  
  
  When Code Reviews Aren't the Solution
&lt;/h3&gt;

&lt;p&gt;If you've ever participated in a code review, you know they’re designed to ferret out issues, not secrets. For instance, a condition might pass a review despite your best guesswork in configuring those timeout settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;retries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;retries&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Retrying...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;retries&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fetch failed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That retry logic is all well and good, but you're secretly hoping no one realizes you picked 5 as the number of retries because it seemed...lucky?&lt;/p&gt;

&lt;h3&gt;
  
  
  Learning from Our Fibbing
&lt;/h3&gt;

&lt;p&gt;Here's a real doozy: how many developers can honestly say the comments in their code always match the code’s behavior?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; 
    &lt;span class="c1"&gt;# Returns area of a square (wait, this comment is a lie!) 
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These fibs may seem benign, but there's something deeper at play here: our striving for perfection in an imperfect world. AI can propose better calculations, but it won’t make you label functions more transparently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Turning Secrets into Success: Practical Takeaways
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Embrace Transparency:&lt;/strong&gt; Don’t embellish. Code comments should accurately reflect what's happening. Utilize thorough documentation to clear up ambiguity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assign AI its Limits:&lt;/strong&gt; Use AI for standard tasks like error detection but take ownership of decisions and changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Call Out Myths:&lt;/strong&gt; During code reviews, don't shy away from discussing those ‘temporary’ fixes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-Review:&lt;/strong&gt; Regularly assess your motivations. Are you privileging expediency over quality? Who will suffer from your code fib when AI reviews come up short?&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Closing Thoughts
&lt;/h3&gt;

&lt;p&gt;The truth is, while AI can facilitate faster, more efficient workflows, it can’t quite diagnose our uniquely human fallacies or fibs. We manufacture those as quickly as we write our bug reports.&lt;/p&gt;

&lt;p&gt;For more about innovative developer tools that help you move faster (but only you can handle honesty), check out &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;BLN Craft&lt;/a&gt;. Because we’re all about enhancing human capability, not replacing it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>python</category>
      <category>ai</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Why Undefined Behavior in C is Every Developer's Worst Nightmare</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Wed, 20 May 2026 08:37:04 +0000</pubDate>
      <link>https://dev.to/blncraft/why-undefined-behavior-in-c-is-every-developers-worst-nightmare-1215</link>
      <guid>https://dev.to/blncraft/why-undefined-behavior-in-c-is-every-developers-worst-nightmare-1215</guid>
      <description>&lt;p&gt;When it comes to C programming, undefined behavior is like finding out your code has been renting a horror movie without your permission. It's unsettling and likely to come back to haunt you.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Context: Welcome to Horrorland
&lt;/h3&gt;

&lt;p&gt;In the vast spooky landscape of C, undefined behavior (UB) lurks in the shadows, ready to pounce when you least expect it. It's the ghoul that hides in your closet, the monster under your bed, and if you're not careful, your code's potential doom. You might ask, &lt;em&gt;Why does undefined behavior matter?&lt;/em&gt; Because it's unpredictable, that's why. It treats the compiler like an improvisational actor who's just gone entirely off-script — who can say what they'll do next?&lt;/p&gt;

&lt;p&gt;The International Organization for Standardization (ISO) describes undefined behavior as an ominous absence of restrictions for the code execution. Imagine being perfectly sure that the lights in your dev bunker will turn on, only for them to flicker and throw you into darkness. That's your clue that something UB-like is happening.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Examples: Practical Monsters
&lt;/h3&gt;

&lt;p&gt;Let's take a gander at some real code examples, shall we?&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 1: The Signed Integer Conundrum
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2147483647&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Maximum positive value for a 32-bit signed binary integer&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Say hello to overflow without safety nets!&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Oh no, what happened to 'b'? It's %d!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In theory, one might expect &lt;code&gt;b&lt;/code&gt; to ideally increment to 2147483648, but surprise: C doesn't care. When signed integer overflow happens — consult your fortune teller, because the result is anyone’s guess.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 2: Dereferencing Wild Pointers
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;uninitialized_pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This one's got no name tag, just lurking around&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;uninitialized_pointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Accessing verboten memory territory&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This might not print because UB has struck!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this snippet, we're playing Russian roulette with memory access. Dereferencing pointers without initialization is a standard UB horror route that can send your program spiraling into oblivion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Takeaways: Keeping the Boogeyman at Bay
&lt;/h3&gt;

&lt;p&gt;How do you protect your code from the dreaded UB? Here's your survival guide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialize Your Variables&lt;/strong&gt;: Always give them a proper home before inviting them to your party.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Compiler Warnings&lt;/strong&gt;: Compilers like GCC exist to be your best friends. Let them tell you when you're flirting with danger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get Comfortable with Static Analysis Tools&lt;/strong&gt;: Tools like Clang and Valgrind can be tremendously helpful. Think of them as the Ghostbusters for your spooky code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Undefined Constructs&lt;/strong&gt;: Stay away from controversial areas like signed overflows. It’s not worth the headache or ghost sightings.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Closing Thoughts
&lt;/h3&gt;

&lt;p&gt;Undefined behavior is mysterious, treacherous, and exactly why you need to arm yourself appropriately. Banish those developer nightmares by understanding the true nature of the UB beasts.&lt;/p&gt;

&lt;p&gt;Ready to exorcise the demons from your code? Head over to &lt;a href="https://blncraft.com" rel="noopener noreferrer"&gt;BLN Craft&lt;/a&gt;, where we ship dev tools for developers who want to move faster and code less hauntingly.&lt;/p&gt;

</description>
      <category>c</category>
      <category>programming</category>
      <category>security</category>
      <category>devtools</category>
    </item>
    <item>
      <title>How We Built 162 Production Rules Files for Claude Code and Cursor (And Why You Should Too)</title>
      <dc:creator>BLNCraft</dc:creator>
      <pubDate>Tue, 19 May 2026 13:16:40 +0000</pubDate>
      <link>https://dev.to/blncraft/how-we-built-162-production-rules-files-for-claude-code-and-cursor-and-why-you-should-too-4b0m</link>
      <guid>https://dev.to/blncraft/how-we-built-162-production-rules-files-for-claude-code-and-cursor-and-why-you-should-too-4b0m</guid>
      <description>&lt;p&gt;Cursor 3.3 just shipped parallel agents and worktrees. If you're using AI coding assistants in production, the quality of your rules files is now a multiplier — not just for one agent, but for every parallel agent running in your workspace.&lt;/p&gt;

&lt;p&gt;We've been using Claude Code and Cursor daily across a range of projects. Over the past year, we accumulated a library of rules files for 54 dev stacks. We just packaged and released them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are CLAUDE.md and .cursorrules files?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CLAUDE.md&lt;/strong&gt; is the project-level instruction file for Claude Code (Anthropic's CLI coding agent). It's loaded automatically when Claude Code starts a session in your project. You use it to define conventions, patterns, testing requirements, and constraints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.cursorrules&lt;/strong&gt; is the equivalent for Cursor IDE. It's loaded by Cursor's AI features (Composer, Chat, Tab) to guide code generation.&lt;/p&gt;

&lt;p&gt;Both serve the same purpose: telling the AI how your project works so it generates code that fits your codebase instead of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why generic rules don't work
&lt;/h2&gt;

&lt;p&gt;Most rules files you find online are generic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Write clean, maintainable code
- Follow best practices
- Add comments where necessary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the equivalent of telling a new hire "write good code." It doesn't work because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Every stack has specific conventions&lt;/strong&gt; — React hooks have rules, FastAPI has dependency injection patterns, Rust has error handling idioms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-patterns are stack-specific&lt;/strong&gt; — the things an AI gets wrong in Go are different from what it gets wrong in TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your team's conventions matter&lt;/strong&gt; — snake_case vs camelCase, barrel exports vs direct imports, test file locations&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's in our pack
&lt;/h2&gt;

&lt;p&gt;We built rules files for 54 stacks:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Stacks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;React, Next.js, Vue, Svelte, Angular, Astro, Remix, Solid, Qwik&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;FastAPI, Django, Flask, Express, NestJS, Hono, Rails, Spring Boot, Laravel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Systems&lt;/td&gt;
&lt;td&gt;Rust, Go, C++, Zig&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile&lt;/td&gt;
&lt;td&gt;React Native, Swift/iOS, Kotlin/Android, Flutter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infra&lt;/td&gt;
&lt;td&gt;Docker, Kubernetes, Terraform, Pulumi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;PostgreSQL, MongoDB, Redis, Prisma, Drizzle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Languages&lt;/td&gt;
&lt;td&gt;TypeScript, Python, Rust, Go, Java, C#, Ruby, PHP, Elixir&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each stack gets three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CLAUDE.md&lt;/strong&gt; — full rules for Claude Code (typically 100-200 lines of specific conventions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.cursorrules&lt;/strong&gt; — condensed version for Cursor IDE (focused on code generation patterns)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;README.md&lt;/strong&gt; — explains what each rule enforces and why&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: FastAPI CLAUDE.md excerpt
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## API Patterns&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use Pydantic v2 model_validator instead of root_validator
&lt;span class="p"&gt;-&lt;/span&gt; Return Pydantic models directly from endpoints, never dict()
&lt;span class="p"&gt;-&lt;/span&gt; Use Annotated[Depends(...)] for dependency injection
&lt;span class="p"&gt;-&lt;/span&gt; Async handlers only — no sync def endpoints
&lt;span class="p"&gt;-&lt;/span&gt; HTTPException for client errors, let unexpected errors propagate

&lt;span class="gu"&gt;## Testing&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use httpx.AsyncClient, not TestClient
&lt;span class="p"&gt;-&lt;/span&gt; Fixtures: db_session, async_client, authenticated_client
&lt;span class="p"&gt;-&lt;/span&gt; Test file mirrors source: tests/api/test_users.py → src/api/users.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare that to "follow FastAPI best practices." One tells the AI exactly what to do. The other tells it nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use them
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Download the pack&lt;/li&gt;
&lt;li&gt;Find your stack folder&lt;/li&gt;
&lt;li&gt;Copy &lt;code&gt;CLAUDE.md&lt;/code&gt; to your project root (for Claude Code)&lt;/li&gt;
&lt;li&gt;Copy &lt;code&gt;.cursorrules&lt;/code&gt; to your project root (for Cursor)&lt;/li&gt;
&lt;li&gt;Customize for your team's specific conventions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. No setup, no dependencies. Drop in and go.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cursor 3.3 multiplier
&lt;/h2&gt;

&lt;p&gt;With Cursor 3.3's parallel agents, good rules files compound. Each agent that spins up in a worktree loads your .cursorrules. If those rules are specific and accurate, every agent produces code that fits your codebase. If they're generic, you're reviewing and fixing output from multiple agents simultaneously.&lt;/p&gt;

&lt;p&gt;162 rules files covering 54 stacks. €29 one-time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://blncraft.gumroad.com/l/claude-cursor-rules-pack" rel="noopener noreferrer"&gt;Get the pack on Gumroad →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
