Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .cursor/rules/ai-rules-generated-00-project-context.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
description: Project overview and context for react-router-starter
globs: **/*
alwaysApply: true
---

# Project Context

## What This Repo Is

**react-router-starter** is a monorepo starter for React Router 7 apps with best practices: Storybook, @lambdacurry/forms, Bun test + React Testing Library, and shared AI rules.

## Structure

- **apps/todo-app** – Reference app (React Router 7, Vite, Tailwind v4, forms, Storybook, tests).
- **packages/** – Shared packages (e.g. `@todo-starter/ui`, `@todo-starter/utils`) used by apps.
- **ai-rules/** – Source-of-truth AI rules (project context, React Router, Storybook, forms, testing, monorepo, UI).
- **.cursor/rules/** – Generated Cursor rules (do not edit directly).
- **AGENTS.md / CLAUDE.md / GEMINI.md** – Generated agent rules (do not edit directly).

## Issue Tracking (Beads)

Beads is required **only** when running Ralph loops or when a task explicitly comes from Beads. For ad-hoc work, you can skip Beads.

When Beads is in use, follow `.devagent/plugins/ralph/AGENTS.md` and use the CLI:

```bash
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --status in_progress # Claim work
bd update <id> --status closed # Complete work
bd sync # Sync with git
```

## Quality Gates (todo-app)

From `apps/todo-app/package.json`:

- **Test:** `bun run test:run` or `bun run test:ci` (Bun test)
- **Lint:** `npm run lint` (Biome)
- **Typecheck:** `npm run typecheck` (tsc)
- **Build:** `npm run build` (react-router build)
- **Storybook:** `npm run storybook` (dev), `npm run build-storybook` (build)

Run these from `apps/todo-app` or via workspace root scripts if defined.

## Conventions

- **Routing:** File-based routes in `app/routes/`; use loaders/actions and route types.
- **Forms:** @lambdacurry/forms + remix-hook-form + Zod; see `ai-rules/lambda-curry-forms.md`.
- **Tests:** Bun test + React Testing Library; use `renderWithRouter` for router-dependent components; see `apps/todo-app/TESTING.md` and `ai-rules/testing-best-practices.md`.
- **Styling:** Tailwind CSS v4; mobile-first; prefer existing UI components.

## AI Rules Workflow

- **Edit source rules** in `ai-rules/`
- **Generated outputs** in `.generated-ai-rules/` and `.cursor/rules/` are maintained by repository automation
- **Do not edit generated files directly**; change source rules in `ai-rules/`
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,6 @@ export const action = async ({ request }: ActionFunctionArgs) => {
};
```

## Advanced Patterns

### Conditional Fields
```typescript
const watchAccountType = methods.watch('accountType');

{watchAccountType === 'business' && (
<TextField name="companyName" label="Company Name" />
)}
```

## Available Form Components

### TextField Component
Expand Down
49 changes: 49 additions & 0 deletions .cursor/rules/ai-rules-generated-monorepo.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
description: Monorepo structure, package boundaries, and workspace conventions
globs: **/*
alwaysApply: true
---

# Monorepo Rules

## Package Structure
- `apps/` - Applications (todo-app)
- `packages/` - Shared packages (ui, utils)
- Each package has its own package.json with proper exports

## Workspace Dependencies
- Use `workspace:*` for internal package dependencies
- Keep external dependencies in sync across packages
- Use peerDependencies for shared libraries like React

## Import Patterns
```tsx
// Import from workspace packages
import { Button } from '@todo-starter/ui';
import { cn, type Todo } from '@todo-starter/utils';

// Import from local files
import { TodoItem } from '~/components/todo-item';
import type { Route } from './+types/home';
```

## Package Naming
- Use scoped packages: `@todo-starter/package-name`
- Keep names descriptive and consistent
- Use kebab-case for package names

## Scripts and Tasks
- Define scripts at both root and package level
- Use Turbo for orchestrating build tasks
- Prefer package-specific scripts for development

## TypeScript Configuration
- Use Tailwind CSS v4's CSS-first configuration with `@theme` directive
- Use path mapping for workspace packages
- Keep tsconfig.json files minimal and focused

## Best Practices
- Keep packages focused and single-purpose
- Avoid circular dependencies between packages
- Use proper exports in package.json
- Document package APIs and usage patterns
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ alwaysApply: false
Components that use `Link`, `useNavigate`, `useFetcher`, or `useHref` need router context. Use a global decorator in `preview.tsx`:

```tsx
import type { Preview } from '@storybook/react';
import type { ComponentType } from 'react';
import { createMemoryRouter, RouterProvider } from 'react-router-dom';

Expand Down
78 changes: 78 additions & 0 deletions .cursor/rules/ai-rules-generated-testing-best-practices.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
description: Bun test and React Testing Library patterns for React Router apps
globs: apps/**/*.test.{ts, tsx}, apps/**/*.spec.{ts, tsx}, apps/**/test/**/*
alwaysApply: false
---

# Testing Best Practices

## Stack

- **Runner:** Bun test (`bun:test`) with JSDOM bootstrap in `test/setup.ts` (loaded via `bunfig.toml`)
- **Component/DOM:** React Testing Library
- **Router:** `createMemoryRouter` + `RouterProvider` via shared `renderWithRouter` helper

## Test Layout (todo-app)

| Pattern | Location | Purpose |
|---------------|-----------------------------------|--------|
| Unit | `app/lib/__tests__/*.test.ts` | Pure utilities, helpers |
| Component | `app/components/__tests__/*.test.tsx` | UI with router/context mocking |
| Integration | `app/routes/__tests__/*.integration.test.tsx` | Full route + provider flows |

Shared setup: `test/setup.ts` (jest-dom, RTL cleanup). Shared helpers: `test/test-utils.tsx`.

## Router-Dependent Components

Use `renderWithRouter` for any component that uses `Link`, `useNavigate`, `useFetcher`, or `useHref`:

```tsx
import { renderWithRouter } from '../../../test/test-utils';

it('renders and submits', () => {
renderWithRouter(<MyComponent />);
});

it('renders at /contact', () => {
renderWithRouter(<Page />, { initialEntries: ['/contact'] });
});
```

For full route trees (loaders, nested layouts), use `createTestRouter` or pass `routes` into `renderWithRouter`.

## Integration Tests

Wrap route components with the same providers as the app (e.g. TodoProvider), then assert user flows:

```tsx
import { renderWithRouter } from '../../test/test-utils';
import { TodoProvider } from '../../lib/todo-context';
import Home from '../home';

renderWithRouter(
<TodoProvider>
<Home />
</TodoProvider>
);
// fire events, assert DOM/state
```

## Bun Config (reference)

- **preload:** `test/setup.ts` via `bunfig.toml`
- **jsdom:** initialized in `test/setup.ts` (globals + `@testing-library/jest-dom`)
- **testTimeout:** Bun default is `5000`; adjust with `bun test --timeout <ms>` when needed

## Commands

- `bun run test` – run tests
- `bun run test:watch` – watch mode
- `bun run test:run` / `bun run test:ci` – single run (CI)

## Best Practices

- Prefer `getByRole`, `getByLabelText`, `getByPlaceholderText` over brittle selectors
- Use `jest.fn()` from `bun:test` for callbacks; assert calls and args
- Hoist repeated regex/selectors to describe scope to satisfy lint rules
- Keep tests focused; use multiple `it` blocks instead of one large test
- For forms: test validation, submit behavior, and error display (see lambda-curry-forms rules for FormError)
85 changes: 85 additions & 0 deletions .cursor/rules/ai-rules-generated-ui-components.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
description: UI component conventions and shadcn/ui patterns
globs: packages/ui/**/*.tsx, packages/ui/**/*.ts, apps/**/app/**/*.tsx
alwaysApply: true
---

# UI Component Rules

## Component Structure
- Use forwardRef for components that need ref forwarding
- Implement proper TypeScript interfaces
- Use class-variance-authority for variant-based styling

## shadcn/ui Patterns
```tsx
// Component example
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@todo-starter/utils';
import { Slot } from '@radix-ui/react-slot';

const buttonVariants = cva(
'base-classes',
{
variants: {
variant: {
default: 'default-classes',
destructive: 'destructive-classes'
},
size: {
default: 'default-size',
sm: 'small-size'
}
},
defaultVariants: {
variant: 'default',
size: 'default'
}
}
);

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : 'button';
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
}
);
Button.displayName = 'Button';
```

## Styling Guidelines
- Use Tailwind CSS classes for styling
- Leverage CSS variables for theming
- Use cn() utility for conditional classes
- Follow shadcn/ui color and spacing conventions

## Accessibility
- Include proper ARIA attributes
- Ensure keyboard navigation works
- Use semantic HTML elements
- Test with screen readers

## Component Organization
- Keep components in `packages/ui/src/components/ui/`
- Export all components from main index file
- Group related components together
- Use consistent naming conventions

## Best Practices
- Prefer composition over complex props
- Keep components focused and reusable
- Document component APIs with TypeScript
- Test components in isolation
51 changes: 0 additions & 51 deletions .cursorrules/00-project-context.mdc

This file was deleted.

Loading