How I Automated My Entire Dev Workflow With 8 Cursor Rules…
    Neura MarketNeura Market/Cursor
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeek
    CoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    View All Directories
    OverviewRulesPromptsMCPsAgentsGamesBlogVideosGuidesCoursesCommunityExtensionsTrending
    CursorBlogHow I Automated My Entire Dev Workflow With 8 Cursor Rules (and What Changed)
    Back to Blog
    How I Automated My Entire Dev Workflow With 8 Cursor Rules (and What Changed)
    cursorrules

    How I Automated My Entire Dev Workflow With 8 Cursor Rules (and What Changed)

    Olivia Craft April 24, 2026
    0 views

    How I Automated My Entire Dev Workflow With 8 Cursor Rules (and What Changed) It was 11:47...

    How I Automated My Entire Dev Workflow With 8 Cursor Rules (and What Changed)

    It was 11:47 PM on a Tuesday when I realized I'd just spent forty minutes fixing a bug that Cursor had written for me that morning.

    The AI had happily generated a fetch() call with no error handling, no types on the response, a stray console.log('here') left in for good measure, and a commit message that read fixes stuff. Every one of those choices was fine in the moment. Every one of those choices cost me an hour at midnight.

    That's when I stopped prompting and started writing rules.

    Over the next few weeks I replaced the nagging, the re-prompting, and the "please remember we use TypeScript strict" with eight entries in my .cursorrules file. My workflow stopped being something I executed and became something the AI executed for me — correctly, every time.

    Here are the eight rules, with concrete before/after examples and what changed once they were in place.


    Rule 1: Test-First — Write the Failing Test Before the Code

    Before implementing any function, write a failing test for it first.
    Place the test next to the source file as *.test.ts. Only then
    write the minimum code needed to make the test pass.
    

    Before: I'd accept a 40-line function, then try to retrofit tests around its actual (often wrong) behavior.

    // Cursor's default: implementation first, tests never
    export function parseDuration(input: string): number {
      // ...40 lines of regex and edge cases, no tests
    }
    

    After: Cursor generates the test first, which forces it to clarify the contract before writing any logic.

    // parseDuration.test.ts — written first
    describe('parseDuration', () => {
      it('parses "2h 30m" as 9000 seconds', () => {
        expect(parseDuration('2h 30m')).toBe(9000);
      });
      it('throws on invalid input', () => {
        expect(() => parseDuration('banana')).toThrow();
      });
    });
    
    // parseDuration.ts — written to pass the tests
    export function parseDuration(input: string): number {
      // minimal implementation, every branch covered
    }
    

    One rule, zero retrofitted tests.


    Rule 2: Conventional Commits — Never Commit Without a Type

    Every commit message must follow Conventional Commits:
    <type>(<scope>): <description>. Types: feat, fix, refactor, test,
    docs, chore, perf. Keep the subject under 72 characters. Add a body
    for any non-trivial change.
    

    Before: My git log was a graveyard of update, fix bug, and wip.

    * wip
    * fix
    * update stuff
    * more changes
    

    After: Every commit tells me what it does without opening the diff.

    * feat(auth): add refresh token rotation
    * fix(billing): prevent double charge on retry
    * refactor(api): extract error middleware
    * test(auth): cover expired-token edge case
    

    Semantic-release picks up the types, my changelog writes itself, and I can actually git bisect because every commit means something.


    Rule 3: No console.log in Committed Code — Use a Logger

    Never use console.log, console.error, or console.warn in committed
    code. Import the project logger (e.g., `import { logger } from
    '@/lib/logger'`) and use logger.info / logger.error with a structured
    context object. Debug prints must be removed before the commit.
    

    Before: Prod logs were a graffiti wall of console.log('here'), console.log('hmm'), and the occasional unredacted API key.

    console.log('user', user); // leaks PII
    console.log('token', token); // leaks secrets
    console.log('here'); // leaks my sanity
    

    After: Structured logs, every time, with levels that actually mean something.

    logger.info('user.login', { userId: user.id, method: 'oauth' });
    logger.error('payment.failed', { orderId, error: err.message });
    

    Datadog queries work. PagerDuty alerts work. I stopped getting paged at 3 AM by logs I couldn't search.


    Rule 4: Typed Errors at Every Async Boundary

    Every async function that can fail must have explicit try/catch and
    return a discriminated union: { ok: true, data: T } | { ok: false,
    error: AppError }. Never let unhandled rejections propagate. AppError
    must have a `code` field for programmatic handling.
    

    Before: Errors vanished into .catch(console.error) and reappeared as user-facing white screens.

    async function charge(amount: number) {
      const res = await stripe.charges.create({ amount });
      return res; // what if stripe throws? who knows
    }
    

    After: Every call site is forced to handle both branches.

    async function charge(amount: number): Promise<Result<Charge>> {
      try {
        const res = await stripe.charges.create({ amount });
        return { ok: true, data: res };
      } catch (err) {
        return { ok: false, error: { code: 'STRIPE_FAILED', cause: err } };
      }
    }
    
    const result = await charge(1999);
    if (!result.ok) return handleChargeError(result.error);
    // TypeScript now knows result.data exists
    

    The compiler caught three unhandled error paths the day I added this rule.


    Rule 5: Config via a Typed Module — Never Touch process.env Directly

    Never access process.env directly outside of src/config/env.ts.
    That file must validate all env vars with zod at startup and export
    a typed `env` object. All other code imports `env` and gets
    autocomplete + runtime guarantees.
    

    Before: Every file reached into process.env like it was a shared snack drawer.

    const apiKey = process.env.STRIPE_KEY; // string | undefined, maybe?
    stripe.setApiKey(apiKey!); // the ! is doing a lot of work
    

    After: One source of truth, validated on boot.

    // src/config/env.ts
    import { z } from 'zod';
    export const env = z.object({
      STRIPE_KEY: z.string().min(1),
      DATABASE_URL: z.string().url(),
      NODE_ENV: z.enum(['development', 'test', 'production']),
    }).parse(process.env);
    
    // everywhere else:
    import { env } from '@/config/env';
    stripe.setApiKey(env.STRIPE_KEY); // typed, non-null, validated
    

    The app now refuses to start if an env var is missing. No more "works on my machine" outages.


    Rule 6: One File, One Purpose — 200 Lines Max

    A file must have a single responsibility. Max 200 lines. If a file
    grows past 200 lines, split it by responsibility — not by arbitrary
    chunks. Co-locate related files in a folder rather than stacking
    them into one mega-module.
    

    Before: utils.ts was 900 lines of unrelated functions, and every new utility got dumped into it.

    src/
      utils.ts  ← 900 lines, 47 exports, nobody knows what's in it
    

    After: Cursor refuses to grow files past the limit and proposes a folder split instead.

    src/
      utils/
        date/
          formatDate.ts
          parseDuration.ts
        string/
          slugify.ts
          truncate.ts
        money/
          formatCents.ts
    

    Every file fits on one screen. Reviewers can actually read PRs.


    Rule 7: Validate at the Boundary — Every API Input Through a Schema

    Every HTTP handler must validate its input (body, query, params) with
    a zod schema before any business logic runs. Reject invalid input
    with a 400 and a structured error. Never trust `req.body`.
    

    Before: Business logic was defensive-coded against missing fields, wrong types, and whatever else the internet threw at it.

    app.post('/api/orders', async (req, res) => {
      const { items, userId } = req.body; // any? undefined? an attack?
      if (!items) return res.status(400).send('bad');
      if (!Array.isArray(items)) return res.status(400).send('bad');
      // ...20 more lines of manual validation
    });
    

    After: One schema, one parse call, typed body downstream.

    const CreateOrderBody = z.object({
      userId: z.string().uuid(),
      items: z.array(z.object({
        sku: z.string(),
        quantity: z.number().int().positive(),
      })).min(1),
    });
    
    app.post('/api/orders', async (req, res) => {
      const body = CreateOrderBody.parse(req.body); // throws → 400 middleware
      await createOrder(body); // body is fully typed here
      res.status(201).end();
    });
    

    SQL injection attempts, missing fields, and the intern sending quantity: -1 all die at the door.


    Rule 8: The PR-Ready Checklist — Nothing Ships Without It

    Before declaring any task complete, Cursor must run and report:
    1. Typecheck passes (npm run typecheck)
    2. Tests pass (npm test)
    3. Lint passes (npm run lint)
    4. No new `any` types introduced
    5. No `console.log` in committed code
    If any step fails, fix it before claiming the task is done.
    

    Before: "Done" meant "the code compiles on my branch," and CI caught it three hours later.

    me: "done!"
    CI: ❌ 4 type errors, 12 lint warnings, 1 failing test
    me: (fixing for the next hour)
    

    After: Cursor self-checks before handing the PR back.

    ✓ typecheck (0 errors)
    ✓ tests (142 passed)
    ✓ lint (0 warnings)
    ✓ no new `any` types
    ✓ no console.log
    Ready for review.
    

    My CI pipeline now passes on the first try about 90% of the time. The other 10% is usually a flaky integration test, not a mistake I made.


    What Actually Changed

    Four weeks after these rules went live, I measured.

    • Speed. Feature work that used to take a day now takes a morning. Not because Cursor is faster — it was always fast — but because I stopped rewriting its first draft.
    • Consistency. Every file in the repo looks like it was written by the same person. Because effectively, it was.
    • Bugs caught. The typed-error rule alone caught 3 unhandled promise rejections in the first week. The env-validation rule caught 2 missing config values before they hit staging. The test-first rule caught a dozen off-by-one errors I would have merged otherwise.
    • Review fatigue. My PR review comments dropped by maybe 70%. The nits — missing types, stray logs, inconsistent commits — just don't appear anymore.

    The meta-lesson: prompting is a loop. Rules are a state machine. Every rule you write is one conversation you never have to repeat.


    Copy-Paste Starter: All 8 Rules

    Drop this into .cursorrules or .cursor/rules/workflow.mdc:

    # Workflow Automation Rules
    
    ## Testing
    - Write a failing test before any implementation
    - Tests live next to source as *.test.ts
    
    ## Commits
    - Conventional Commits format: <type>(<scope>): <description>
    - Subject under 72 chars; body for non-trivial changes
    
    ## Logging
    - Never use console.log/error/warn in committed code
    - Use the project logger with structured context
    
    ## Errors
    - Every async function returns { ok: true, data } | { ok: false, error }
    - AppError must have a `code` field
    - No unhandled promise rejections
    
    ## Config
    - Never access process.env outside src/config/env.ts
    - Validate all env vars with zod at startup
    
    ## File Structure
    - One responsibility per file
    - Max 200 lines; split by responsibility when exceeded
    
    ## Input Validation
    - Every HTTP handler validates input with zod before logic runs
    - Never trust req.body/query/params
    
    ## PR-Ready
    - Before declaring done: typecheck + tests + lint must pass
    - No new `any` types; no console.log
    

    Want the Full Set?

    These 8 rules are the workflow layer. The rest of my stack — React, TypeScript, Next.js, Prisma, testing patterns — runs on 50+ more rules I've built out over the last year.

    I packaged them into the Cursor Rules Pack v2 — organized by framework, priority-tagged, and production-tested. If you've ever felt like you're re-prompting Cursor for the same fixes every day, this is the file that stops it.

    Stop prompting. Start ruling.

    Tags

    cursorrulesaiproductivitycursor

    Comments

    More Blog

    View all
    Cursor Automations in 2026: wire event-triggered coding agents to Slack, CI, and timerscursor

    Cursor Automations in 2026: wire event-triggered coding agents to Slack, CI, and timers

    Cursor Automations in 2026: wire event-triggered coding agents to Slack, CI, and...

    M
    Manu Shukla
    Index Everything, or Read Everything? The Dilemma of Feeding Specs to AI in Multi-Repo Developmentai

    Index Everything, or Read Everything? The Dilemma of Feeding Specs to AI in Multi-Repo Development

    The specs exist. The AI just can't see them. I've always been the type who builds hobby...

    S
    Shunya Shida
    Connect Claude Code, Cursor and Codex to Amazon Bedrock's new console (2026)amazonbedrock

    Connect Claude Code, Cursor and Codex to Amazon Bedrock's new console (2026)

    Connect Claude Code, Cursor and Codex to Amazon Bedrock's new console (2026) Summary. On 5...

    M
    Manu Shukla
    Spotting AI UI is too easyai

    Spotting AI UI is too easy

    There is a weird uncanny valley with LLM-generated UI right now. The code functions perfectly, but if...

    H
    Harish .s
    Seven ranking frameworks, one search page, zero translation tablesai

    Seven ranking frameworks, one search page, zero translation tables

    I went down a rabbit hole this morning reading the late-2025 Juejin AI roundups side by side, and the...

    N
    ninghonggang
    Zendesk MCP: Let Claude Handle Your Support Ticketsmcp

    Zendesk MCP: Let Claude Handle Your Support Tickets

    Install guide and config at curatedmcp.com Zendesk MCP: Let Claude Handle Your Support...

    C
    curatedmcp

    Stay up to date

    Get the latest Cursor prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for Cursor and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Neura Market

    Custom AI Systems & Services

    Our team of experienced AI builders will help build custom AI systems, workflows, and solutions for your business.

    Request custom work

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this Cursor resource

    • Automated Workflow Backup System with Google Drive, Gmail, and Discord Alertsn8n · $14.99 · Related topic
    • Automated Workflow Backups with Google Drive and Slack Notificationsn8n · $9.99 · Related topic
    • Automated Execution Cleanup System with n8n API and Custom Retention Rulesn8n · $9.99 · Related topic
    • Automated Lead Generation & Contact Enrichment with Hunter.io and Perplexity AIn8n · $24.99 · Related topic
    Browse all workflows