This file is guidance for agentic coding tools working in this repo.
- App name: Library (private personal media library)
- Frontend: React + TanStack Router (file-based routes in
src/routes) - Build tool: Vite (TanStack Start plugin) + Nitro
- Backend: Convex self-hosted + TanStack Start server routes for metadata/internal bridges
- Styling: Tailwind v4 + shadcn/ui
- Tests: Vitest
- Lint/format: Biome
- Package manager/runtime: Bun
⚠️ Multi-usuario: la app ya no es de uso individual — hay varias personas usándola. Tener mucho cuidado con cambios que puedan romper funcionalidad existente o perder datos. Privilegiar estabilidad, migraciones seguras y datos de prueba antes de tocar schema o eliminar columnas/tablas.
- Discord bot repo:
~/dev/alfred. - When the task involves Discord notifications or bot behavior, you can and should review/edit that repo as part of the implementation.
- Treat
~/dev/alfredas the canonical bot runtime for notification delivery and operational bot logic when applicable.
- You may run
bun run devwhen useful for verification. First check whether a server is already running and choose a non-conflicting port if needed. Dev uses the same Convex deployment/data as production, so never mutate real user data outside explicit user requests or E2E-prefixed test flows.
# install
bun install
# dev
bun run dev
bun run dev:web
# build
bun run build
bun run preview
# convex
bun run convex:dev
bun run convex:push
bun run convex:deploy
# lint/format (Biome; tabs + double quotes)
bun run lint
bun run format
bun run check
# tests (Vitest)
bun run test
bun run test -- src/path/to/my.test.ts
bun run test -- -t "my test name"
bunx vitest
# browser verification (Playwright)
bun run test:e2e:install
bun run test:e2e
bun run test:e2e:headed
bun run test:e2e:debugsrc/routes/*: TanStack Router file-based routes (most routes setssr: false).convex/*: Convex schema, auth, functions and crons.src/components/*: App components.src/components/ui/*: shadcn/ui primitives.src/lib/*: app types, metadata providers and mapping helpers.src/lib/server/*: server-side helpers for TanStack Start routes.
Generated files (do not edit): src/routeTree.gen.ts, convex/_generated/*.
- Local config lives in
.env.local(never commit secrets). - Convex:
VITE_CONVEX_URLCONVEX_SELF_HOSTED_URLCONVEX_SELF_HOSTED_ADMIN_KEYCONVEX_SITE_URL
- App:
VITE_SITE_URLOBSIDIAN_VAULT_PATHREADING_BOOKS_PATHREADING_INTEGRATION_OWNER_IDLIBRARY_MCP_SECRETTMDB_API_KEY
ALFRED_NOTIFY_SECRETALFRED_NOTIFY_URLALFRED_NOTIFY_USER_EMAIL(usuario propietario cuyas obras se notifican)- E2E browser tests:
E2E_TEST_EMAILE2E_TEST_PASSWORDE2E_BASE_URL(defaults tohttp://localhost:3100)
- Use Biome; do not hand-format large sections.
- Indentation: tabs.
- Quotes: double quotes.
- Keep diffs minimal and consistent with surrounding code.
- Prefer path alias
@/*for app imports (configured intsconfig.json). - Use type-only imports when possible:
import type { ... } from .... - Let Biome organize imports; avoid manual reordering unless necessary.
- Prefer explicit unions for enums (see
src/lib/types.ts). - Use
interfacefor object shapes shared across modules;typefor unions. - Avoid
any; if truly necessary, scope it narrowly and add context. - Keep DB rows separated from UI types (see
src/lib/obras.tsandsrc/lib/server/obras.ts).
- Components: PascalCase names, exported as named exports when reusable.
- Files: kebab-case for components (existing pattern:
add-obra-dialog.tsx). - Routes: keep data fetching in the route component; pass typed data to UI.
- Copy/labels: product language should be Spanish (per current direction); internal enum values may remain English, but UI should map to Spanish labels.
- Existing obra edits auto-save: do not add global "Guardar" buttons for persisted fields on existing obras. Use debounced saves for text fields, immediate saves for discrete controls, and always show save/error state.
- Creation, destructive actions, external search, and explicit external apply flows remain user-confirmed actions.
- Use Playwright for browser-level feature verification after UI/user-flow changes.
- Default E2E URL is
http://localhost:3100, so verification does not accidentally reuse an unrelated app on port 3000. Override withE2E_BASE_URLonly when intentionally targeting another running instance. - Authenticated E2E flows require a dedicated test account via
E2E_TEST_EMAILandE2E_TEST_PASSWORD; never use a personal account. - E2E-created records must keep the
[E2E ...]prefix and be cleaned up from the UI flow when possible.
When the user describes a feature and asks for autonomous execution:
- Do the intake carefully before automation:
- Explore the repo first; do not ask questions that can be answered from code, docs, config, tests, or existing UI.
- For medium/large features, ambiguous product behavior, user-facing
workflow changes, data model changes, or anything that will be hard to
unwind after an automatic PR+merge, use
grill-meto stress-test the plan one decision at a time before implementation. - For small bug fixes, copy tweaks, narrow test fixes, mechanical refactors,
or clearly specified changes, skip
grill-meand clarify only product-impacting ambiguity. - When using
grill-me, ask one question at a time, give a recommended answer, and stop grilling once goal, scope, non-goals, acceptance criteria, risks, and verification are clear enough to implement autonomously.
- Create or use a feature branch. If on
main, createcodex/{feature-slug}. - Implement with subagents when scopes can be separated cleanly.
- Verify with:
bun run checkbun run testbun run test:e2e
- Use Playwright/browser verification for user-facing flows.
- Commit atomically and avoid staging unrelated user changes.
- Push and open a draft PR automatically.
- Spawn an independent reviewer agent; it must not be the implementation thread.
- Fix blocking and should-fix review findings automatically when the fix does not change product intent or data semantics.
- Update the PR body with validation status, browser verification notes, and known blockers.
Loop safety rules:
- Never use personal accounts for E2E.
- Never mutate real user data outside an E2E-prefixed dedicated test account.
- Never mark PRs ready-for-review without explicit user instruction.
- Stop only for real blockers: missing credentials, risky data mutation, non-trivial git conflicts, inaccessible CI logs, or product ambiguity that changes visible behavior.
- Default screenshots policy: rely on Playwright artifacts and summarize what
was verified in the PR. Do not commit
test-results/orplaywright-report/.
- Prefer domain language in UI: "Obra", "Biblioteca", "En progreso", etc.
- Keep storage enums stable (English) unless you plan a migration.
- Component files: kebab-case; exported components: PascalCase.
- New routes belong in
src/routes. - Use
createFileRoute(...)({ ssr: false, component: ... })unless SSR is intentionally required. - Prefer
<Link>for navigation and route params (seesrc/routes/obra/$obraId.tsx).
- Validate Convex/API inputs before touching the DB.
- Use indexes where needed and keep them in
convex/schema.ts. - Use
Date.now()for app timestamps; keepcreatedAtimmutable and updateupdatedAt. - Error handling: throw
new Error("...")with a clear, user-facing message. - Keep Convex functions small and deterministic; isolate external fetches in actions and scheduled work in
convex/crons.ts.
Access control (important):
- Do not ship new write endpoints without an auth check.
- All DB reads/writes that touch user data must scope by the authenticated user.
Data model notes:
- Auth state lives in Convex Auth tables.
- In the UI, map Convex-backed payloads to app types via
obraFromDoc(src/lib/obras.ts).
- The goal is a private app; do not leave write operations unauthenticated.
- Convex Auth protects user-facing reads/writes.
- Protect server routes and API handlers, and keep login gates in UI.
- Never commit secrets; use
.env.localfor local config.
- Prefer adding/adjusting small components over large refactors.
- Avoid touching auto-generated output in
.output/. - Keep UI text changes consistent (Spanish) and avoid mixing languages.
This repo includes .cursorrules. Key points:
- Use the latest shadcn/ui CLI when adding components:
pnpm dlx shadcn@latest add button- Prefer explicit enums/unions for stable storage values.
- Keep Convex schema as the source of truth in
convex/schema.ts. - Deploy Convex schema/functions with
bun run convex:deploy. - The
.cursorrulesfile also contains schema guidance; use it as reference for unions, optional fields, and indexes.