faw

software engineer

Create MF2 App: Ship in Days, Not Months

I spent 3 months building authentication. Again. For the fourth startup in a row.

Same login flow. Same password reset emails. Same session management. By the time I shipped my first feature, two competitors had already launched.

That's when I decided to build MF2 Stack. Move F*cking Fast.

The 3-Month Trap

Here's how every project used to start:

Week 1: Set up Next.js, configure TypeScript, add ESLint
Week 2: Research auth solutions, implement authentication
Week 3: Database schema, ORM setup, migrations
Week 4: Payment integration (why is Stripe so complex?)
Week 5-8: Build the actual product
Week 9-12: Fix all the integration issues

Three months. Every time. For infrastructure that users never see.

I tracked my last startup's setup phase:

  • 47 hours configuring build tools
  • 31 hours implementing auth
  • 22 hours setting up payments
  • 18 hours debugging CORS issues

That's 118 hours before writing a single feature. At $150/hour (consultant rate), that's $17,700 of pure overhead.

The Decision Paralysis Problem

Modern web development offers too many choices. Every decision branches into more decisions:

Choose a framework → Choose a router → Choose a data fetching strategy → Choose a state management solution → Choose a styling approach → Choose a component library...

I counted 73 significant technical decisions before writing code. Each decision required research, comparison, and often reversal when incompatibilities emerged.

The worst part? Most of these decisions don't matter for your MVP. Your users don't care if you use Prisma or Drizzle. They care if your product solves their problem.

Why AI Makes It Worse

When Claude and Copilot arrived, I thought they'd solve this. Finally, AI could handle the boilerplate.

But here's what actually happened: AI amplifies your architecture. If you start with a complex, inconsistent codebase, AI helps you create more complex, inconsistent code. Fast.

I watched Claude generate 500 lines of authentication logic because that's what it learned from my overcomplicated patterns. The same auth flow could have been 5 lines with the right abstractions.

AI doesn't fix bad stacks. It accelerates them.

What MF2 Actually Is

MF2 Stack is an opinionated, production-ready starting point for web applications. It's not a boilerplate or template - it's a philosophy encoded in code.

The philosophy is simple: eliminate decisions that don't differentiate your product.

npm create mf2-app@latest my-startup
cd my-startup
npm run dev

In under 60 seconds, you have:

  • User authentication with Clerk
  • Subscription payments with Polar
  • Real-time database with Convex
  • Email sending with Resend
  • Analytics with PostHog
  • Beautiful UI with shadcn/ui

All configured. All integrated. All production-ready.

The Stack That Ships

Here's what's included and why:

Frontend: Next.js 15 + React 19

The industry standard. No explanation needed. App Router for simplicity, Server Components for performance.

Database: Convex

Real-time by default. No API routes. No REST endpoints. Just functions that sync data instantly. After using it, traditional request-response patterns feel archaic.

Auth: Clerk

Handles everything: passwords, OAuth, MFA, user management. One integration instead of twenty.

Payments: Polar

Stripe is powerful but overkill for most startups. Polar handles subscriptions with 10% of the complexity.

Styling: Tailwind v4 + shadcn/ui

Every component you need, pre-built and customizable. No design decisions. Just ship.

Real Usage Patterns

Here's how development actually looks with MF2:

Day 1: Clone and Customize

npm create mf2-app@latest founder-rank
cd founder-rank
npm run dev

Change the logo. Update the colors. You're branded.

Day 2: Add Your First Feature

// convex/rankings.ts
export const create = mutation({
  args: {
    startup: v.string(),
    score: v.number(),
  },
  handler: async (ctx, args) => {
    const userId = await auth.getUserId(ctx)
    return await ctx.db.insert('rankings', {
      ...args,
      userId,
      createdAt: Date.now(),
    })
  },
})

That's it. Real-time synced. Authenticated. Type-safe.

Day 3: Add Payments

// app/upgrade/page.tsx
import { PricingTable } from "@/components/pricing"

export default function UpgradePage() {
  return <PricingTable />
}

Subscriptions work. Webhooks configured. Customer portal ready.

Day 4: Ship to Production

npm run deploy

Deployed to Vercel. Database on Convex. Auth on Clerk. Payments on Polar. Done.

Where MF2 Shines

Solo founders and small teams - When velocity matters more than customization. When shipping beats perfection.

MVPs and experiments - Test ideas in days, not months. Fail fast or scale fast.

AI-assisted development - Consistent patterns make AI incredibly effective. Claude understands MF2 instantly.

Hackathons - Win by shipping features while others configure webpack.

The Honest Limitations

MF2 isn't for everyone.

Large teams might need more flexibility. The opinionated choices that enable speed can constrain architecture at scale.

Complex requirements might not fit. If you need microservices, custom auth flows, or specific compliance requirements, you'll fight the stack.

Learning curve exists. Convex thinks differently than traditional backends. The real-time mental model takes adjustment.

Vendor lock-in is real. You're committing to Clerk, Convex, and Polar. Migrations are possible but non-trivial.

The Results Speak

Since launching MF2:

  • 147 startups shipped their MVP in under a week
  • Average time to first customer: 4.2 days
  • Average setup time: 47 minutes (vs 3 months)

My favorite success story: Sarah built and launched a SaaS for photographers in 4 days. Previous attempt with a "flexible" stack took 3 months and never shipped.

Making the Choice

Ask yourself:

  • How many hours have you spent on authentication?
  • How many times have you built the same CRUD APIs?
  • How many competitors shipped while you configured?

If the answers hurt, you might need MF2.

Start Now

The best time to simplify your stack was before you started. The second best time is now.

npm create mf2-app@latest

Set a timer. See how long until you have a working app with auth, payments, and real-time data.

Then ask yourself what you could build if every project started here.


Move F*cking Fast. Start at mf2.dev

July 28th, 2025