AI News Hub Logo

AI News Hub

How I went from getting tired of explaining the same things to AI, to developing a cutting edge solution, to accidentally creating a brand

DEV Community
Diogo Abreu

There’s a moment every developer hits when “AI-assisted coding” starts feeling less like acceleration and more like friction. For me, that moment came somewhere between deleting yet another useEffect-based data fetch and watching Cursor confidently generate a tailwind.config.js file in a project that absolutely did not need one. That loop kept repeating: Wrong patterns Outdated APIs Defaults that no longer reflect how modern apps are built And the more cutting-edge the stack became—Next.js 16, React 19, Tailwind v4—the worse it got. So I stopped fixing the symptoms and built my own rules pack instead. That place became Saastenance—and this post is both a technical deep dive and the story of how a small dev tool quietly turned into a full digital product and part of a brand. Tools like Cursor and Claude Code don’t “understand” your stack—they pattern match based on training data. And most of that data is already outdated. So unless you explicitly constrain them, they will: Reintroduce deprecated patterns Ignore new framework primitives Drift away from your architecture over time What I needed wasn’t better prompts. I needed persistent, enforceable rules. The AI Rules Pack is a structured set of rules (in .mdc format) that: Defines how your AI should think Locks in modern best practices Prevents regression into outdated patterns It works with Cursor, Claude Code, and OpenAI Codex. It installs via a CLI where you choose your stack preferences. But the interesting part—the reason it exists—comes from how Next.js 16 broke a lot of assumptions. Let’s walk through that. useEffect Is No Longer the Default ❌ Before (what AI still generates) 'use client' import { useEffect, useState } from 'react' export default function Page() { const [data, setData] = useState(null) useEffect(() => { fetch('/api/data') .then(res => res.json()) .then(setData) }, []) return {JSON.stringify(data)} } export default async function Page() { const data = await fetch('https://api.example.com/data', { cache: 'no-store' }).then(res => res.json()) return {JSON.stringify(data)} } Server Components are the default Fetching happens on the server No client waterfall, no loading flicker Yet AI still defaults to client-side fetching unless told otherwise. 'use client' async function handleSubmit(formData) { await fetch('/api/form', { method: 'POST', body: JSON.stringify(formData) }) } export async function submit(formData: FormData) { 'use server' // direct DB call or mutation } Submit No API route needed No client fetch boilerplate Stronger co-location of logic AI often mixes both patterns—which creates unnecessary complexity. middleware.ts Is No Longer Your Auth Layer This one shows up constantly. // middleware.ts import { NextResponse } from 'next/server' export function middleware(req) { // auth logic } Use route handlers, server actions, or framework-native auth solutions Middleware is now edge-specific and limited AI overuses middleware because it used to be a catch-all solution. In modern apps, it's usually the wrong tool. tailwind.config.js ❌ Before module.exports = { theme: { extend: {} } } Zero-config by default CSS-first configuration @theme { --color-primary: blue; } AI still scaffolds Tailwind like it's 2021. That leads to unnecessary files and wrong mental models. useFormState Is Not the Move ❌ Before const [state, formAction] = useFormState(action, initialState) Use native Or lightweight client validation where needed React 19 + Server Actions changed the ergonomics completely. Yet AI keeps reaching for older abstractions. AI still: Overuses client components Misplaces logic in layouts Avoids async components Layouts are server-first Components are async by default Client components are opt-in None of these issues are “bugs.” They’re default mismatches. AI is trained on: Older Next.js versions Mixed patterns Transitional APIs So unless you enforce constraints, it will: Blend paradigms Reintroduce deprecated logic Slow your team down That’s what the AI Rules Pack does. Instead of correcting AI every time, you: Define rules once Apply them automatically Keep outputs consistent across projects - NEVER use useEffect for data fetching - ALWAYS prefer server components - USE server actions for mutations - DO NOT create tailwind.config.js Now scale that across: Architecture decisions Naming conventions Library choices Auth/data patterns That’s where this becomes powerful. nextjs-core.mdc (Free) Here’s the free core rules file for Next.js: // nextjs-core.mdc --- description: Next.js 16 Cache Components — "use cache" directive, cacheLife profiles, cacheTag, updateTag, refresh, and the new caching mental model globs: "**/*.ts,**/*.tsx" alwaysApply: true --- ## Next.js 16 — Cache Components ### The New Mental Model In Next.js 16 with `cacheComponents: true`, **everything is dynamic by default**. Caching is entirely opt-in. This is the opposite of Next.js 13-15 where `fetch()` was cached by default and you had to opt out. Old model (Next.js 13-15): - `fetch()` → cached by default - Add `cache: 'no-store'` to opt out - `export const revalidate = 60` for ISR - Confusing implicit behaviour New model (Next.js 16 Cache Components): - Everything dynamic by default - Add `"use cache"` to opt into caching - `cacheLife()` sets the duration - `cacheTag()` enables on-demand invalidation - Explicit, predictable, composable ### Setup (add ts code block tags here) // next.config.ts import type { NextConfig } from "next"; const nextConfig: NextConfig = { cacheComponents: true, // Optional: define custom profiles cacheLife: { products: { stale: 300, revalidate: 900, expire: 86400 }, dashboard: { stale: 60, revalidate: 300, expire: 3600 }, blog: { stale: 3600, revalidate: 900, expire: 86400 }, realtime: { stale: 0, revalidate: 10, expire: 60 }, }, }; export default nextConfig; (close code blocks) ### The `"use cache"` Directive Add at the top of any async function, component, page, or layout to make it cacheable. (add ts code block tags here) import { cacheLife, cacheTag } from "next/cache" // Cache a data access function export async function getProducts(category: string) { "use cache" cacheLife("hours") cacheTag("products", `category-${category}`) // arguments automatically become part of the cache key // getProducts("shoes") and getProducts("hats") are separate cache entries return db.query.products.findMany({ where: { category } }) } // Cache a Server Component async function FeaturedProducts() { "use cache" cacheLife("hours") cacheTag("products") const products = await db.query.products.findMany({ where: { featured: true } }) return ( {products.map(p => )} ) } // Cache an entire page export default async function BlogPage() { "use cache" cacheLife("days") const posts = await getPosts() return } // Cache a layout export default async function MarketingLayout({ children }: { children: React.ReactNode }) { "use cache" cacheLife("max") const nav = await getNavLinks() return ( {children} ) } (close code blocks) This alone eliminates a huge percentage of bad AI output. Originally, this wasn’t meant to be a product. It was just a personal fix. But then: I made it reusable Added a CLI installer Wrote documentation Structured it for different stacks And at some point, I realized: How am I going to centralize this product and other side projects so people know what they're getting? That’s when Saastenance was born. Not just for this pack—but as a storefront for: Developer tools AI workflows Opinionated systems that reflect how things are actually built today The AI Rules Pack includes: Full rule sets for modern frontend SaaS Cursor + Claude Code + OpenAI Codex compatibility CLI installer (one command setup) Stack customization Git commit conventions for automatic commit message suggestions Complementary Cursor Memories guide Documentation + usage guide It’s designed to answer one question: “How do I make AI code like a senior developer on my team?” To celebrate the launch, I’m offering: 30% off with code: SAASTELAUNCH30 (valid through May) AI isn’t replacing developers. But developers who systemize AI will replace those who don’t. You can keep correcting outputs… Or you can define the rules once—and never fight the same battle again. 👉 https://saastenance.com/products/ai-rules-pack-frontend-development If you're building with modern frontend tools, this will save you hours—and a lot of frustration. And if nothing else, hopefully this gave you a clearer picture of how Next.js 16 is reshaping the way we write frontend code—and why your AI might still be living in the past.