Skip to content

Commit 2a102e9

Browse files
authored
Update AI Rules & Docs (wasp-lang#431)
* add rules files * Add guide to docs * make Miho happy * add docs referencing info * Update authentication.mdc * Update advanced-troubleshooting.mdc * newlines * add userSignupFields rule to auth rules * update wasp overview rule
1 parent 7fde793 commit 2a102e9

File tree

13 files changed

+730
-52
lines changed

13 files changed

+730
-52
lines changed
20.7 KB
Loading
48 KB
Loading
960 KB
Loading
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: Vibe Coding with Open SaaS
3+
banner:
4+
content: |
5+
Have an Open SaaS app in production? <a href="https://e44cy1h4s0q.typeform.com/to/EPJCwsMi">We'll send you some swag! 👕</a>
6+
---
7+
import { Image } from 'astro:assets';
8+
import llmsFullCursor from '@assets/ai/llm-full-cursor.webp';
9+
import llmsTextChat from '@assets/ai/llm-txt-chat.webp';
10+
import vibeBoi from '@assets/ai/vibe-boi.png';
11+
12+
<Image src={vibeBoi} alt="vibe boi" width={300} />
13+
14+
If you're looking to use AI to help build (or "vibe code") your SaaS app, this guide is for you.
15+
16+
## Coding with AI, Open SaaS, & Wasp
17+
18+
Wasp is particularly well suited to coding with AI due to its central config file which gives LLMs context about the entire full-stack app, and its ability to manage boilerplate code so AI doesn't have to.
19+
20+
Regardless, there are still some shortcomings to using AI to code with Wasp, as well as a learning curve to using it effectively.
21+
22+
Luckily, we did the work for you and put together a bunch of resources to help you use Wasp & Open SaaS with AI as effectively as possible.
23+
24+
### AI Resources in the Template
25+
26+
The template comes with:
27+
- A full set of rules files, `app/.cursor/rules`, to be used with Cursor or adapted to your coding tool of choice (Windsurf, Claude Code, etc.).
28+
- A set of example prompts, `app/.cursor/example-prompts.md`, to help you get started.
29+
30+
### LLM-Friendly Documentation
31+
32+
We've also created a bunch of LLM-friendly documentation:
33+
- [Open SaaS Docs - LLMs.txt](https://docs.opensaas.sh/llms.txt) - Links to the raw text docs.
34+
- [Open SaaS Docs - LLMs-full.txt](https://docs.opensaas.sh/llms-full.txt) - Complete docs as one text file.
35+
- [Wasp Docs - LLMs.txt](https://wasp.sh/llms.txt) - Links to the raw text docs.
36+
- [Wasp Docs - LLMs-full.txt](https://wasp.sh/llms-full.txt) - Complete docs as one text file.
37+
38+
Add these to your AI-assisted IDE settings so you can easily reference them in your chat sessions with the LLM.
39+
**In most cases, you'll want to pass the `llms-full.txt` url to the LLM and ask it to help you with a specific task.**
40+
41+
<Image src={llmsFullCursor} alt="add llms-full.txt to settings" />
42+
43+
<Image src={llmsTextChat} alt="add llms.txt to settings" />
44+
45+
### More AI-assisted Coding Learning Resources
46+
47+
Here's a list of articles and tutorials we've made:
48+
- [3hr YouTube tutorial: Vibe Coding a Personal Finance App w/ Wasp & Cursor](https://www.youtube.com/watch?v=WYzEROo7reY)
49+
- [Article: A Structured Workflow for "Vibe Coding" Full-Stack Apps](https://dev.to/wasp/a-structured-workflow-for-vibe-coding-full-stack-apps-352l)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## Example Prompts
2+
3+
### PRD / initial prompt
4+
5+
I want to create a `<insert-type-of-app-here>` app with the current SaaS boilerplate template project I'm in which uses Wasp and already has payment processing, AWS S3 file upload, a landing page, an admin dashboard, and authentication already setup. Leveraging Wasp's full-stack features (such as Auth), let's build the app based on the following spec:
6+
- `<insert-feature-spec-here>`
7+
- `<insert-feature-spec-here>`
8+
- `<insert-feature-spec-here>`
9+
10+
With this in mind, I want you to first evaluate the project template and think about a few possible PRD approaches before landing on the best one. Provide reasoning why this would be the best approach. Remember we're using Wasp, a full-stack framework with batteries included, that can do some of the heavy lifting for us, and we want to use a modified vertical slice implementation approach for LLM-assisted coding so we can start with basic implementations of features first, and add on complexity from there.
11+
12+
### Plan prompt
13+
14+
From this PRD, create an actionable, step-by-step plan that we can use as a guide for LLM-assisted coding. Remember that this project is a SaaS boilerplate template with many features already implemented. Each feature is organized into its own folder (e.g. `src/payment`) with its client and server code split into subfolders and files. Before you create the plan, think about a few different plan styles that would be suitable for this project and the implmentation style before selecting the best one. Give your reasoning for why you think we should use this plan style. Remember that we will constantly refer to this plan to guide our coding implementation so it should be well structured, concise, and actionable, while still providing enough information to guide the LLM.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
# 6. Advanced Features & Troubleshooting
7+
8+
This document covers advanced Wasp capabilities like Jobs, API Routes, and Middleware, along with performance optimization tips and common troubleshooting steps.
9+
10+
## Advanced Features ( [main.wasp](mdc:main.wasp) )
11+
12+
These features are configured in [main.wasp](mdc:main.wasp).
13+
14+
### Jobs and Workers
15+
16+
- Wasp supports background jobs, useful for tasks like sending emails, processing data, or scheduled operations.
17+
- Jobs require a job executor like PgBoss (which requires PostgreSQL, see [database-operations.mdc](mdc:template/app/.cursor/rules/database-operations.mdc)).
18+
- Example Job definition in [main.wasp](mdc:main.wasp):
19+
```wasp
20+
job emailSender {
21+
executor: PgBoss, // Requires PostgreSQL
22+
// Define the function that performs the job
23+
perform: {
24+
fn: import { sendEmail } from "@src/server/jobs/emailSender.js"
25+
},
26+
// Grant access to necessary entities
27+
entities: [User, EmailQueue]
28+
}
29+
```
30+
- Jobs can be scheduled or triggered programmatically from Wasp actions or other jobs.
31+
- See the Wasp Recurring Jobs Docs for more info [wasp-overview.mdc](mdc:template/app/.cursor/rules/wasp-overview.mdc)
32+
33+
### Custom HTTP API Endpoints
34+
35+
- Define custom server API endpoints, often used for external integrations (webhooks, third-party services) where Wasp Operations are not suitable.
36+
- Example API route definition in [main.wasp](mdc:main.wasp):
37+
```wasp
38+
api stripeWebhook {
39+
// Implementation function in server code
40+
fn: import { handleStripeWebhook } from "@src/server/apis/stripe.js",
41+
// Define the HTTP method and path
42+
httpRoute: (POST, "/webhooks/stripe"),
43+
// Optional: Grant entity access
44+
entities: [User, Payment],
45+
// Optional: Apply middleware config function
46+
// middlewareConfigFn: import { apiMiddleware } from "@src/apis"
47+
// Optional: If auth is enabled, this will default to true and provide a context.user
48+
// object. If you do not wish to attempt to parse the JWT in the Authorization Header
49+
// you should set this to false.
50+
// auth: false
51+
}
52+
```
53+
- See the Wasp Custom HTTP API Endpoints docs for more info [wasp-overview.mdc](mdc:template/app/.cursor/rules/wasp-overview.mdc)
54+
55+
### Middleware
56+
57+
- Wasp supports custom middleware functions that can run before API route handlers or Page components.
58+
- Useful for logging, custom checks, request transformation, etc.
59+
- Example Middleware definition in [main.wasp](mdc:main.wasp):
60+
```wasp
61+
// Customize global middleware
62+
app todoApp {
63+
// ...
64+
server: {
65+
middlewareConfigFn: import { serverMiddlewareFn } from "@src/serverSetup"
66+
},
67+
}
68+
```
69+
- See the Wasp Middleware Docs for more info [wasp-overview.mdc](mdc:template/app/.cursor/rules/wasp-overview.mdc)
70+
71+
## Performance Optimization
72+
73+
- **Operation Dependencies:** Use specific entity dependencies (`entities: [Task]`) in your Wasp operations ([main.wasp](mdc:main.wasp)) to ensure queries are automatically refetched only when relevant data changes.
74+
- **Pagination:** For queries returning large lists of data, implement pagination logic in your server operation and corresponding UI controls on the client.
75+
- **React Optimization:**
76+
- Use `React.memo` for components that re-render often with the same props.
77+
- Use `useMemo` to memoize expensive calculations within components.
78+
- Use `useCallback` to memoize functions passed down as props to child components (especially event handlers).
79+
- **Optimistic UI Updates (Actions):**
80+
- For actions where perceived speed is critical (e.g., deleting an item, marking as complete), consider using Wasp's `useAction` hook (from `wasp/client/operations`) with `optimisticUpdates`.
81+
- This updates the client-side cache (affecting relevant `useQuery` results) *before* the action completes on the server, providing instant feedback.
82+
- **Use Sparingly:** Only implement optimistic updates where the action is highly likely to succeed and the instant feedback significantly improves UX. Remember to handle potential server-side failures gracefully (Wasp helps revert optimistic updates on error).
83+
- See the Wasp Actions docs for more info [wasp-overview.mdc](mdc:template/app/.cursor/rules/wasp-overview.mdc)
84+
85+
## Troubleshooting
86+
87+
- **Wasp Type/Import Errors:** If you encounter TypeScript errors related to missing Wasp imports (e.g., from `wasp/client/operations`, `wasp/entities`, `wasp/server`) or unexpected type mismatches after modifying [main.wasp](mdc:main.wasp) or [schema.prisma](mdc:schema.prisma) , **prompt the user to restart the Wasp development server** (`wasp start`) before further debugging. Wasp needs to regenerate code based on these changes.
88+
- **Operations Not Working:**
89+
- Check that all required `entities` are listed in the operation's definition in [main.wasp](mdc:main.wasp).
90+
- Verify the import path (`fn: import { ... } from "@src/..."`) in [main.wasp](mdc:main.wasp) is correct.
91+
- Check for runtime errors in the Wasp server console where `wasp start` is running.
92+
- Ensure client-side calls match the expected arguments and types.
93+
- **Auth Not Working:**
94+
- Verify the `auth` configuration in [main.wasp](mdc:main.wasp) (correct `userEntity`, `methods`, `onAuthFailedRedirectTo`).
95+
- Ensure `userEntity` in [main.wasp](mdc:main.wasp) matches the actual `User` model name in [schema.prisma](mdc:schema.prisma).
96+
- Check Wasp server logs for auth-related errors.
97+
- If using social auth, confirm environment variables (e.g., `GOOGLE_CLIENT_ID`) are correctly set (e.g., in a `.env.server` file) and loaded by Wasp.
98+
- **Database Issues:**
99+
- Ensure your [schema.prisma](mdc:schema.prisma) syntax is correct.
100+
- Run `wasp db migrate-dev "Migration description"` after schema changes to apply them.
101+
- If using PostgreSQL, ensure the database server is running.
102+
- Check the `.env.server` file for the correct `DATABASE_URL`.
103+
- **Build/Runtime Errors:**
104+
- Check import paths carefully (Wasp vs. relative vs. `@src/` rules, see [project-conventions.mdc](mdc:template/app/.cursor/rules/project-conventions.mdc)).
105+
- Ensure all dependencies are installed (`npm install`).
106+
- Check the Wasp server console and the browser's developer console for specific error messages.
107+
108+
### Referencing Wasp Documentation
109+
- Search for and reference applicable LLM-optimized docs, available in [wasp-overview.mdc](mdc:template/app/.cursor/rules/wasp-overview.mdc)
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
# 4. Authentication
7+
8+
This document gives a quick rundown on how authentication is configured and used within the Wasp application.
9+
10+
See the Wasp Auth docs for available methods and complete guides [wasp-overview.mdc](mdc:template/app/.cursor/rules/wasp-overview.mdc)
11+
12+
## Wasp Auth Setup
13+
14+
- Wasp provides built-in authentication with minimal configuration via the Wasp config file.
15+
- Wasp generates all necessary auth routes, middleware, and UI components based on the configuration.
16+
- Example auth configuration in [main.wasp](mdc:main.wasp):
17+
```wasp
18+
app myApp {
19+
// ... other config
20+
auth: {
21+
// Links Wasp auth to your User model in @schema.prisma
22+
userEntity: User,
23+
methods: {
24+
// Enable username/password login
25+
usernameAndPassword: {},
26+
// Enable Google OAuth login
27+
// Requires setting GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET env vars
28+
google: {},
29+
// Enable email/password login with verification
30+
email: {
31+
// Set up an email sender (Dummy prints to console)
32+
// See https://wasp-lang.com/docs/auth/email-auth#email-sending
33+
fromField: {
34+
name: "Budgeting Vibe",
35+
36+
},
37+
emailVerification: {
38+
clientRoute: EmailVerificationRoute
39+
},
40+
passwordReset: {
41+
clientRoute: PasswordResetRoute
42+
}
43+
}
44+
},
45+
// Route to redirect to if auth fails
46+
onAuthFailedRedirectTo: "/login",
47+
// Optional: Route after successful signup/login
48+
// onAuthSucceededRedirectTo: "/dashboard"
49+
}
50+
emailSender: {
51+
provider: Dummy // Use Dummy for local dev (prints emails to console)
52+
// provider: SMTP // For production, configure SMTP
53+
}
54+
}
55+
56+
// Define the routes needed by email auth methods
57+
route EmailVerificationRoute { path: "/auth/verify-email", to: EmailVerificationPage }
58+
page EmailVerificationPage { component: import { EmailVerification } from "@src/features/auth/EmailVerificationPage.tsx" }
59+
60+
route PasswordResetRoute { path: "/auth/reset-password", to: PasswordResetPage }
61+
page PasswordResetPage { component: import { PasswordReset } from "@src/features/auth/PasswordResetPage.tsx" }
62+
```
63+
64+
- **Dummy Email Provider Note:** When `emailSender: { provider: Dummy }` is configured in [main.wasp](mdc:main.wasp), Wasp does not send actual emails. Instead, the content of verification/password reset emails, including the clickable link, will be printed directly to the server console where `wasp start` is running.
65+
66+
## Wasp Auth Rules
67+
68+
- **User Model ( [schema.prisma](mdc:schema.prisma) ):**
69+
- Wasp Auth methods handle essential identity fields (like `email`, `password hash`, `provider IDs`, `isVerified`) internally. These are stored in separate Prisma models managed by Wasp (`AuthProvider`, `AuthProviderData`).
70+
- Your Prisma `User` model (specified in [main.wasp](mdc:main.wasp) as `auth.userEntity`) typically **only needs the `id` field** for Wasp to link the auth identity.
71+
```prisma
72+
// Minimal User model in @schema.prisma
73+
model User {
74+
id Int @id @default(autoincrement())
75+
// Add other *non-auth* related fields as needed
76+
// e.g., profile info, preferences, relations to other models
77+
// profileImageUrl String?
78+
// timeZone String? @default("UTC")
79+
}
80+
```
81+
- **Avoid adding** `email`, `emailVerified`, `password`, `username`, or provider-specific ID fields directly to *your* `User` model in [schema.prisma](mdc:schema.prisma) unless you have very specific customization needs that require overriding Wasp's default behavior and managing these fields manually.
82+
- If you need frequent access to an identity field like `email` or `username` for *any* user (not just the logged-in one), see the **Recommendation** in the "Wasp Auth User Fields" section below.
83+
84+
- **Auth Pages:**
85+
- When initially creating Auth pages (Login, Signup), use the pre-built components provided by Wasp for simplicity:
86+
- `import { LoginForm, SignupForm } from 'wasp/client/auth';`
87+
- These components work with the configured auth methods in [main.wasp](mdc:main.wasp).
88+
- You can customize their appearance or build completely custom forms if needed.
89+
90+
- **Protected Routes/Pages:**
91+
- Use the `useAuth` hook from `wasp/client/auth` to access the current user's data and check authentication status.
92+
- Redirect or show alternative content if the user is not authenticated.
93+
```typescript
94+
import { useAuth } from 'wasp/client/auth';
95+
import { Redirect } from 'wasp/client/router'; // Or use Link
96+
97+
const MyProtectedPage = () => {
98+
const { data: user, isLoading, error } = useAuth(); // Returns AuthUser | null
99+
100+
if (isLoading) return <div>Loading...</div>;
101+
// If error, it likely means the auth session is invalid/expired
102+
if (error || !user) {
103+
// Redirect to login page defined in main.wasp (auth.onAuthFailedRedirectTo)
104+
// Or return <Redirect to="/login" />;
105+
return <div>Please log in to access this page.</div>;
106+
}
107+
108+
// User is authenticated, render the page content
109+
// Use helpers like getEmail(user) or getUsername(user) if needed
110+
return <div>Welcome back!</div>; // Access user.id if needed
111+
};
112+
```
113+
114+
## Wasp Auth User Fields (`AuthUser`)
115+
116+
- The `user` object returned by `useAuth()` hook on the client, or accessed via `context.user` in server operations/APIs, is an `AuthUser` object (type imported from `wasp/auth`).
117+
- **Auth-specific fields** (email, username, verification status, provider IDs) live under the nested `identities` property based on the auth method used.
118+
- e.g., `user.identities.email?.email`
119+
- e.g., `user.identities.username?.username`
120+
- e.g., `user.identities.google?.providerUserId`
121+
- **Always check for `null` or `undefined`** before accessing these nested properties, as a user might not have used all configured auth methods.
122+
- **Helpers:** Wasp provides helper functions from `wasp/auth` for easier access to common identity fields on the `AuthUser` object:
123+
- `import { getEmail, getUsername } from 'wasp/auth';`
124+
- `const email = getEmail(user); // Returns string | null`
125+
- `const username = getUsername(user); // Returns string | null`
126+
- **Standard User Entities:** Remember that standard `User` entities fetched via `context.entities.User.findMany()` or similar in server code **DO NOT** automatically include these auth identity fields (`email`, `username`, etc.) by default. They only contain the fields defined directly in your [schema.prisma](mdc:schema.prisma) `User` model.
127+
- **Recommendation:**
128+
- If you need *frequent* access to an identity field like `email` or `username` for *any* user (not just the currently logged-in one accessed via `context.user` or `useAuth`) and want to query it easily via `context.entities.User`, consider this approach:
129+
1. **Add the field directly** to your `User` model in [schema.prisma](mdc:schema.prisma).
130+
```prisma
131+
model User {
132+
id Int @id @default(autoincrement())
133+
email String? @unique // Add if needed frequently
134+
// other fields...
135+
}
136+
```
137+
2. **Ensure this field is populated correctly** when the user signs up or updates their profile. You can do this through the `userSignupFields` property in the wasp config file for each auth method.
138+
```wasp
139+
//main.wasp
140+
auth: {
141+
userEntity: User,
142+
methods: {
143+
email: {
144+
//...
145+
userSignupFields: import { getEmailUserFields } from "@src/auth/userSignupFields"
146+
},
147+
}
148+
}
149+
```
150+
```ts
151+
//userSignupFields.ts
152+
import { defineUserSignupFields } from 'wasp/auth/providers/types';
153+
154+
const userDataSchema = z.object({
155+
email: z.string(),
156+
});
157+
158+
export const getEmailUserFields = defineUserSignupFields({
159+
email: (data) => {
160+
const userData = userDataSchema.parse(data);
161+
return userData.email;
162+
}
163+
})
164+
```
165+
3. This makes the field (`email` in this example) a standard, queryable field on your `User` entity, accessible via `context.entities.User`, separate from the `AuthUser`'s identity structure.
166+
167+
- **Common Issue:** If auth isn't working, first verify the `auth` configuration in [main.wasp](mdc:main.wasp) is correct and matches your intent (correct `userEntity`, enabled `methods`, `onAuthFailedRedirectTo`). Ensure environment variables for social providers are set if applicable. Check the Wasp server logs for errors.

0 commit comments

Comments
 (0)