Skip to main content

Wasp Review 2026: Full-Stack Web Framework with Built-In Auth

·StarterPick Team
waspframeworkreactnode-jsfull-stacksaas2026

TL;DR

Wasp is a full-stack language built on React + Node.js that eliminates most backend boilerplate — and it works. You define your app in a .wasp config file, and Wasp generates auth, routing, API endpoints, database, email, and background jobs. The result is genuinely faster development: auth in 5 minutes, email in 5 minutes, background jobs in 10 minutes. The cost: you're learning a DSL, and debugging generated code takes getting used to. For indie hackers and small teams willing to bet on Wasp, it's legitimately productive.

Key Takeaways

  • Type: Open source full-stack framework (React + Node.js + Prisma)
  • Key DX: Declare features in .wasp, Wasp generates the boilerplate
  • Built-in: Auth (email, Google, GitHub), email sending, background jobs, RPC (tRPC-like)
  • Database: Prisma + PostgreSQL
  • Best for: indie hackers, solo developers, small teams wanting fast iteration
  • GitHub: 14K+ stars, actively maintained

How Wasp Works

// main.wasp — the central config file
app MySaaS {
  wasp: { version: "^0.14.0" },
  title: "My SaaS",
  
  auth: {
    userEntity: User,
    methods: {
      email: {
        fromField: { name: "My SaaS", email: "noreply@mysaas.com" },
        emailVerification: { clientRoute: EmailVerificationRoute },
        passwordReset: { clientRoute: PasswordResetRoute },
      },
      google: {},
      github: {},
    },
    onAuthFailedRedirectTo: "/login",
  },
  
  emailSender: {
    provider: SendGrid,
    defaultFrom: { name: "My SaaS", email: "noreply@mysaas.com" },
  },
}

// Define your data model:
entity User {=psl
  id          Int     @id @default(autoincrement())
  email       String  @unique
  createdAt   DateTime @default(now())
  subscription Subscription?
psl=}

// Define routes:
route DashboardRoute { path: "/dashboard", to: DashboardPage }
page DashboardPage {
  authRequired: true,
  component: import { DashboardPage } from "@client/pages/DashboardPage.tsx",
}

// Define server-side actions (mutations):
action createPost {
  fn: import { createPost } from "@server/actions/posts.js",
  entities: [Post, User]
}

// Define queries:
query getPosts {
  fn: import { getPosts } from "@server/queries/posts.js",
  entities: [Post]
}

What Wasp Generates

From the .wasp config above, Wasp generates:

  • Complete auth UI (login, signup, email verification, password reset)
  • JWT session handling with secure cookies
  • Route protection middleware
  • Type-safe RPC layer (similar to tRPC)
  • Email verification + password reset flows
  • OAuth integration (Google, GitHub)

You don't write any of this — you just configure it.


Wasp Actions and Queries (RPC)

// src/server/actions/posts.ts
import type { CreatePost } from 'wasp/server/operations';
import { HttpError } from 'wasp/server';

type CreatePostArgs = { title: string; content: string };

export const createPost: CreatePost<CreatePostArgs, Post> = async (args, context) => {
  if (!context.user) throw new HttpError(401);
  
  return context.entities.Post.create({
    data: {
      title: args.title,
      content: args.content,
      authorId: context.user.id,
    },
  });
};
// src/client/pages/DashboardPage.tsx — client-side usage
import { useQuery, useAction } from 'wasp/client/operations';
import { getPosts, createPost } from 'wasp/client/operations';

export function DashboardPage() {
  const { data: posts, isLoading } = useQuery(getPosts);  // Auto-typed!
  const createPostFn = useAction(createPost);
  
  return (
    <div>
      {posts?.map(post => <div key={post.id}>{post.title}</div>)}
      <button onClick={() => createPostFn({ title: 'New Post', content: '...' })}>
        Create Post
      </button>
    </div>
  );
}

Background Jobs

// Declare a job in main.wasp:
job weeklyReport {
  executor: PgBoss,
  perform: {
    fn: import { sendWeeklyReport } from "@server/jobs/weeklyReport.js",
  },
  schedule: {
    cron: "0 9 * * MON",  // Every Monday 9am
  },
  entities: [User],
}
// src/server/jobs/weeklyReport.ts
export const sendWeeklyReport = async (_args: unknown, context: JobContext) => {
  const users = await context.entities.User.findMany({
    where: { weeklyReportsEnabled: true },
  });
  
  for (const user of users) {
    await sendReportEmail(user);
  }
};

Wasp vs Next.js + T3

WaspT3 Stack (create-t3-app)
Setup time~5 minutes~15 minutes
Auth included❌ (add NextAuth separately)
Email included
Background jobs
Learning curveMedium (learn .wasp)Medium (learn tRPC)
Framework lock-inHigh (Wasp-specific)Medium (T3 conventions)
EcosystemSmall (Wasp-only)Huge (Next.js ecosystem)
DeploymentFly.io / Railway / VPSVercel (native)

Who Should Use Wasp

Use Wasp if:
  → Indie hacker or solo developer
  → Want to minimize boilerplate
  → Willing to learn Wasp's conventions
  → Self-hosting on VPS/Railway/Fly.io
  → OpenSaaS template appeals to you

Skip Wasp if:
  → Team requires standard Next.js/React
  → Need Vercel-native deployment
  → Enterprise environment with strict tech standards
  → Need the full Node.js ecosystem without constraints

Verdict: Wasp genuinely accelerates development for solo developers and small teams. The .wasp config is the learning curve — once past it, auth/email/jobs take minutes instead of hours. If you're an indie hacker building your first SaaS, Wasp + OpenSaaS is worth serious consideration.


Compare Wasp with other SaaS starters at StarterPick.

Comments