Back to skills
SkillHub ClubShip Full StackFull StackBackend

backend

Imported from https://github.com/tidemann/st44-home.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
0
Hot score
74
Updated
March 20, 2026
Overall rating
C2.5
Composite score
2.5
Best-practice grade
B81.2

Install command

npx @skill-hub/cli install tidemann-st44-home-backend

Repository

tidemann/st44-home

Skill path: .claude/skills/backend

Imported from https://github.com/tidemann/st44-home.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack, Backend.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: tidemann.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install backend into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/tidemann/st44-home before adding backend to shared team environments
  • Use backend for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: backend
description: Fastify Node.js expert for .ts API files, REST endpoints, routes, middleware, handlers, PostgreSQL, SQL queries, pg.Pool, Zod schemas, validation, authentication, authorization, async/await, database connections, camelCase, type safety, error handling
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
---

# Backend Development Skill

Expert in Fastify backend API development following project conventions.

## When to Use This Skill

Use this skill when:

- Implementing API endpoints
- Creating or modifying business logic
- Working with middleware or authentication
- Database query implementation
- Any backend-related task

## CRITICAL: camelCase Everywhere (UNBREAKABLE RULE)

**ALL code, schemas, database columns, API requests/responses MUST use camelCase.**

### ✅ CORRECT

```typescript
interface User {
  id: string;
  firstName: string;      // camelCase
  lastName: string;
  createdAt: Date;        // camelCase
}

// Database queries - use camelCase columns
SELECT id, "firstName", "createdAt" FROM users;
```

### ❌ FORBIDDEN

```typescript
interface User {
  first_name: string; // NO snake_case!
  last_name: string; // NO snake_case!
}
```

**No Exceptions.** This applies to ALL new code.

## Schema-Query Alignment (CRITICAL)

**Before ANY endpoint is complete:**

### 1. Verify Schema Matches Query

```typescript
// ❌ WRONG - Schema requires field not in SELECT
const HouseholdSchema = z.object({
  id: z.string(),
  name: z.string(),
  adminUserId: z.string(), // ← Required but missing from query!
});

const result = await pool.query(
  'SELECT id, name FROM households', // ← Missing adminUserId
);

// ✅ CORRECT - Schema matches query
const HouseholdSchema = z.object({
  id: z.string(),
  name: z.string(),
  adminUserId: z.string().optional(), // ← Optional or included in query
});

const result = await pool.query('SELECT id, name, "adminUserId" FROM households');
```

### 2. Check Database Schema First

**ALWAYS read the database schema before writing Zod schemas:**

```bash
# Check what columns exist and if they're nullable
cat docker/postgres/init.sql | grep -A 20 "CREATE TABLE users"
```

**Make schema fields optional if:**

- Column is nullable in database
- Column doesn't exist in table yet
- SELECT query doesn't include the column

## Mandatory Local Testing (CRITICAL)

**BEFORE EVERY PUSH, run ALL checks from apps/backend:**

```bash
cd apps/backend

# 1. Type check
npm run type-check

# 2. Format check
npm run format:check

# 3. Tests
npm run test

# 4. Build
npm run build
```

**If ANY check fails:**

1. STOP - Do not proceed
2. Fix the issue
3. Re-run ALL checks
4. Only push when ALL pass

**Why:** CI feedback loop takes 3-5 minutes vs local checks in <1 minute. Type errors in production cause runtime failures.

## API Development Patterns

### Route Handler Template

```typescript
import { FastifyRequest, FastifyReply } from 'fastify';
import { z } from 'zod';
import { pool } from '../db';

// Define schemas with camelCase
const RequestSchema = z.object({
  userId: z.string(),
  taskName: z.string(),
});

const ResponseSchema = z.object({
  id: z.string(),
  taskName: z.string(),
  createdAt: z.string(),
});

export async function createTask(
  request: FastifyRequest<{ Body: z.infer<typeof RequestSchema> }>,
  reply: FastifyReply,
) {
  // Validate request
  const body = RequestSchema.parse(request.body);

  // Database query with camelCase columns
  const result = await pool.query(
    `INSERT INTO tasks ("userId", "taskName", "createdAt")
     VALUES ($1, $2, NOW())
     RETURNING id, "taskName", "createdAt"`,
    [body.userId, body.taskName],
  );

  // Validate response
  const task = ResponseSchema.parse(result.rows[0]);

  return reply.code(201).send(task);
}
```

### Error Handling

```typescript
export async function getUser(
  request: FastifyRequest<{ Params: { id: string } }>,
  reply: FastifyReply,
) {
  try {
    const result = await pool.query('SELECT id, "firstName", email FROM users WHERE id = $1', [
      request.params.id,
    ]);

    if (result.rows.length === 0) {
      return reply.code(404).send({ error: 'User not found' });
    }

    const user = UserSchema.parse(result.rows[0]);
    return reply.send(user);
  } catch (error) {
    if (error instanceof z.ZodError) {
      return reply.code(500).send({ error: 'Data validation failed' });
    }
    throw error;
  }
}
```

## Database Query Best Practices

### Always Use Parameterized Queries

```typescript
// ✅ CORRECT - Prevents SQL injection
await pool.query('SELECT * FROM users WHERE id = $1', [userId]);

// ❌ WRONG - SQL injection vulnerability
await pool.query(`SELECT * FROM users WHERE id = '${userId}'`);
```

### Use camelCase Column Aliases

```typescript
// When querying snake_case columns (legacy), alias to camelCase
await pool.query(`
  SELECT
    id,
    first_name as "firstName",
    last_name as "lastName",
    created_at as "createdAt"
  FROM users
`);

// Or better: use camelCase columns in database
await pool.query(`
  SELECT id, "firstName", "lastName", "createdAt"
  FROM users
`);
```

## Validation Checklist

Before completing ANY endpoint:

- [ ] Read database schema (init.sql or SCHEMA.md)
- [ ] Compare schema fields with SELECT columns
- [ ] All required fields in Zod schema are in SELECT
- [ ] Optional fields marked as `.optional()` if nullable or not in table
- [ ] Test endpoint locally (no serialization errors)
- [ ] Run type-check, format-check, tests, build
- [ ] All checks pass

## Common Mistakes That Cause Runtime Errors

### Mistake 1: Required field not in database

```typescript
// ❌ Schema says required, but column doesn't exist
adminUserId: z.string();

// ✅ Check database first, make optional if needed
adminUserId: z.string().optional();
```

### Mistake 2: Nullable field required

```typescript
// ❌ Database column is nullable, schema requires it
description: z.string();

// ✅ Make it optional
description: z.string().optional();
```

### Mistake 3: SELECT doesn't match schema

```typescript
// ❌ Schema has fields not in SELECT
const schema = z.object({
  id: z.string(),
  name: z.string(),
  email: z.string(), // ← Not in SELECT!
});

await pool.query('SELECT id, name FROM users');

// ✅ Add to SELECT or make optional
await pool.query('SELECT id, name, email FROM users');
```

## Workflow

1. **Read** the optimized agent spec: `.claude/agents/backend.md`
2. **Check** database schema for column names and types
3. **Implement** endpoint with camelCase throughout
4. **Validate** schema-query alignment
5. **Test** locally with ALL checks (type-check, format, tests, build)
6. **Test** endpoint manually (verify no errors)
7. **Only then** commit and push

## Reference Files

For detailed patterns and examples:

- `.claude/agents/backend.md` - Complete agent specification
- `apps/backend/AGENTS.md` - Project-specific patterns (if exists)
- `CLAUDE.md` - Project-wide conventions
- `docker/postgres/init.sql` - Database schema

## Success Criteria

Before marking work complete:

- [ ] All local checks pass (type-check, format, tests, build)
- [ ] Endpoint tested locally (no errors)
- [ ] camelCase naming throughout
- [ ] Schema-query alignment verified
- [ ] Parameterized queries used
- [ ] Error handling implemented
backend | SkillHub