DEV Community

Alex Spinov
Alex Spinov

Posted on

Wasp Has a Free API That Generates a Full-Stack React App From a Config File

Wasp is a Rails-like framework for React + Node.js. Write a .wasp config file and it generates everything — auth, CRUD, jobs, email.

The Wasp File: Your Entire App

app ScrapingDashboard {
  wasp: { version: "^0.14.0" },
  title: "Scraping Dashboard",
  auth: {
    userEntity: User,
    methods: { email: {}, google: {} },
    onAuthFailedRedirectTo: "/login",
  },
  db: { system: PostgreSQL },
  emailSender: { provider: Resend },
}

entity User {=psl
  id       Int       @id @default(autoincrement())
  email    String    @unique
  products Product[]
psl=}

entity Product {=psl
  id        Int      @id @default(autoincrement())
  title     String
  price     Float
  url       String   @unique
  userId    Int
  user      User     @relation(fields: [userId], references: [id])
  createdAt DateTime @default(now())
psl=}

route DashboardRoute { path: "/dashboard", to: DashboardPage }
page DashboardPage {
  authRequired: true,
  component: import { DashboardPage } from "@src/pages/Dashboard",
}

query getProducts {
  fn: import { getProducts } from "@src/queries",
  entities: [Product],
}

action createProduct {
  fn: import { createProduct } from "@src/actions",
  entities: [Product],
}

job dailyScrape {
  executor: PgBoss,
  perform: { fn: import { scrapeAll } from "@src/jobs/scrape" },
  schedule: { cron: "0 9 * * *" },
}
Enter fullscreen mode Exit fullscreen mode

Queries and Actions (Server)

// src/queries.ts
import { GetProducts } from "wasp/server/operations";

export const getProducts: GetProducts<void, Product[]> = async (args, context) => {
  return context.entities.Product.findMany({
    where: { userId: context.user.id },
    orderBy: { createdAt: "desc" },
  });
};

// src/actions.ts
import { CreateProduct } from "wasp/server/operations";

export const createProduct: CreateProduct<{ title: string; price: number; url: string }, Product> = async (
  { title, price, url },
  context
) => {
  return context.entities.Product.create({
    data: { title, price, url, userId: context.user.id },
  });
};
Enter fullscreen mode Exit fullscreen mode

React Client (Auto-Generated Hooks)

import { useQuery, useAction } from "wasp/client/operations";
import { getProducts, createProduct } from "wasp/client/operations";

function DashboardPage() {
  const { data: products, isLoading } = useQuery(getProducts);
  const createProductFn = useAction(createProduct);

  if (isLoading) return <Spinner />;

  return (
    <div>
      {products?.map(p => (
        <div key={p.id}>{p.title} — ${p.price}</div>
      ))}
      <button onClick={() => createProductFn({ title: "New", price: 29.99, url: "..." })}>
        Add Product
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Auth: Built-In

import { LoginForm, SignupForm } from "wasp/client/auth";

function LoginPage() {
  return <LoginForm />; // Email + Google OAuth — just works!
}
Enter fullscreen mode Exit fullscreen mode

CLI

wasp new my-app        # Create project
wasp start             # Dev server
wasp db migrate-dev    # Run migrations
wasp deploy fly        # Deploy to Fly.io
Enter fullscreen mode Exit fullscreen mode

Build scraping dashboards fast? My Apify tools + Wasp = full-stack in hours.

Custom full-stack app? Email spinov001@gmail.com

Top comments (0)