-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Update AI Rules & Docs #431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
d29a9be
bae70d2
0061da2
10258f2
2ed1be4
3b88229
3d7ea98
9425d07
186d7df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
--- | ||
title: Vibe Coding with Open SaaS | ||
banner: | ||
content: | | ||
Have an Open SaaS app in production? <a href="https://e44cy1h4s0q.typeform.com/to/EPJCwsMi">We'll send you some swag! 👕</a> | ||
--- | ||
import { Image } from 'astro:assets'; | ||
import llmsFullCursor from '@assets/ai/llm-full-cursor.webp'; | ||
import llmsTextChat from '@assets/ai/llm-txt-chat.webp'; | ||
import vibeBoi from '@assets/ai/vibe-boi.png'; | ||
|
||
<Image src={vibeBoi} alt="vibe boi" width={300} /> | ||
|
||
If you're looking to use AI to help build (or "vibe code") your SaaS app, this guide is for you. | ||
|
||
## Coding with AI, Open SaaS, & Wasp | ||
|
||
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. | ||
|
||
Regardless, there are still some shortcomings to using AI to code with Wasp, as well as a learning curve to using it effectively. | ||
|
||
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. | ||
|
||
### AI Resources in the Template | ||
|
||
The template comes with: | ||
- 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.). | ||
- A set of example prompts, `app/.cursor/example-prompts.md`, to help you get started. | ||
|
||
### LLM-Friendly Documentation | ||
|
||
We've also created a bunch of LLM-friendly documentation: | ||
- [Open SaaS Docs - LLMs.txt](https://docs.opensaas.sh/llms.txt) - Links to the raw text docs. | ||
- [Open SaaS Docs - LLMs-full.txt](https://docs.opensaas.sh/llms-full.txt) - Complete docs as one text file. | ||
- [Wasp Docs - LLMs.txt](https://wasp.sh/llms.txt) - Links to the raw text docs. | ||
- [Wasp Docs - LLMs-full.txt](https://wasp.sh/llms-full.txt) - Complete docs as one text file. | ||
|
||
Add these to your AI-assisted IDE settings so you can easily reference them in your chat sessions with the LLM. | ||
**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.** | ||
|
||
<Image src={llmsFullCursor} alt="add llms-full.txt to settings" /> | ||
|
||
<Image src={llmsTextChat} alt="add llms.txt to settings" /> | ||
|
||
### More AI-assisted Coding Learning Resources | ||
|
||
Here's a list of articles and tutorials we've made: | ||
- [3hr YouTube tutorial: Vibe Coding a Personal Finance App w/ Wasp & Cursor](https://www.youtube.com/watch?v=WYzEROo7reY) | ||
- [Article: A Structured Workflow for "Vibe Coding" Full-Stack Apps](https://dev.to/wasp/a-structured-workflow-for-vibe-coding-full-stack-apps-352l) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
## Example Prompts | ||
|
||
### PRD / initial prompt | ||
|
||
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: | ||
- `<insert-feature-spec-here>` | ||
- `<insert-feature-spec-here>` | ||
- `<insert-feature-spec-here>` | ||
|
||
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. | ||
|
||
### Plan prompt | ||
|
||
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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
--- | ||
description: | ||
globs: | ||
alwaysApply: true | ||
--- | ||
# 6. Advanced Features & Troubleshooting | ||
|
||
This document covers advanced Wasp capabilities like Jobs, API Routes, and Middleware, along with performance optimization tips and common troubleshooting steps. | ||
|
||
## Advanced Features ( [main.wasp](mdc:main.wasp) ) | ||
|
||
These features are configured in [main.wasp](mdc:main.wasp). | ||
|
||
### Jobs and Workers | ||
|
||
- Wasp supports background jobs, useful for tasks like sending emails, processing data, or scheduled operations. | ||
- Jobs require a job executor like PgBoss (which requires PostgreSQL, see [3-database-operations.mdc](mdc:.cursor/rules/3-database-operations.mdc) ). | ||
- Example Job definition in [main.wasp](mdc:main.wasp): | ||
```wasp | ||
job emailSender { | ||
executor: PgBoss, // Requires PostgreSQL | ||
// Define the function that performs the job | ||
perform: { | ||
fn: import { sendEmail } from "@src/server/jobs/emailSender.js" | ||
}, | ||
// Grant access to necessary entities | ||
entities: [User, EmailQueue] | ||
} | ||
``` | ||
- Jobs can be scheduled or triggered programmatically from Wasp actions or other jobs. | ||
- See [Wasp Jobs Documentation](mdc:https:/wasp-lang.com/docs/advanced/jobs). | ||
|
||
### API Routes | ||
|
||
- Define custom server API endpoints, often used for external integrations (webhooks, third-party services) where Wasp Operations are not suitable. | ||
- Example API route definition in [main.wasp](mdc:main.wasp): | ||
```wasp | ||
api stripeWebhook { | ||
// Implementation function in server code | ||
fn: import { handleStripeWebhook } from "@src/server/apis/stripe.js", | ||
// Define the HTTP method and path | ||
httpRoute: (POST, "/webhooks/stripe"), | ||
// Optional: Grant entity access | ||
entities: [User, Payment], | ||
// Optional: Apply middleware | ||
// middlewares: [checkStripeSignature] | ||
// Optional: Disable default auth check if webhook handles its own | ||
// auth: false | ||
} | ||
``` | ||
- See [Wasp API Routes Documentation](mdc:https:/wasp-lang.com/docs/advanced/apis). | ||
|
||
### Middleware | ||
|
||
- Wasp supports custom middleware functions that can run before API route handlers or Page components. | ||
- Useful for logging, custom authentication/authorization checks, request transformation, etc. | ||
- Example Middleware definition in [main.wasp](mdc:main.wasp): | ||
```wasp | ||
// Define the middleware itself | ||
middleware checkAdmin { | ||
fn: import { checkAdminMiddleware } from "@src/server/middleware/auth.js" | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we ever use middleware to check if someone is an admin? Will this example steer Cursur in the wrong direction? |
||
|
||
// Apply it to a page or API route | ||
page AdminDashboardPage { | ||
component: import { AdminDashboard } from "@src/features/admin/AdminDashboardPage.tsx", | ||
auth: true, // Ensure user is logged in first | ||
middlewares: [checkAdmin] // Apply custom admin check | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
api adminAction { | ||
fn: import { handleAdminAction } from "@src/server/apis/admin.js", | ||
httpRoute: (POST, "/api/admin/action"), | ||
auth: true, | ||
middlewares: [checkAdmin] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't exist in Wasp as well, the proper key is |
||
} | ||
``` | ||
- See [Wasp Middleware Documentation](mdc:https:/wasp-lang.com/docs/advanced/middleware). | ||
|
||
## Performance Optimization | ||
|
||
- **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. | ||
- **Pagination:** For queries returning large lists of data, implement pagination logic in your server operation and corresponding UI controls on the client. | ||
- **React Optimization:** | ||
- Use `React.memo` for components that re-render often with the same props. | ||
- Use `useMemo` to memoize expensive calculations within components. | ||
- Use `useCallback` to memoize functions passed down as props to child components (especially event handlers). | ||
- **Optimistic UI Updates (Actions):** | ||
- 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`. | ||
- This updates the client-side cache (affecting relevant `useQuery` results) *before* the action completes on the server, providing instant feedback. | ||
- **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). | ||
- Example: | ||
```typescript | ||
import { useAction, useQuery } from 'wasp/client/operations'; | ||
import { deleteTask, getTasks } from 'wasp/client/operations'; // Assuming these exist | ||
import type { Task } from 'wasp/entities'; | ||
|
||
function TaskList() { | ||
const { data: tasks } = useQuery(getTasks); | ||
|
||
// Use useAction when optimistic updates are needed | ||
const { execute: deleteAction, isExecuting } = useAction(deleteTask, { | ||
optimisticUpdates: [ | ||
{ | ||
// Specify the query to update optimistically | ||
getQuerySpecifier: getTasks, | ||
// Function to update the query cache | ||
updateQuery: (oldTasks, args) => { | ||
// args contains { taskId: number } passed to deleteAction | ||
return oldTasks.filter(task => task.id !== args.taskId); | ||
} | ||
} | ||
] | ||
}); | ||
|
||
const handleDelete = async (taskId: number) => { | ||
try { | ||
await deleteAction({ taskId }); | ||
} catch (error) { | ||
console.error("Failed to delete task:", error); | ||
// Optionally show an error message to the user | ||
} | ||
}; | ||
|
||
// ... render task list with delete buttons calling handleDelete ... | ||
} | ||
``` | ||
- See [Wasp Optimistic Updates Documentation](mdc:https:/wasp-lang.com/docs/advanced/optimistic-updates). | ||
|
||
## Troubleshooting | ||
|
||
- **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) , **try restarting the Wasp development server** (stop `Ctrl+C` and run `wasp start` again) before further debugging. Wasp needs to regenerate code based on these changes. | ||
- **Operations Not Working:** | ||
- Check that all required `entities` are listed in the operation's definition in [main.wasp](mdc:main.wasp). | ||
- Verify the import path (`fn: import { ... } from "@src/..."`) in [main.wasp](mdc:main.wasp) is correct. | ||
- Check for runtime errors in the Wasp server console where `wasp start` is running. | ||
- Ensure client-side calls match the expected arguments and types. | ||
- **Auth Not Working:** | ||
- Verify the `auth` configuration in [main.wasp](mdc:main.wasp) (correct `userEntity`, `methods`, `onAuthFailedRedirectTo`). | ||
- Ensure `userEntity` in [main.wasp](mdc:main.wasp) matches the actual `User` model name in [schema.prisma](mdc:schema.prisma). | ||
- Check Wasp server logs for auth-related errors. | ||
- 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. | ||
- **Database Issues:** | ||
- Ensure your [schema.prisma](mdc:schema.prisma) syntax is correct. | ||
- Run `wasp db migrate-dev "Migration description"` after schema changes to apply them. | ||
- If using PostgreSQL, ensure the database server is running. | ||
- Check the `.env.server` file for the correct `DATABASE_URL`. | ||
- **Build/Runtime Errors:** | ||
- Check import paths carefully (Wasp vs. relative vs. `@src/` rules, see [2-project-conventions.mdc](mdc:.cursor/rules/2-project-conventions.mdc) ). | ||
- Ensure all dependencies are installed (`npm install`). | ||
- Check the Wasp server console and the browser's developer console for specific error messages. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should have newlines at the end of files - you get nicer diffs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose we'll merge this first: wasp-lang/wasp#2772
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah that was my assumption.