-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Use expanded cursorrules after testing * update package-lock
- Loading branch information
Showing
2 changed files
with
12,000 additions
and
7,200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,241 @@ | ||
// Wasp Import Rules | ||
- Import Wasp functions from 'wasp' package, not '@wasp' | ||
# Overview | ||
You are a TypeScript, Node.js, Wasp, React, Shadcn UI, Radix UI, Zod, React Hook Form, and TailwindCSS expert with deep knowledge on each topic. | ||
This project is a Wasp app template. It includes a bunch of examples and guides. | ||
You are helping a developer set up the project and add new pages while using the project's conventions as an example. | ||
|
||
# Wasp Rules | ||
## main.wasp and general | ||
- Wasp is on ^0.15.x | ||
- Try not to remove things from main.wasp unless the user asks you to, if you do, use the existing code as an example. | ||
- When you add a route, page, action, query, or job to main.wasp the app will not work | ||
until you add the related file to the directory, so make sure to add one. | ||
|
||
## Actions and Queries | ||
- Store actions and queries together in feature/operations.ts | ||
- For queries, always use the satisfies keyword so we can dynamically type the response later with | ||
``` | ||
export interface ExampleProps { | ||
example: Awaited<ReturnType<typeof getExample>> | ||
} | ||
``` | ||
|
||
## Routing | ||
- Use Wasp's built-in Link component from wasp/client/router for internal links | ||
- Use <a> elements for external links and anchor links | ||
|
||
# Import Rules | ||
|
||
## Wasp Imports | ||
- Always import Wasp functions from 'wasp' package, not '@wasp' | ||
✓ import { Task } from 'wasp/entities' | ||
✓ import { type GetTasks } from 'wasp/server/operations' | ||
✓ import { getTasks, useQuery } from 'wasp/client/operations' | ||
✗ import { ... } from '@wasp/...' | ||
|
||
// Wasp Schema Rules | ||
## React Imports | ||
- Do not import React from 'react' because it's automatically imported | ||
- Import hooks directly from packages: | ||
✓ import { useState } from 'react' | ||
✗ import React, { useState } from 'react' | ||
|
||
## Motion Imports | ||
- Import from 'motion/react' instead of 'framer-motion' | ||
✓ import { motion } from 'motion/react' | ||
✗ import { motion } from 'framer-motion' | ||
|
||
## General Imports | ||
- Never use the @ alias, use relative imports only. | ||
- When the user manually updates the import you suggest, please don't change it back. | ||
|
||
# Schema & Data Models | ||
|
||
## Prisma Schema | ||
- Add new entities (models) to 'schema.prisma', NOT 'main.wasp' | ||
- Use meaningful names for models and fields | ||
- Add proper relations between models | ||
- Include field validations where needed | ||
- Provide default values where it makes common sense (fields like createdAt and updatedAt can default to now) | ||
- Follow Prisma naming conventions: | ||
✓ Model names: PascalCase (User, Task) | ||
✓ Field names: camelCase (firstName, createdAt) | ||
|
||
// Wasp Dependencies | ||
# Dependencies & Package Management | ||
|
||
## Installation | ||
- Do NOT add dependencies to 'main.wasp' | ||
- Install dependencies via 'npm install' instead | ||
- Use exact versions for critical dependencies | ||
- Keep dependencies up to date | ||
- Keep dependencies in package.json | ||
|
||
# TypeScript | ||
|
||
## General | ||
- Always use TypeScript for new files | ||
- Enable strict mode in tsconfig | ||
- Define proper types for all variables and functions | ||
- Use type inference when types are obvious | ||
- Use .tsx extension for React components | ||
- Use .ts extension for non-React files | ||
- Define proper types for operations: | ||
✓ type GetTasks = QueryFn<void, Task[]> | ||
✓ type CreateTask = ActionFn<{ description: string }, Task> | ||
|
||
## Type Definitions | ||
- Place shared types in the same file they will be used in. | ||
- Use interface for object types that can be extended | ||
- Use type for unions, intersections, and mapped types | ||
|
||
# Styling | ||
|
||
## Icon library | ||
- Use @phosphor-icons/react for icons | ||
|
||
## Tailwind CSS | ||
- Use Tailwind CSS for styling | ||
- Do not use inline styles unless absolutely necessary | ||
- Follow semantic color naming: | ||
✓ text-destructive, text-muted-foreground | ||
✗ text-red-500, text-gray-600 | ||
- Let the theme handle colors and spacing | ||
- Follow mobile-first approach | ||
|
||
## Lint and format | ||
- Follow these prettier rules | ||
{ | ||
"arrowParens": "avoid", | ||
"bracketSpacing": true, | ||
"htmlWhitespaceSensitivity": "css", | ||
"insertPragma": false, | ||
"bracketSameLine": false, | ||
"jsxSingleQuote": true, | ||
"printWidth": 80, | ||
"proseWrap": "always", | ||
"quoteProps": "as-needed", | ||
"requirePragma": false, | ||
"semi": false, | ||
"singleQuote": true, | ||
"tabWidth": 2, | ||
"trailingComma": "all", | ||
"useTabs": false, | ||
} | ||
- Use ' for apostrophes in content | ||
|
||
|
||
## Component Structure | ||
- Group related styles together | ||
- Use meaningful class names | ||
- Leverage Tailwind's responsive utilities | ||
- Use good UI spacing via the tailwind gap class. | ||
|
||
# State Management | ||
- Use Wasp's built-in auth state management | ||
- Use Wasp's built-in useQuery for server state | ||
- Use local state (useState) for UI state | ||
- Use context sparingly and only for truly global state | ||
- Use appropriate hooks for state management | ||
- Keep state as local as possible | ||
- Avoid prop drilling with context when needed | ||
- Implement proper error boundaries | ||
|
||
# Performance | ||
- Use proper key props in lists | ||
- Use precaching for routes where it makes sense | ||
- Use proper caching strategies | ||
- Implement proper data fetching patterns | ||
- Use proper React Query configurations | ||
- Use proper code splitting | ||
|
||
// Wasp | ||
- Always use typescript for Wasp code. | ||
# Accessibility | ||
- Use semantic HTML elements | ||
- Include proper ARIA labels | ||
- Ensure keyboard navigation works | ||
- Maintain sufficient color contrast | ||
- Support reduced motion preferences | ||
- Support screen readers | ||
- Implement proper ARIA attributes | ||
|
||
// Framer Motion | ||
- Use 'motion/react' instead of 'framer-motion', this is the new opensourced version of Framer Motion. | ||
# Error Handling | ||
- Implement proper error boundaries | ||
- Use type-safe error handling | ||
- Log errors appropriately | ||
- Provide user-friendly error messages | ||
- Handle operation errors appropriately: | ||
✓ try { await createTask(...) } catch (e) { handleError(e) } | ||
|
||
// CSS | ||
- Use Tailwind CSS for styling. | ||
- Do not use inline styles. | ||
# Project Structure | ||
- Organize code by features (vertically) rather than technical layers | ||
✓ src/tasks/{actions.ts,queries.ts,TaskList.tsx} | ||
✓ src/auth/{actions.ts,LoginPage.tsx} | ||
✗ src/client/components/TaskList.tsx | ||
- Keep source files in src/ | ||
- Keep static files in public/ | ||
- Use feature-based organization: ``` | ||
src/ | ||
├── tasks/ | ||
│ ├── actions.ts | ||
│ ├── queries.ts | ||
│ └── TaskList.tsx | ||
├── auth/ | ||
│ ├── actions.ts | ||
│ ├── LoginPage.tsx | ||
│ └── RegisterPage.tsx | ||
└── shared/ | ||
└── utils.ts ``` | ||
|
||
// General | ||
- Use single quotes | ||
# Forms | ||
- Use React Hook Form for form actions like useForm and zodresolver | ||
- Use Zod to validate form schemas | ||
- Here is an example form using both | ||
``` | ||
import { zodResolver } from "@hookform/resolvers/zod" | ||
import { useForm } from "react-hook-form" | ||
import { z } from "zod" | ||
|
||
import { Button } from "@/components/ui/button" | ||
import { | ||
Form, | ||
FormControl, | ||
FormDescription, | ||
FormField, | ||
FormItem, | ||
FormLabel, | ||
FormMessage, | ||
} from "@/components/ui/form" | ||
import { Input } from "@/components/ui/input" | ||
|
||
const formSchema = z.object({ | ||
username: z.string().min(2, { | ||
message: "Username must be at least 2 characters.", | ||
}), | ||
}) | ||
|
||
export function ProfileForm() { | ||
// ... | ||
|
||
return ( | ||
<Form {...form}> | ||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"> | ||
<FormField | ||
control={form.control} | ||
name="username" | ||
render={({ field }) => ( | ||
<FormItem> | ||
<FormLabel>Username</FormLabel> | ||
<FormControl> | ||
<Input placeholder="shadcn" {...field} /> | ||
</FormControl> | ||
<FormDescription> | ||
This is your public display name. | ||
</FormDescription> | ||
<FormMessage /> | ||
</FormItem> | ||
)} | ||
/> | ||
<Button type="submit">Submit</Button> | ||
</form> | ||
</Form> | ||
) | ||
} | ||
``` | ||
- Type validate all form inputs. |
Oops, something went wrong.