What I Learned Building a 9-Tool AI SaaS From Scratch — Real Numbers and Honest Mistakes

I built a 9-tool AI SaaS with 280 TypeScript files, 58,600 lines of code, 6 affiliate network integrations, and encrypted credential storage — solo, in a few months. These are my building AI SaaS from scratch lessons learned 2026: every major decision that saved time, every mistake that cost me days, and the real numbers behind shipping a production platform — not a demo app.

What I Learned Building a 9-Tool AI SaaS From Scratch
A solo developer retrospective: 9 AI tools, 6 networks, 280 TypeScript files — what worked, what cost weeks, and what it runs for per month

What I Built: 9 AI Tools, 6 Networks, 280 Files

I built an affiliate marketing SaaS solo in a few months — 9 AI-powered content tools, 6 network integrations, AES-256-GCM encrypted credential storage, a Canva-style Fabric.js ad editor, and a real-time sales dashboard fed by hourly Vercel Cron syncs.

See also: lessons from building two AI SaaS products solo and production AI SaaS tech stack for 2026.

Metric Number
AI-powered tools 9
Affiliate network integrations 6 (ClickBank, Digistore24, BuyGoods, MaxWeb, JVZoo, Hotmart)
Content platforms covered 3 (Facebook, Instagram, YouTube)
TypeScript / TSX files ~280
Lines of source code ~58,600 in src/
Prisma database models 6 (User, AffiliateNetworkAccount, AffiliateSale, Link, Click, Conversion)
Months to build (solo) ~3–4
Solo developer 1

This is not a weekend hackathon project or a tutorial clone. At 58,600 lines, type errors caught at build time matter. At 9 AI tools sharing one generation pipeline, consistency matters. At 6 affiliate APIs with different auth schemes, adapter isolation matters. The scale forced architectural discipline I would have skipped on a smaller app.

Why I built it

Affiliate marketers juggle fragmented tools — one app for ad copy, another for link tracking, a spreadsheet for sales across ClickBank and Digistore24, Canva for creatives, and nothing that talks to anything else. The platform unifies AI content generation for Facebook, Instagram, and YouTube, smart link tracking with UTM analytics, encrypted storage for network API keys, and a dashboard that aggregates sales from all six networks into one Recharts view. One login, one billing relationship, one codebase.

The tech stack in one sentence

Next.js 16 App Router, React 19, TypeScript, PostgreSQL with Prisma 7, NextAuth v5 credentials auth, Google Gemini 2.5 Flash for text and image generation, Tailwind CSS 4 with shadcn/ui, Fabric.js 5 for the canvas editor, Zod 4 for validation everywhere, and Vercel for hosting plus cron — each choice earned its place for a specific problem, not because it was trending on Twitter.

The Stack: Every Decision and the Reason Behind It

Next.js 16 + PostgreSQL + Google Gemini + Vercel is the stack I'd choose again — each component solved a concrete problem on this project, not a hypothetical one from a framework comparison blog post.

Technology Why chosen Almost used instead
Next.js 16 Server Actions eliminate AI tool API route boilerplate Remix
PostgreSQL + Prisma Relational data fits the domain; generated types and migrations MongoDB
Google Gemini 2.5 Flash Cheaper than GPT-4o at comparable structured-output quality OpenAI GPT-4o
NextAuth v5 Native Next.js 16 support; credentials-only for invite-only product Clerk
Tailwind 4 + shadcn/ui Fastest path to a professional dashboard UI Custom CSS
Fabric.js 5 Full object model for canvas editor — groups, text editing, serialisation Konva.js
Zod 4 Validates env, AI outputs, Server Actions, forms — one library everywhere Yup

TypeScript was non-negotiable at 280 files — I wanted type errors at build time, not in a user's browser at 2 AM. React 19 with the Compiler enabled in config reduced manual memoization across wizard UIs. AES-256-GCM encrypts affiliate network API keys at rest; decryption happens server-side only, never in the client bundle. Recharts composes cleanly inside React Server Component boundaries for the sales dashboard.

src/
├── app/                     # Next.js App Router — routes only
│   ├── (auth)/login/
│   ├── (dashboard)/         # Protected shell layout
│   ├── api/                 # REST + cron + auth handlers
│   └── go/[alias]/          # Public link redirect (no auth)
├── features/                # All domain logic lives here
│   ├── tools/               # AI tool schemas, services, actions, pages
│   ├── sales-tracking/      # Adapters, sync, dashboard, encryption
│   ├── link-tracker/        # Link creation, clicks, conversions
│   ├── image-editor/        # Fabric.js canvas editor
│   └── apps/                # Mini-app registry
├── components/              # Shared UI components (dashboard shell, auth)
├── lib/                     # auth, db, ai/gemini, rate-limit, validation
└── generated/prisma/        # Generated Prisma client (never edit manually)
Tip

Feature-based folders beat component-based folders at scale. With 280 files, finding sales-tracking logic in features/sales-tracking/ takes one second. Finding it in a flat components/ folder — where UI, hooks, and business logic intermingle — takes five minutes and breeds duplicate utilities. Domain logic belongs in features/; shared UI belongs in components/; infrastructure belongs in lib/. That separation held for the entire build.

The 4 Decisions That Saved Me Weeks

The 6-step tool pattern, feature-based structure, Zod at every layer, and Server Actions for AI calls collectively saved more engineering time than any individual library choice on the project.

The 6-step tool pattern

Every AI tool follows the same pipeline: schema → types → service → server action → optional API route → UI page. I documented it in src/features/tools/README.md after tool #1 took two days to establish the shape. Tool #2 took two days following the template. Tools #3 through #9 averaged four to eight hours each — mechanical work, not architectural exploration. Once the pattern locked, adding a tenth tool is a checklist, not a design session.

# Every AI tool follows this exact structure — no exceptions
features/tools/
├── schemas/
│   └── facebook-ad-copy.schema.ts   # Step 1: Zod input + output schemas
├── types/
│   └── facebook-ad-copy.types.ts    # Step 2: TypeScript types (z.infer)
├── services/
│   └── facebook-ad-copy.service.ts  # Step 3: Pure AI logic — no auth, no rate limit
├── actions/
│   └── facebook-ad-copy.actions.ts  # Step 4: auth → rate limit → validate → service call
│                                    # Step 5: Optional /api/ route if public endpoint needed
└── pages/facebook-ad-copy/
    └── page.tsx                     # Step 6: React wizard or form UI

Zod at every layer

Zod validates environment variables at build via @t3-oss/env-nextjs, every Gemini JSON response against an output schema, every Server Action input, and every form submission. A Gemini response that doesn't match the expected schema fails loudly at parse time — not silently in a downstream component three renders later. This caught at least a dozen AI output format issues before they reached production users. Structured generation without schema validation is gambling; Zod makes the bet calculable.

Server Actions over API routes for AI tools

Instead of creating /api/[tool]/route.ts for every AI tool — nine route files minimum, nine fetch() calls in the UI, nine request/response serialisation layers — Server Actions let the wizard call AI logic directly with full TypeScript types end to end. The entire 9-tool surface is Server Actions plus one shared generateTextWithSchema utility in lib/ai/. No fetch(), no manual error parsing, no duplicate auth middleware per route.

Feature-based folder structure

src/features/ contains tools/, sales-tracking/, link-tracker/, image-editor/, and apps/. After 280 files, I never asked "where does this go?" — the domain tells you the folder. Shared components and utilities live elsewhere. This prevented the components/ dumping ground that kills velocity on large React codebases. The sales-tracking adapters, sync orchestrator, and dashboard charts all live together; the link tracker never imports from sales-tracking except through explicit shared types.

Important

The 6-step pattern is only valuable if it's consistent. Tool #1 that breaks the pattern creates exceptions in tool #2 that become technical debt in tool #7. I learned this the hard way when tool #2 skipped the shared service layer and called Gemini directly from the action — retrofitting tool #2 to match the pattern cost a day. The value is in zero exceptions, not in having a README that nobody follows.

The 4 Mistakes That Cost Me Days — With Exact Numbers

Four architectural decisions I made early cost a combined three-plus weeks of refactoring. All four were avoidable with one principle: define the interface before writing the implementation.

Mistake What I built Should have built Cost
Rate limiting In-memory Map + sliding window Redis/Upstash Future refactor at scale
Tool registry Built 2 tools, designed registry after Registry interface before tool #1 1 week
Adapter interface ClickBank first, interface after NetworkAdapter interface first 3 days
SyncLog model lastSyncedAt on account model Separate SyncLog table 2 days migration
Canvas component 400-line monolith useCanvas hook from 50 lines 1–2 days refactor

The common thread

Every mistake shares the same root cause: I optimized for speed on day one instead of correctness on day thirty. The in-memory rate limiter took thirty minutes to build and works perfectly on a single Vercel instance — until Vercel spins up a second instance and each counter runs independently, effectively doubling the allowed request rate per user. The tool registry retrofit happened because I built two tools with slightly different sidebar metadata shapes before realizing a config object should drive routing, status badges, and navigation. ClickBank shipped as a standalone adapter; Digistore24 arrived with different method signatures; the orchestrator had to handle both until I retrofitted a shared NetworkAdapter interface — three days for fifteen lines of TypeScript I should have written first.

The one principle that would have prevented all 4

Write the contract before the implementation. NetworkAdapter, ToolConfig, SyncLog schema, useCanvas hook — each existed informally in working code before it existed as an explicit interface or extracted module. That informality cost one week on the registry, three days on adapters, two days on SyncLog migration, and one to two days on the canvas refactor. The SyncLog mistake is documented in detail in my Vercel Cron background jobs post on hassanr.com — partial sync failures with lastSyncedAt on the account model force an impossible choice after mixed success.

Every one of my expensive mistakes had the same root cause: I wrote the implementation before I wrote the interface. An interface is 15 lines of TypeScript. A retrofit is measured in days.

What It Actually Costs to Run an AI SaaS in 2026

A production AI SaaS on Vercel with Google Gemini, PostgreSQL, and email delivery costs $20–40/month at early stage and $60–100/month at moderate scale — the AI API is the variable line item; everything else is fixed or free-tier.

Service Early stage Moderate scale Notes
Vercel Pro $20/mo $20/mo Required for cron jobs beyond Hobby limits
PostgreSQL (Neon) $0 $19/mo Free tier covers early stage (0.5 GB, 100 compute hours)
Google Gemini API $20–40/mo $40–80/mo Variable — 100–500 tool calls/day early; 500–1000 at moderate scale
Email delivery (SendGrid) $0 $0 Free tier: 100 emails/day
Image/blob storage $0 $5–15/mo Free tier initially; scales with generated creatives
Total $20–40/mo $60–100/mo AI API is the only variable cost

Build cost vs running cost

These are separate numbers people conflate constantly. Build cost for this project was months of solo developer time — no contractor invoices, no agency fees, just focused hours across architecture, nine AI tools, six network adapters, a canvas editor, link tracker, admin panel, and polish. Running cost is the table above. You can operate a production AI SaaS for less than a gym membership once it's built. The barrier is not AWS bills — it's the three to four months of architecture and implementation before the first paying user.

Gemini vs OpenAI at moderate usage

I chose Google Gemini 2.5 Flash for text and Gemini 2.5 Flash Image over OpenAI GPT-4o after comparing structured output quality on ad copy, hook generation, and image prompts. At moderate usage — a few hundred users making 500 to 1000 AI calls per day combined — Gemini runs $40–80/month where GPT-4o would run significantly higher for the same call volume. Output quality for structured JSON generation with Zod validation was comparable; cost was not. For image generation specifically, Gemini 2.5 Flash Image priced better per generation than DALL-E at the volumes I tested during development.

Warning

Don't let "AI API costs" scare you off building. At moderate usage — a few hundred users, 500–1000 AI calls/day — Google Gemini 2.5 Flash text plus image combined runs $40–80/month. Vercel Pro is $20/month fixed. The real cost barrier is developer time measured in months, not API bills measured in tens of dollars. I see founders delay launches over projected $200/month API spend while burning $15,000/month in opportunity cost waiting.

What I'd Tell Myself Before Starting

Five building AI SaaS from scratch lessons learned 2026 would have saved three-plus weeks of refactoring if I'd followed them from commit #1 — each maps directly to a real mistake or decision on this project.

  1. Write every interface before its first implementation. NetworkAdapter, ToolConfig, HistoryManager — all existed in working code before they existed as explicit TypeScript interfaces. That informality cost weeks collectively across adapters, registry, and canvas extraction.
  2. Establish the 6-step tool pattern before building tool #1. Tool #1 should have been the template commit, not the prototype that tool #2 had to reconcile with. The pattern documented in README.md should have been commit #1, not the result of tool #2's inconsistencies.
  3. A SyncLog model is basic observability, not overengineering. Recording every sync attempt with success, failure, recordsSynced, and timestamps per (userId, network) is table stakes for any background job. Storing lastSyncedAt on the account model broke incremental sync logic after partial failures — two days to migrate.
  4. In-memory rate limiting is a 2-hour build vs a future N-day refactor. Redis/Upstash setup takes two to three hours upfront. The in-memory Map took thirty minutes and works until your second Vercel instance spins up. Pay the two hours now.
  5. Extract hooks before components hit 100 lines. The Fabric.js canvas editor grew to 400+ lines with setup, event listeners, undo history, keyboard shortcuts, and export logic in one component. Extracting useCanvas should have happened at line 50, not line 400.

The one meta-lesson

Design for the third iteration, not the first. The first version of anything can be ugly — but the contracts between modules must be correct from day one. Interfaces, folder structure, sync observability, and rate limit storage are not premature optimization; they are the scaffolding that makes iterations two and three cheap. I write about the technical implementations of several decisions from this project across hassanr.com — the adapter pattern post, the Vercel Cron sync post, and the NextAuth v5 RBAC post each cover one subsystem in depth. This post is the map; those are the territory.

If you're about to start a similar platform — 9 tools, multiple API integrations, solo or small team — Hassan Raza is available for architecture reviews and build partnerships. I'd rather help you define NetworkAdapter on day one than retrofit ClickBank on day forty-five.

Frequently Asked Questions

It depends on scope, but a 9-tool AI SaaS with six integrations took Hassan Raza a few months solo. The first month covered architecture, auth, core infrastructure, and the first two AI tools. Once the six-step tool pattern locked in, tools three through nine averaged four to eight hours each—roughly as long as the first two combined. An experienced full-stack developer could ship a two- or three-tool MVP in four to six weeks if patterns are defined before feature one. Timeline killers: integration complexity, retrofitting registries, and skipping interfaces upfront. Design the pattern at commit one, not after tool two.

The biggest mistakes are writing implementations before interfaces and choosing simple infrastructure that fails under load. Hassan Raza lost one week retrofitting a tool registry, three days on a NetworkAdapter interface, and two days migrating to SyncLog—all because ClickBank, tool configs, and sync timestamps were built before their contracts existed. In-memory rate limiting with a JavaScript Map works on one Vercel instance and silently multiplies limits across instances. A four-hundred-line Fabric.js canvas monolith needed a useCanvas hook refactor. The common thread: optimize for the first iteration, not the third. An interface is fifteen lines; a retrofit is measured in days.

Running costs $20–40/month early and $60–100/month at moderate scale; build cost is developer time. Hassan Raza's affiliate marketing SaaS runs Vercel Pro at $20/month, Neon PostgreSQL at $0 early then $19/month, and Google Gemini 2.5 Flash at $20–80/month depending on volume—SendGrid free tier covers email. The AI API is the only variable line item; hosting, database, and email stay fixed or free-tier initially. Gemini 2.5 Flash text plus image generation costs significantly less than GPT-4o at comparable structured-output quality. The real barrier is months of solo development, not monthly API bills.