Imported from joangoal8/jgoal-lab-frontend (
AGENTS.md). Install upstream withnpx skills add joangoal8/jgoal-lab-frontend. Copyright stays with the author.
AGENTS.md — AI Agent Guidelines for Nestra Backoffice
This document defines how AI agents (Claude Code, Cursor, etc.) should work with this frontend codebase. It covers context engineering for the agent itself, codebase conventions, and the frontend patterns that make Nestra an AI-native product.
Scope boundary: This is a frontend repository. Backend AI pipelines, extraction prompts, and document processing logic live in
nestra-ai-core. This file does NOT cover how the backend works — only what the frontend consumes and how to build on top of it.
1. Context Engineering for the Agent
1.1 Understand Before You Build
Before writing any code, the agent must understand the existing patterns. This codebase is intentionally consistent — deviating from patterns creates maintenance debt.
Required reads before any feature work:
CLAUDE.md— project overview, stack, conventions, API endpoints- The relevant
types/*.ts— understand the data contracts - The relevant
stores/*.ts— understand state management patterns - The relevant
components/{feature}/— understand UI patterns messages/en.json— understand the i18n namespace structure
1.2 Context Hierarchy for This Repo
CLAUDE.md (project-level rules, always loaded)
└─ AGENTS.md (agent-specific guidelines, this file)
└─ types/*.ts (data contracts — what the BE sends, what the FE renders)
└─ Feature files (stores, components, API functions)
Key principle: The type definitions are the contract between frontend and backend. When the BE response changes, update types/api.ts first — everything else follows from there.
1.3 What the Agent Should NOT Do
- Don't assume backend behavior — the BE is a separate system. If a field is missing or changed, ask or check the API response, don't guess.
- Don't create abstractions prematurely — three similar lines of code is better than a premature abstraction.
- Don't mix concerns — stores handle state/async, components handle rendering, API functions handle HTTP. Keep them separated.
- Don't create
.claude/branches — the user manages branching strategy directly. - Don't commit unless asked — and when asked, write commit messages that explain why, not what.
2. API Contract Awareness
The frontend consumes structured data from the BE. The agent must understand these contracts without needing to know how the BE produces them.
2.1 BE Response Fields the Frontend Must Handle
Processing statuses — The BE tracks status per document type independently:
type DocumentTypeStatus = "pending" | "in_progress" | "completed" | "failed" | "not_applicable";
Dual data models — The BE returns two representations of the same data:
parameters— Legacy structure (will eventually be deprecated)urban_params— New consolidated structure
Frontend rule: Display both when present. Never hide one in favor of the other — the consolidation happens on the BE side, not here.
2.2 Defensive Typing
The BE evolves independently. The frontend must be resilient:
- Use optional fields (
?) for anything that might not be present in all responses - Use
DocumentId = number | string— IDs are migrating from integers to UUIDs - Default unknown statuses to a safe state (
"ongoing"not"empty") — showing the view is safer than showing the upload form - Never fail silently — if the API returns unexpected data, surface it rather than hiding it
2.3 Endpoint Strategy Pattern
AI analysis endpoints vary per document type. We use a strategy pattern in lib/api/normatives.ts:
const AI_ANALYSIS_ENDPOINTS: Record<DocumentType, (id: number) => string> = {
pgou: (id) => `/ai/normatives/${id}/urban-qualification-analysis/pgou`,
urban_plan: (id) => `/ai/municipality-urban-plans/${id}/urban-plan-qualification-analysis`,
// Add new types here — no other code changes needed
};
Why a strategy pattern: Each document type has a different AI pipeline endpoint on the BE. This keeps the frontend decoupled from pipeline internals — we just know which URL to call.
3. Frontend Patterns for AI-Native UX
3.1 Status-Driven UI
The UI adapts to the processing status of each section. This is the core AI-native UX pattern:
| Status | Header Badge | Expanded Content |
|---|---|---|
pending (has docs) |
Ready to analyze |
"Analyze with AI" CTA button |
pending (0 docs) |
No documents (gray) |
Muted, non-interactive |
in_progress |
Analyzing... + spinner |
Processing description, non-interactive |
completed |
Completed ✓ (green) |
Extracted results displayed |
failed |
Failed (red) |
"Retry" button + error context |
not_applicable |
Hidden or very muted | No action available |
3.2 Progressive Disclosure
- Collapsed sections: Status badge only (informational, scannable)
- Expanded sections: Full action area (CTA buttons, document list, error details)
- Detail views: Complete extracted data with source references
Why: Users managing 5+ document sections need to scan status at a glance, then drill into the section that needs attention.
3.3 Source Reference Display
When rendering AI-extracted data, always show provenance when available:
interface SourceRef {
page?: number | null;
article?: string | null;
file?: string | null;
exact_quote?: string | null;
}
Display rules:
- If
source_refexists withexact_quote→ show as grounded (high confidence) - If
source_refexists withoutexact_quote→ show reference only - If
source_refis null/missing → visually indicate lower confidence (e.g., muted styling)
3.4 Optimistic Refresh Pattern
After triggering an AI pipeline action:
- Show immediate feedback (button state change, loading indicator)
- Call the API endpoint
- Re-fetch normative data to pick up the new status
- User can navigate away — status persists server-side
4. Codebase Conventions (Agent Checklist)
Before starting any feature:
- Read the relevant existing types in
types/ - Read the relevant existing store in
stores/ - Read similar existing components for pattern reference
While implementing:
- Types first — define interfaces before writing components
- One store per feature domain — colocate actions with state
- All user-facing strings in
messages/{en,es}.json - Use existing UI primitives (
Card,Badge,Button,CollapsibleSection, etc.) - Use design tokens for styling (never raw colors like
text-gray-500— usetext-text-tertiary)
Before finishing:
- Run
pnpm build— TypeScript compilation is the primary validation gate - Verify both
en.jsonandes.jsonare updated - Check that new components follow
"use client"directive pattern - Ensure no hardcoded strings in components
Architectural decisions:
- State the tradeoff when making a choice (e.g., "Using
DocumentId = number | stringadds type complexity but avoids a breaking migration") - Prefer editing existing files over creating new ones
- Don't add dependencies without discussing the tradeoff
5. Domain Context
The agent needs enough domain knowledge to make good UI decisions, without needing to understand the backend internals.
5.1 Document Types
| Type | What it is | Frontend behavior |
|---|---|---|
pgou |
General Urban Plan (Plan General) | Required for upload. Single file. Primary normative. |
urban_plan |
Urban planning maps/schemas (Planos) | Required for upload. Multiple files. |
partial_plan |
Partial development plans (Planes Parciales) | Optional. Sector-specific supplements. |
heritage |
Heritage protection documents (Patrimonio) | Optional. Constraint overlay. |
other |
Supporting documents (Otros) | Optional. No AI processing status tracked. |
5.2 Key Domain Concepts
- Municipality (
municipio): The geographic unit. All normatives, qualifications, and plots belong to a municipality. - Urban Qualification (
calificación urbanística): A zone code (e.g.,EO-2) with building parameters — what you can build, how tall, setbacks, land uses. - Plot (
parcela): A specific land parcel identified by cadastral reference. Linked to a qualification zone. - Normative (
normativa): The set of uploaded planning documents for a municipality, with their processing status.
5.3 Terminology Mapping
| Spanish (source docs) | English (UI) | Code reference |
|---|---|---|
| Edificabilidad | Buildability | buildability_rules, buildability_index |
| Retranqueo | Setback | front_setback, side_setback |
| Ocupación | Occupancy | max_above_ground_occupancy |
| Altura reguladora | Regulatory height | max_regulatory_height |
| Calificación urbanística | Urban qualification | UrbanQualification type |
| Referencia catastral | Cadastral reference | ref_catastral |