Wasp Spec (main.wasp.ts)
You define and configure the high level of your app (pages, routes, queries, actions, auth, ...) in a main.wasp.ts file in the root of your project. We call this file the Wasp Spec.
You write the Wasp Spec in TypeScript, so you get out-of-the-box support in all editors, full type checking, and the flexibility of a real programming language while configuring your app.
The Wasp Spec replaces two older ways of configuring a Wasp app:
- The Wasp DSL (
main.wasp). See Migrating from the Wasp DSL. - The TS Config (
main.wasp.tswith the class-basednew App(...)API). See Migrating from the TS Config.
A quick example
import { app, page, route, query } from '@wasp.sh/spec'
import MainPage from './src/MainPage' with { type: "ref" }
import { getTasks } from './src/queries' with { type: "ref" }
export default app({
name: 'todoApp',
title: 'ToDo App',
wasp: { version: '^0.24.0' },
parts: [
route('MainRoute', '/', page(MainPage, { authRequired: true })),
query(getTasks, { entities: ['Task'] }),
],
})
You build your app by:
- Importing the building blocks (
app,page,route,query, ...) from@wasp.sh/spec. - Importing your own components and functions adding the import attribute
with { type: "ref" }. - Calling
app({ ... })with your app's configuration, listing all the pages, routes, queries, actions, etc. in thepartsarray. - Exporting the result as the default export of the file.
wasp install
The @wasp.sh/spec package doesn't exist on npm, but it is generated by Wasp per project, so we can customize it to fit the needs of your app. We do this through the wasp install command, which sets up the necessary files and dependencies. You'll have to run it at least once after creating a new Wasp project, but you might also need to run it again later on when the generated spec needs to be updated.
If the Spec needs to be regenerated, Wasp will tell you to run wasp install before being able to start the app. Usually, this might happen when upgrading Wasp versions, running wasp clean, or removing the node_modules folder.
Referencing your app's code
Anywhere the Wasp Spec expects your app's function or component (like a page's component or a query's fn), you can provide it in one of two ways:
Reference imports
Recommended
Import the value with the regular syntax, adding with { type: "ref" }. Then you can pass it directly.
import MainPage from './src/MainPage' with { type: "ref" }
import { getTasks } from './src/queries' with { type: "ref" }
export default app({
parts: [
page(MainPage),
query(getTasks)
]
})
You can use relative import paths when splitting an app into multiple files:
import LoginPage from './LoginPage' with { type: "ref" }
export const auth = [
page(LoginPage),
]
Reference imports have some limitations:
- They only work from
*.wasp.tsfiles. - The referenced files must be inside the
srcdirectory.
The vast majority of Wasp apps won't run into these limitations, so we recommend using reference imports by default.
Reference objects
Just pass an object with import (or importDefault) and from:
export default app({
parts: [
page({ importDefault: 'MainPage', from: '@src/MainPage' }),
query({ import: 'getTasks', from: '@src/queries' }),
// You can rename a named import with `alias`:
query({ import: 'getTasks', alias: 'getAllTasks', from: '@src/queries' })
]
})
The from path should always start with @src and is relative to your project's src directory.
Useful patterns
Splitting your spec into multiple files
For larger apps you don't have to keep everything in main.wasp.ts. You can move related parts into their own *.wasp.ts files and combine them in main.wasp.ts.
A feature file exports an array of parts:
import { page, route, Part } from '@wasp.sh/spec'
import LoginPage from './LoginPage' with { type: "ref" }
import SignupPage from './SignupPage' with { type: "ref" }
export const auth: Part[] = [
route('SignupRoute', '/signup', page(SignupPage)),
route('LoginRoute', '/login', page(LoginPage)),
]
Then main.wasp.ts imports it and spreads it into parts:
import { app, page, route } from '@wasp.sh/spec'
import MainPage from './src/MainPage' with { type: "ref" }
import { auth } from './src/auth/auth.wasp'
export default app({
name: 'todoApp',
title: 'ToDo App',
wasp: { version: '^0.24.0' },
parts: [
route('MainRoute', '/', page(MainPage, { authRequired: true })),
...auth,
],
})
All spec files should have the .wasp.ts extension, so they are included in the tsconfig.wasp.json and type-checked.
Detecting production mode
Wasp sets the NODE_ENV environment variable based on which command you use to run Wasp:
"development"duringwasp start(and some other commands that compile the project, likewasp db migrate-dev)."production"duringwasp build.
Because the Wasp Spec is just TypeScript, you can read this variable to switch config values per environment:
const isProd = process.env.NODE_ENV === 'production'
export default app({
//...
emailSender: {
provider: isProd ? 'SMTP' : 'Dummy',
defaultFrom: { email: 'hi@example.com' },
}
})
Reference
Visit our API Reference for a complete overview of all the available configuration options in the Wasp Spec.