Imported from christensenjo/grimoire (
AGENTS.md). Install upstream withnpx skills add christensenjo/grimoire. Copyright stays with the author.
Agent Guidelines for Grimoire
Laravel 13 + React 19 + Inertia v3 + Tailwind v4 + Pest v4 + Vite+
Build/Development Commands
### In most cases, the developer will already have the environment running locally as they work via Laravel Herd and `vp dev`. Feel free to build in order to catch build errors, or to start your own dev environment if you specifically need to, but in many cases you can simply ask the developer to check the app for your changes.
# Start full dev environment (runs concurrently)
composer run dev # Starts: artisan serve, queue, vite
# Individual frontend commands
vp dev # Start Vite+ dev server
vp build # Production build
vp build --ssr # Build with SSR support
vp run <script> # Run a package.json script through pnpm
# PHP commands
php artisan serve # Start Laravel server
php artisan queue:listen # Start queue worker
Testing Commands
# Run all tests
php artisan test # Run complete test suite
./vendor/bin/pest # Direct Pest execution
# Run specific tests
php artisan test tests/Feature/Auth/AuthenticationTest.php
php artisan test --filter=testName
# Run tests by suite
php artisan test --testsuite=Unit
php artisan test --testsuite=Feature
Lint/Format Commands
# PHP formatting (MUST run before finalizing changes)
vendor/bin/pint # Auto-fix all PHP files
vendor/bin/pint --dirty # Fix only changed files
# Frontend formatting / checks
vp fmt # Auto-fix with Oxfmt
vp fmt --check # Check formatting without fixing
vp lint # Oxlint
vp check # Format, lint, and type-check
Code Style Guidelines
PHP
- PHP 8.2+ features: Use constructor property promotion
- Types: Always declare explicit return types and parameter types
- Braces: Always use curly braces for control structures
- PHPDoc: Prefer PHPDoc blocks over inline comments
- Models: Use
casts()method instead of$castsproperty - Naming: Descriptive variable/method names (
isRegisteredForDiscounts, notdiscount()) - Factories: Always create factories when creating new models
- Validation: Use Form Request classes, not inline validation
TypeScript/React
- Types: Use explicit types, avoid implicit
any - Imports: Group: React → External libs → Internal (@/components)
- Components: Export default for pages, named exports for UI components
- Naming: PascalCase for components, camelCase for functions/variables
- Props: Destructure in function parameters
- Hooks: Follow rules of hooks, include exhaustive deps
Inertia.js
- Use
Inertia::render()instead of Blade views - Place page components in
resources/js/pages - Use
<Link>orrouter.visit()for navigation (not<a>tags) - Use
<Form>component for forms oruseFormhook
Tailwind CSS v4
- Use
@import "tailwindcss"(not deprecated@tailwinddirectives) - Use
/for opacity:bg-black/50(notbg-opacity-50) - Use
shrink-*andgrow-*(notflex-shrink-*/flex-grow-*) - Prefer gap utilities over margins for spacing in lists
- Support dark mode with
dark:prefixes where existing
Testing (Pest v4)
- All tests use Pest syntax (not PHPUnit)
- Use specific assertion methods:
assertForbidden(),assertNotFound() - Create tests with:
php artisan make:test --pest <name> - Use datasets for repetitive validation tests
- Test happy paths, failure paths, and edge cases
Project Structure
app/
Actions/ # Invokable application Actions (see docs/agents/actions.md)
Console/Commands/ # Auto-registered commands
Http/
Controllers/ # Follow existing patterns
Requests/ # Form Request validation classes
Middleware/ # Middleware classes
Models/ # Eloquent models with casts() method
Providers/
bootstrap/
app.php # Register middleware, routes, exceptions
providers.php # Service providers
config/
database/
factories/ # Model factories
seeders/ # Database seeders
resources/
js/
components/ # React components
ui/ # shadcn/ui components
hooks/ # Custom React hooks
layouts/ # Layout components
lib/ # Utilities (cn function)
pages/ # Inertia page components
types/ # TypeScript definitions
css/
tests/
Feature/ # Feature tests
Unit/ # Unit tests
Key Conventions
- Laravel 13 Structure: No
app/Console/Kernel.php, no middleware directory by default - Routes: Use named routes with
route()helper - Actions: Application-layer behavior lives in invokable
App\Actionsclasses; seedocs/agents/actions.md - Slugs: User-facing models exposed through resource/Inertia routes use readable slugs; see
docs/agents/slugs.md - Config: Use
config()helper, neverenv()outside config files - Database: Prefer Eloquent over
DB::facade, eager load to avoid N+1 - Queues: Implement
ShouldQueuefor time-consuming operations - Imports: Check sibling files for existing conventions before writing new code
Migrations and Data Backfills
- Use
Schemaexclusively for structural changes in migrations - Put data backfills in versioned application Actions and Commands that use Eloquent
- Raw
DBstatements in migrations require an explicitly documented exception
Pre-commit Checklist
- Run
vendor/bin/pint --dirtyfor PHP formatting - Run
vp fmtfor frontend formatting - Run
vp lintfor Oxlint checks - Run
vp checkfor TypeScript validation - Run affected tests:
php artisan test --filter=YourFeature - Ensure dark mode support if applicable
React Performance Guidelines (Vercel Best Practices)
Reference these guidelines when writing React components, implementing data fetching, or optimizing performance:
1. Eliminating Waterfalls (CRITICAL)
async-parallel- UsePromise.all()for independent operationsasync-defer-await- Move await into branches where actually usedasync-dependencies- Use better-all for partial dependenciesasync-suspense-boundaries- Use Suspense to stream content
2. Bundle Size Optimization (CRITICAL)
bundle-barrel-imports- Import directly, avoid barrel filesbundle-dynamic-imports- UseReact.lazy()for heavy componentsbundle-defer-third-party- Load analytics after hydrationbundle-conditional- Load modules only when feature is activated
3. Re-render Optimization (MEDIUM)
rerender-memo- Extract expensive work into memoized componentsrerender-memo-with-default-value- Hoist default non-primitive propsrerender-dependencies- Use primitive dependencies in effectsrerender-derived-state- Subscribe to derived booleans, not raw valuesrerender-lazy-state-init- Pass function to useState for expensive valuesrerender-transitions- Use startTransition for non-urgent updatesrerender-use-ref-transient-values- Use refs for transient frequent values
4. Rendering Performance (MEDIUM)
rendering-animate-svg-wrapper- Animate div wrapper, not SVG elementrendering-hoist-jsx- Extract static JSX outside componentsrendering-conditional-render- Use ternary, not && for conditionals
5. JavaScript Performance (LOW-MEDIUM)
js-batch-dom-css- Group CSS changes via classes or cssTextjs-cache-property-access- Cache object properties in loopsjs-combine-iterations- Combine multiple filter/map into one loopjs-early-exit- Return early from functionsjs-set-map-lookups- Use Set/Map for O(1) lookups
React Composition Patterns
Reference these guidelines when building flexible, maintainable React components:
1. Component Architecture (HIGH)
architecture-avoid-boolean-props- Use composition instead of boolean props to customize behaviorarchitecture-compound-components- Structure complex components with shared context
2. State Management (MEDIUM)
state-lift-state- Move state into provider components for sibling accessstate-context-interface- Define generic interface (state, actions, meta) for dependency injection
3. Implementation Patterns (MEDIUM)
patterns-explicit-variants- Create explicit variant components instead of boolean modespatterns-children-over-render-props- Use children for composition instead of renderX props
4. React 19 APIs (MEDIUM)
react19-no-forwardref- Don't useforwardRef; useuse()instead ofuseContext()
Web Interface Guidelines
When asked to "review my UI", "check accessibility", "audit design", or "review UX":
- Follow Web Interface Guidelines for UI best practices
- Check accessibility compliance (keyboard navigation, ARIA labels, color contrast)
- Ensure responsive design patterns are properly implemented
- Validate semantic HTML structure
Animation Performance Guidelines
Reference these guidelines when adding or changing UI animations:
1. Never Patterns (CRITICAL)
- Do not interleave layout reads and writes in the same frame
- Do not animate layout continuously on large surfaces
- Do not drive animation from scroll events
- No requestAnimationFrame loops without a stop condition
- Do not mix multiple animation systems
2. Choose the Mechanism (CRITICAL)
- Default to
transformandopacityfor motion - Use JS-driven animation only when interaction requires it
- Paint or layout animation only on small, isolated surfaces
- Prefer downgrading technique over removing motion entirely
3. Measurement (HIGH)
- Measure once, then animate via transform or opacity
- Batch all DOM reads before writes
- Prefer FLIP-style transitions for layout-like effects
4. Scroll (HIGH)
- Prefer Scroll or View Timelines for scroll-linked motion
- Use IntersectionObserver for visibility and pausing
- Do not poll scroll position for animation
- Pause animations when off-screen
5. Paint & Layers (MEDIUM)
- Paint-triggering animation only on small, isolated elements
- Do not animate CSS variables for transform/opacity
- Use
will-changetemporarily and surgically - Avoid many or large promoted layers
6. Blur and Filters (MEDIUM)
- Keep blur animation small (<=8px)
- Use blur only for short, one-time effects
- Never animate blur continuously on large surfaces
- Prefer opacity and translate before blur
Design System & Components
We use shadcn/ui as our component library. When creating components or building features:
- Check shadcn first - Look for existing components at https://ui.shadcn.com/docs/components before building custom ones
- Install missing primitives - Prefer
pnpm dlx shadcn@latest add <component>over hand-rolling a styled native control with copied token classes - shadcn MCP available - Use the shadcn MCP server (configured in
opencode.json) for component discovery and documentation - Brand colors configured - Our
resources/css/app.cssis set up with brand colors mapped to shadcn CSS variables - Base UI only - shadcn components must use Base UI (
@base-ui/react), not Radix UI. Do not add@radix-ui/*dependencies. Install components withpnpm dlx shadcn@latest add <component>using the existingbase-vegastyle incomponents.json, then verify generated components import from@base-ui/react. - Extend, don't replace - Build on top of existing shadcn components rather than creating parallel implementations
- Native form controls when needed - Native
<select>(and similar) is acceptable when a Base UI compound control is a poor fit for uncontrolled Inertia<Form>namesubmission; still avoid duplicating Input-like class strings across call sites when a primitive exists
Interim Design Philosophy
Until Grimoire is closer to feature-complete, prioritize shipping backend and product functionality over custom visual design.
- Use stock shadcn/ui components and simple layouts before custom-designed surfaces
- Keep styling minimal and local to components; do not modify
resources/css/app.cssfor temporary marketing polish - Keep the public landing page honest and minimal while major advertised features are still in progress
- Preserve the
Lombardicdrop-cap component as an intentional design element - Revisit this section when the app is ready for a more comprehensive design process
External Rules
See .cursor/rules/laravel-boost.mdc for comprehensive Laravel Boost guidelines including:
- Version-specific documentation search with
search-docstool - Laravel Boost MCP server usage
- Inertia v2 features (polling, prefetching, deferred props)
- React + Inertia form patterns
- Tailwind v4 migration notes
Agent skills
Issue tracker
Issues live in Linear (workspace grimoire-worldbuilding, team key JBC), accessed via the Linear MCP server; external PRs are not a triage surface. See docs/agents/issue-tracker.md.
Triage labels
The five canonical triage roles map 1:1 to Linear labels (needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix). See docs/agents/triage-labels.md.
Domain docs
Single-context: CONTEXT.md at the repo root is the domain glossary; ADRs live in docs/adr/. See docs/agents/domain.md.
Frontend skills
Global UI/design skills (ibelick, Emil, ui.sh) and how they attach to the mattpocock SDLC — current choices and deferred evaluation. See docs/agents/frontend-skills-roadmap.md.