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 * * *" },
}
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 },
});
};
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>
);
}
Auth: Built-In
import { LoginForm, SignupForm } from "wasp/client/auth";
function LoginPage() {
return <LoginForm />; // Email + Google OAuth — just works!
}
CLI
wasp new my-app # Create project
wasp start # Dev server
wasp db migrate-dev # Run migrations
wasp deploy fly # Deploy to Fly.io
Build scraping dashboards fast? My Apify tools + Wasp = full-stack in hours.
Custom full-stack app? Email spinov001@gmail.com
Top comments (0)