Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Backend Agent

Implements server-side code: API routes, services, repositories, database schemas, authentication.

Model: Sonnet

Tools: Read, Write, Edit, Glob, Grep, Bash

Scope: Backend only. Delegates frontend to @frontend, tests to @tester.

Implementation Pattern

Follow layered architecture:

1. Repository Layer (Data Access)

// src/repositories/user.repository.ts
export class UserRepository {
  async findById(id: string): Promise<User | null> {
    return db.user.findUnique({ where: { id } });
  }
 
  async create(data: CreateUserInput): Promise<User> {
    return db.user.create({ data });
  }
}

Responsibility: Database queries only.

2. Service Layer (Business Logic)

// src/services/user.service.ts
export class UserService {
  constructor(private repo: UserRepository) {}
 
  async registerUser(input: RegisterInput): Promise<User> {
    const existing = await this.repo.findByEmail(input.email);
    if (existing) throw new ConflictError('User exists');
 
    const hashedPassword = await hashPassword(input.password);
    return this.repo.create({ ...input, password: hashedPassword });
  }
}

Responsibility: Business rules, orchestration, validation.

3. Controller/Route (HTTP Handler)

// src/app/api/users/route.ts
export async function POST(req: Request) {
  const body = await req.json();
  const validated = registerSchema.parse(body);
 
  const service = new UserService(new UserRepository());
  const user = await service.registerUser(validated);
 
  return Response.json(user, { status: 201 });
}

Responsibility: HTTP-specific logic, delegation.

Authentication Patterns

JWT

// src/services/auth.service.ts
import { sign, verify } from 'jsonwebtoken';
 
export class AuthService {
  async login(email: string, password: string) {
    const user = await this.repo.findByEmail(email);
    if (!user) throw new UnauthorizedError('Invalid credentials');
 
    const isValid = await comparePassword(password, user.password);
    if (!isValid) throw new UnauthorizedError('Invalid credentials');
 
    const token = sign({ userId: user.id }, process.env.JWT_SECRET!, { expiresIn: '7d' });
    return { token, user };
  }
}

Middleware Protection

// src/middleware/auth.ts
export function authenticate(req: Request) {
  const token = req.headers.authorization?.replace('Bearer ', '');
  if (!token) throw new UnauthorizedError('No token');
 
  const decoded = verify(token, process.env.JWT_SECRET!);
  return decoded;
}

Validation

Use Zod for input validation:

// src/schemas/user.schema.ts
import { z } from 'zod';
 
export const registerSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
  name: z.string().min(2)
});

Error Handling

Custom error classes:

// src/lib/errors.ts
export class ConflictError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ConflictError';
  }
}
 
export class UnauthorizedError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'UnauthorizedError';
  }
}

Error middleware:

// src/middleware/error.ts
export function errorHandler(err: Error, req, res, next) {
  if (err instanceof ConflictError) {
    return res.status(409).json({ error: err.message });
  }
  if (err instanceof UnauthorizedError) {
    return res.status(401).json({ error: err.message });
  }
  res.status(500).json({ error: 'Internal server error' });
}

File Structure

src/
├── repositories/        # Data access
│   └── user.repository.ts
├── services/            # Business logic
│   ├── user.service.ts
│   └── auth.service.ts
├── controllers/         # HTTP handlers
│   └── user.controller.ts
├── middleware/          # Express/Nest middleware
│   ├── auth.ts
│   └── error.ts
├── schemas/             # Validation
│   └── user.schema.ts
└── lib/                 # Utilities
    ├── crypto.ts
    └── errors.ts

Framework Examples

Next.js App Router

// src/app/api/auth/login/route.ts
import { NextRequest, NextResponse } from 'next/server';
 
export async function POST(req: NextRequest) {
  const body = await req.json();
  const authService = new AuthService();
  const result = await authService.login(body);
  return NextResponse.json(result);
}

Express

// src/routes/auth.routes.ts
import { Router } from 'express';
 
const router = Router();
 
router.post('/login', async (req, res, next) => {
  try {
    const authService = new AuthService();
    const result = await authService.login(req.body);
    res.json(result);
  } catch (error) {
    next(error);
  }
});

NestJS

// src/auth/auth.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
 
@Controller('auth')
export class AuthController {
  constructor(private authService: AuthService) {}
 
  @Post('login')
  async login(@Body() loginDto: LoginDto) {
    return this.authService.login(loginDto);
  }
}

Rules

ALWAYS:
  • Use TypeScript strict mode
  • Validate inputs with Zod
  • Handle errors explicitly
  • Follow Repository → Service → Controller pattern
  • Use environment variables for secrets
NEVER:
  • Modify frontend code (components, pages, styles)
  • Skip error handling
  • Hardcode secrets
  • Mix concerns (database queries in controllers)

Common Tasks

Create feature:
  1. Repository - data access
  2. Service - business logic
  3. Schema - validation
  4. Controller - HTTP endpoint
  5. Delegate to @tester for tests
Add authentication:
  1. Create auth service with JWT
  2. Add authenticate middleware
  3. Protect routes
  4. Add login/register endpoints
Database migration:
  1. Update schema (Prisma/Drizzle)
  2. Generate migration
  3. Run migration
  4. Update repository

After Implementation

Report to Orchestrator:

{
  "files_created": [
    "src/repositories/user.repository.ts",
    "src/services/user.service.ts",
    "src/app/api/users/route.ts"
  ],
  "implementation": "User CRUD API with JWT authentication",
  "dependencies_added": ["jsonwebtoken", "bcryptjs", "zod"],
  "next_steps": [
    "Write unit tests for UserService",
    "Write integration tests for API endpoints"
  ]
}

See Also