This project uses pnpm as its package manager. Always use pnpm for all package operations:
- Installing packages:
pnpm add <package> - Running scripts:
pnpm <script-name> - For shadcn/ui components: Use
pnpm dlx shadcn@latest add <component>(notnpx)
Never use npm or yarn for this project.
When working on this project, always follow these steps before completing your work:
pnpm type-checkRun TypeScript compiler to check for type errors. Fix any type errors that appear.
pnpm fixThis will automatically format and lint all code using Ultracite (combines formatting and linting with auto-fixes).
If any of the above commands fail or show errors:
- Read the error messages carefully
- Fix the issues in the relevant files
- Re-run the commands to verify fixes
- Repeat until all checks pass
- Never commit code with type errors or linting issues
- Run
pnpm fixbefore making commits to ensure code is properly formatted and linted - All checks must pass before work is considered complete
- No Emojis: Do not use emojis in any code, documentation, or README files
- No File Structure: Do not include file/folder structure diagrams in README files
- No Random Documentation: Do not create markdown documentation files unless explicitly requested by the user. This includes integration guides, feature documentation, or any other .md files
- Use shadcn/ui: Always use shadcn/ui components when available. Do not create custom components that duplicate shadcn functionality
- Add Components: Use
pnpm dlx shadcn@latest add <component>to add new shadcn components as needed - No Native Dialogs: Never use native
alert()orconfirm()dialogs. Always use shadcn AlertDialog, Dialog, or Sonner toast components instead
- Generate Migrations: Use
pnpm db:generateto automatically generate database migrations from schema changes - Never Write Manual Migrations: Do not manually create SQL migration files in the
drizzle/directory - Workflow:
- Update the schema in
lib/db/schema.ts - Run
pnpm db:generateto generate the migration - Run
pnpm db:pushto apply the migration to the database
- Update the schema in
- The migration generator will create properly formatted SQL files based on your schema changes
- Remove Unused Code: If a variable, import, or function is unused, remove it entirely. Do not prefix with underscore unless it's intentionally unused but required (e.g., function parameters)
- Use Correct Jotai Hooks: When working with Jotai atoms, use the appropriate hook based on usage:
useAtom(atom)- Use when you need both the value and setteruseAtomValue(atom)- Use when you only need to read the valueuseSetAtom(atom)- Use when you only need the setter function- Never use
useAtomif you're only using one part (getter or setter)
- Use API Routes: This project uses API routes instead of Next.js server actions
- API Client: Always use the type-safe API client from
@/lib/api-clientfor all backend calls - No Server Actions: Do not create or use server actions (files with
"use server"directive) - Import Pattern: Import the API client as
import { api } from "@/lib/api-client" - Available APIs:
api.ai.*- AI operations (generate workflows)api.integration.*- Test integration connectionsapi.user.*- User operations (get, update)api.vercelProject.*- Vercel project integrationsapi.workflow.*- Workflow CRUD and operations (create, update, delete, deploy, execute, etc.)
- No Barrel Files: Do not create barrel/index files that re-export from other files
- No SDK Dependencies: Plugin step files must use
fetchdirectly instead of SDK client libraries. Do not add npm package dependencies for API integrations. - No dependencies field: Do not use the
dependenciesfield in pluginindex.tsfiles. All API calls should use nativefetch. - Why: Using
fetchinstead of SDKs reduces supply chain attack surface. SDKs have transitive dependencies that could be compromised.
All plugin steps must return a standardized output format:
// Success
return { success: true, data: { id: "...", name: "..." } };
// Error
return { success: false, error: { message: "Error description" } };- outputFields in plugin
index.tsshould reference fields withoutdata.prefix (e.g.,{ field: "id" }not{ field: "data.id" }) - Template variables automatically unwrap:
{{GetUser.firstName}}resolves todata.firstName - Logs display only the inner
dataorerrorobject, not the full wrapper