docs: add development prompts and vibe coding checklist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
177
dev-docs/MASTER_PROMPT_CURSOR.md
Normal file
177
dev-docs/MASTER_PROMPT_CURSOR.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# Crewli — Cursor Master Prompt
|
||||
# Plak dit BOVEN elke task. Vervang [TASK] onderaan.
|
||||
|
||||
## MANDATORY PREAMBLE
|
||||
|
||||
Read `@CLAUDE.md` and `@dev-docs/SCHEMA.md` before starting. Use `@workspace`
|
||||
for full codebase context. These documents are your source of truth.
|
||||
|
||||
If modifying existing code, read the current implementation first. Understand
|
||||
the patterns already in use before writing anything new.
|
||||
|
||||
## PROJECT CONTEXT
|
||||
|
||||
Crewli — multi-tenant SaaS for event/festival management.
|
||||
|
||||
- **Frontend:** Vue 3 + TypeScript + Vuexy 9.5 (Vuetify 3.10) + Pinia +
|
||||
TanStack Vue Query + VeeValidate + Zod
|
||||
- **Three SPAs:**
|
||||
- `apps/admin/` — Super Admin (port 5173)
|
||||
- `apps/app/` — Organizer main app (port 5174)
|
||||
- `apps/portal/` — Dual-mode portal (port 5175)
|
||||
- **API base:** `VITE_API_URL` from `.env.local` (default `http://localhost:8000`)
|
||||
- **Axios instance:** `src/lib/axios.ts` — this is the ONLY axios instance.
|
||||
Never create another. Never import axios directly in components.
|
||||
- **Backend Enums:** PHP Enums in `api/app/Enums/` define all valid status/type
|
||||
values. TypeScript equivalents must mirror these exactly in `src/types/`.
|
||||
|
||||
### Frontend file structure (per app)
|
||||
|
||||
```
|
||||
src/
|
||||
├── lib/axios.ts # Singleton axios instance (DO NOT DUPLICATE)
|
||||
├── types/ # TypeScript interfaces per module
|
||||
│ └── [module].ts
|
||||
├── composables/api/ # TanStack Query composables per module
|
||||
│ └── use[Module].ts
|
||||
├── stores/ # Pinia stores (cross-component state only)
|
||||
│ └── use[Module]Store.ts
|
||||
├── pages/ # Page components
|
||||
│ └── [module]/
|
||||
│ ├── index.vue # List view
|
||||
│ └── [id].vue # Detail view (or side panel)
|
||||
└── router/ # Vue Router config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ZERO-COMPROMISE RULES — VIOLATIONS ARE BLOCKERS
|
||||
|
||||
### TypeScript & typing
|
||||
|
||||
1. **NO `any` TYPES. EVER.** Every variable, prop, emit, return type, ref,
|
||||
reactive, computed, and API response is fully typed. If you don't know the
|
||||
type, check the backend API Resource in `api/app/Http/Resources/` — that
|
||||
defines the contract. Create matching interfaces in `src/types/[module].ts`.
|
||||
|
||||
2. **TYPES FIRST.** Before writing any composable or component for a new
|
||||
module, create the TypeScript interfaces in `src/types/[module].ts`. These
|
||||
mirror the backend API Resource shape. Include:
|
||||
- Entity interface (e.g., `Shift`, `Person`, `Event`)
|
||||
- Create/Update DTOs (matching backend Form Request fields)
|
||||
- Enum-like union types or const objects matching backend PHP Enums
|
||||
- Paginated response wrapper if applicable
|
||||
|
||||
3. **ENUMS AS CONST OBJECTS.** Mirror backend PHP Enums as TypeScript const
|
||||
objects with `as const`, not as loose string unions scattered across files:
|
||||
```typescript
|
||||
// src/types/shift.ts
|
||||
export const ShiftAssignmentStatus = {
|
||||
PENDING_APPROVAL: 'pending_approval',
|
||||
APPROVED: 'approved',
|
||||
REJECTED: 'rejected',
|
||||
CANCELLED: 'cancelled',
|
||||
COMPLETED: 'completed',
|
||||
} as const
|
||||
export type ShiftAssignmentStatus = typeof ShiftAssignmentStatus[keyof typeof ShiftAssignmentStatus]
|
||||
```
|
||||
|
||||
### Architecture & patterns
|
||||
|
||||
4. **NO DIRECT AXIOS IN COMPONENTS.** All API calls go through composables in
|
||||
`composables/api/use[Module].ts` using TanStack Query (`useQuery` /
|
||||
`useMutation`). Components never import axios or `src/lib/axios.ts`.
|
||||
The composable is the only layer that knows about HTTP.
|
||||
|
||||
5. **NO OPTIONS API.** Always `<script setup lang="ts">`. Props via
|
||||
`defineProps<{...}>()`, emits via `defineEmits<{...}>()`, expose via
|
||||
`defineExpose()`. No `export default { ... }`.
|
||||
|
||||
6. **NO PROP DRILLING.** If state needs to cross more than one component
|
||||
boundary, use a Pinia store (`src/stores/use[Module]Store.ts`). Access
|
||||
reactive state via `storeToRefs()`. Mutations only through store actions.
|
||||
|
||||
7. **DELETE OVER ADAPT.** If you find duplicate composables, overlapping
|
||||
stores, or conflicting patterns: delete the worse version. Do not build
|
||||
alongside existing code that does the same thing. One implementation per
|
||||
concern.
|
||||
|
||||
8. **CONSISTENCY OVER CLEVERNESS.** Look at how existing modules handle the
|
||||
same pattern (table views, form dialogs, detail panels, error handling).
|
||||
Use the exact same approach. Never introduce a "better" alternative without
|
||||
refactoring ALL existing modules to match.
|
||||
|
||||
9. **SINGLE SOURCE OF TRUTH.** Don't duplicate:
|
||||
- Validation logic → Zod schema mirrors backend Form Request. One schema
|
||||
per form, referenced by VeeValidate.
|
||||
- Enum values → const objects in `src/types/`, matching backend Enums.
|
||||
Never use raw string literals like `'approved'` in templates or logic.
|
||||
- API URLs → constructed in composable from module prefix, never
|
||||
hardcoded in components.
|
||||
|
||||
### UI & UX
|
||||
|
||||
10. **NO CUSTOM CSS WHERE VUETIFY HAS A SOLUTION.** Before writing any CSS:
|
||||
check if a Vuetify utility class, component prop, or slot achieves the
|
||||
result. Custom CSS is a last resort, must be `<style scoped>`, and must
|
||||
have a comment explaining why Vuetify couldn't handle it.
|
||||
|
||||
11. **EVERY PAGE HAS THREE STATES:**
|
||||
- **Loading:** Vuetify skeleton loader or progress indicator
|
||||
- **Error:** User-facing message with retry action (`v-alert` with retry
|
||||
button). Show what went wrong in user terms, not technical jargon.
|
||||
- **Empty:** Helpful message explaining why the list is empty and what
|
||||
action to take (not a blank white screen).
|
||||
Never show only the happy path.
|
||||
|
||||
12. **MOBILE-FIRST.** Every component must be usable at 375px width. Use
|
||||
Vuetify's responsive props (`cols`, `sm`, `md`, `lg` on `v-col`). Never
|
||||
use fixed pixel widths for layout. Tables on mobile → card views or
|
||||
horizontal scroll with visual indicator.
|
||||
|
||||
13. **FORMS USE VEEVALIDATE + ZOD.** Define the Zod schema matching the
|
||||
backend Form Request rules. No inline validation logic in templates. Use
|
||||
`useForm()` and `useField()` from VeeValidate with the Zod resolver.
|
||||
|
||||
### Code quality
|
||||
|
||||
14. **NO TODO / FIXME / HACK.** Complete the implementation or report the
|
||||
blocker. No stubs, no "implement later", no placeholder components.
|
||||
|
||||
15. **NO ORPHANED IMPORTS OR UNUSED VARIABLES.** Run `npx tsc --noEmit`
|
||||
after every change. Zero errors, zero warnings. Dead code is deleted
|
||||
immediately, not commented out.
|
||||
|
||||
16. **NO GENERIC NAMES.** Component and composable names must be specific:
|
||||
- ❌ `DataTable.vue`, `useApi.ts`, `helpers.ts`, `utils.ts`
|
||||
- ✅ `ShiftAssignmentTable.vue`, `useShifts.ts`,
|
||||
`formatShiftTimeRange.ts`
|
||||
|
||||
### Routing & auth
|
||||
|
||||
17. **ROUTER GUARDS.** Protected routes check auth state via navigation
|
||||
guard. Portal routes validate token. No unguarded routes to
|
||||
authenticated content. Redirect to login on 401.
|
||||
|
||||
### Process
|
||||
|
||||
18. **COMPONENT CREATION ORDER.** For every new page/feature:
|
||||
1. TypeScript types in `src/types/[module].ts`
|
||||
2. API composable in `src/composables/api/use[Module].ts`
|
||||
3. Pinia store in `src/stores/use[Module]Store.ts` (if cross-component)
|
||||
4. Vue page component in `src/pages/[module]/`
|
||||
5. Router entry in `src/router/`
|
||||
|
||||
19. **VERIFY BEFORE DONE:**
|
||||
- `npx tsc --noEmit` — zero errors
|
||||
- No `any` types anywhere (search: `grep -rn ": any\|as any" src/`)
|
||||
- No TODO/FIXME/HACK
|
||||
- All three states (loading, error, empty) implemented
|
||||
- Mobile responsive at 375px
|
||||
- Consistent with existing module patterns
|
||||
|
||||
---
|
||||
|
||||
## TASK
|
||||
|
||||
[INSERT SPECIFIC TASK HERE]
|
||||
Reference in New Issue
Block a user