4.9 KiB
API-First Architecture – Canonical Rules (SkinBase)
This document defines how Copilot must generate API-first code. It applies to Artworks and all future modules. If generated code conflicts with this file, this file wins.
1. What “API-First” Means (MANDATORY)
API-first means:
- Business logic lives in Services
- Controllers are thin adapters
- Output is defined by API Resources
- Web (Blade), API, Admin all use the same services
- No duplicated logic between web & API
Copilot MUST assume:
- Web UI exists (Blade / SSR)
- API exists (JSON)
- Both consume the same backend logic
2. Layered Architecture (STRICT)
Copilot MUST generate code following this flow:
Request
→ Controller (Web or API)
→ Service (business rules)
→ Models / Queries
→ Resource (output shape)
Forbidden shortcuts
❌ Controller → Model directly ❌ Controller → DB query ❌ Resource contains logic ❌ Model contains business logic
3. Directory Structure (REFERENCE)
Copilot MUST follow this structure:
app/
├── Http/
│ ├── Controllers/
│ │ ├── Api/
│ │ │ └── ArtworkController.php
│ │ └── Web/
│ │ └── ArtworkController.php
│ │
│ ├── Resources/
│ │ ├── ArtworkResource.php
│ │ ├── ArtworkListResource.php
│ │ └── CategoryResource.php
│
├── Services/
│ ├── ArtworkService.php
│ ├── ArtworkStatsService.php
│ └── CategoryService.php
│
├── Policies/
│ └── ArtworkPolicy.php
│
├── Models/
│ └── Artwork.php
4. Services Layer (CORE)
4.1 ArtworkService (MANDATORY)
Copilot MUST generate an ArtworkService that handles:
- Fetch public artwork by slug
- Fetch artworks by category
- Apply visibility rules
- Apply soft delete rules
- Throw domain-appropriate exceptions
Example responsibilities (NOT code):
getPublicArtworkBySlug(string $slug)getCategoryArtworks(Category $category)getLatestArtworks(int $limit)
Rules
- Services MUST NOT return JSON
- Services MUST return models or collections
- Services MUST enforce visibility rules
5. Controllers (ADAPTERS ONLY)
5.1 API Controllers
Location:
app/Http/Controllers/Api/
Rules:
- Return API Resources only
- Never return models directly
- No business logic
- Stateless
Example:
return new ArtworkResource(
$this->service->getPublicArtworkBySlug($slug)
);
5.2 Web Controllers
Location:
app/Http/Controllers/Web/
Rules:
- Use same services as API
- Prepare data for Blade
- No duplication of logic
- SEO handled here (meta tags, schema)
Example:
return view('artworks.show', [
'artwork' => new ArtworkResource($artwork),
]);
6. API Resources (OUTPUT CONTRACT)
Rules
Copilot MUST:
- Use Laravel
JsonResource - Define explicit fields
- Never expose internal fields accidentally
- Avoid N+1 queries
- Include relations conditionally
ArtworkResource MUST include:
- slug
- title
- description
- dimensions
- categories
- URLs (canonical)
ArtworkListResource MUST:
- Be lightweight
- Exclude heavy relations
- Exclude stats unless requested
7. Routes (SEO-Safe)
API routes
Location:
routes/api.php
Rules:
- Stateless
- Slug-based
- Versionable (
/api/v1/...)
Example:
GET /api/v1/artworks/{slug}
GET /api/v1/categories/{slug}/artworks
Web routes
Location:
routes/web.php
Rules:
- Slug-based
- No IDs
- SEO-friendly
- SSR output
8. Stats Handling (High Load Rule)
Copilot MUST:
- Use
ArtworkStatsService - Increment stats via Jobs
- Never mutate counters inline
- Assume Redis may be present
Forbidden:
❌ $artwork->increment('views')
❌ Updating stats inside controllers
9. Caching Rules
Copilot SHOULD assume:
- Redis is available
- Cache keys are service-level
- Resources are cacheable
Examples:
artwork:{slug}category:{slug}:artworks
Cache invalidation:
- On update
- On delete
- On restore
10. Error Handling Rules
Copilot MUST:
- Return 404 for missing public content
- Return 410 or 301 for soft-deleted content (if requested)
- Never expose private content via API
11. Testing Philosophy
Copilot MUST generate tests that:
- Hit API endpoints
- Validate JSON structure
- Test visibility & approval
- Do NOT test Blade HTML
12. Forbidden Patterns (ABSOLUTE)
❌ Controllers with logic ❌ Models with business rules ❌ Duplicate logic between API & Web ❌ Direct DB queries in controllers ❌ Different rules for API vs Web
13. Final Instruction (NON-NEGOTIABLE)
API is the primary contract. Web UI, Admin UI, Mobile apps are clients.
Copilot MUST always ask:
“Can this logic live in a service?”
If yes → put it there.