Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/database-integration-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@thecodepace/fastify-skills": minor
---

Add database integration, migrations, test containers, clean architecture, and unit testing rules

- `database-integration.md`: Register a `pg` pool as a Fastify plugin; use `@nearform/sql` for injection-safe queries with tagged template literals
- `database-migrations.md`: Manage schema changes with Postgrator (plain SQL files); run migrations before `server.listen()`
- `test-containers.md`: Spin up real Postgres containers with Testcontainers for isolated integration tests
- `clean-architecture.md`: Pure service-layer functions + thin route handlers with explicit dependency injection
- `unit-testing.md`: Unit-test service functions in isolation using mock database stubs (vitest and node:test examples)
107 changes: 78 additions & 29 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ This file provides guidance to AI coding agents (Claude Code, Cursor, Copilot, e

A collection of skills for Claude.ai, Claude Code, Copilot, Cursor and all the AI coding agents enable to run Skill for working with fastify. Skills are packaged instructions and scripts that extend AI capabilities.

## Package Manager

This repository uses **pnpm** (v10.30.1). Always use `pnpm` instead of `npm` or `yarn`.

```bash
pnpm install # install dependencies
pnpm run lint # lint all files with ESLint
pnpm run validate # validate all rule files against the rule schema
```

## Creating a New Skill

### Directory Structure
Expand All @@ -14,16 +24,16 @@ A collection of skills for Claude.ai, Claude Code, Copilot, Cursor and all the A
skills/
{skill-name}/ # kebab-case directory name
SKILL.md # Required: skill definition
scripts/ # Required: executable scripts
{script-name}.sh # Bash scripts (preferred)
rules/ # Required: best-practice rule files
{rule-name}.md # One file per rule topic
{skill-name}.zip # Required: packaged for distribution
```

### Naming Conventions

- **Skill directory**: `kebab-case` (e.g., `fastify-plugin`, `log-monitor`)
- **SKILL.md**: Always uppercase, always this exact filename
- **Scripts**: `kebab-case.sh` (e.g., `deploy.sh`, `fetch-logs.sh`)
- **Rule files**: `kebab-case.md` (e.g., `error-handling.md`, `database-integration.md`)
- **Zip file**: Must match directory name exactly: `{skill-name}.zip`

### SKILL.md Format
Expand All @@ -47,34 +57,67 @@ description:

{Numbered list explaining the skill's workflow}

## Rules

| Rule | File | Impact | Description |
| ---- | ---- | ------ | ----------- |
| ... | ... | ... | ... |

## Usage

```bash
bash /mnt/skills/user/{skill-name}/scripts/{script}.sh [args]
```
{Topic-based guide linking to relevant rule files}

## Recommended Project Structure

{Directory tree showing the recommended layout}

## Present Results to User

{Template for how the agent should format results when presenting to users}

## Reference

{Links to official documentation}
````

**Arguments:**
### Rule File Format

- `arg1` - Description (defaults to X)
Each rule file must follow this format exactly so the `validate-rules` tool can parse it. Files starting with `_` (e.g., `_template.md`) are excluded from validation.

**Examples:**
{Show 2-3 common usage patterns}
````markdown
---
title: Rule Title Here
impact: HIGH
impactDescription: Optional description of impact
tags: tag1, tag2
---

## Output
## Rule Title Here

{Show example output users will see}
Brief explanation of the rule and why it matters.

## Present Results to User
**Incorrect (description of what's wrong):**

{Template for how Claude should format results when presenting to users}
```typescript
// Bad code example here
```

## Troubleshooting
**Correct (description of what's right):**

{Common issues and solutions, especially network/permissions errors}
```typescript
// Good code example here
```

Reference: [Link text](https://example.com)
````

**Key requirements validated by `pnpm run validate`:**

- `title` — required (non-empty)
- `impact` — must be one of: `CRITICAL`, `HIGH`, `MEDIUM-HIGH`, `MEDIUM`, `LOW-MEDIUM`, `LOW`
- `explanation` — required (text before the first example label)
- Examples — at least one `**Incorrect ...:**` label **and** one `**Correct ...:**` label, each followed by a fenced code block. Do **not** use `###` headings as example labels; use bold labels (`**...**`) instead.

### Best Practices for Context Efficiency

Skills are loaded on-demand — only the skill name and description are loaded at startup. The full `SKILL.md` loads into context only when the agent decides the skill is relevant. To minimize context usage:
Expand All @@ -85,23 +128,32 @@ Skills are loaded on-demand — only the skill name and description are loaded a
- **Prefer scripts over inline code** — script execution doesn't consume context (only output does)
- **File references work one level deep** — link directly from SKILL.md to supporting files

### Script Requirements

- Use `#!/bin/bash` shebang
- Use `set -e` for fail-fast behavior
- Write status messages to stderr: `echo "Message" >&2`
- Write machine-readable output (JSON) to stdout
- Include a cleanup trap for temp files
- Reference the script path as `/mnt/skills/user/{skill-name}/scripts/{script}.sh`

### Creating the Zip Package

After creating or updating a skill:

```bash
cd skills
zip -r {skill-name}.zip {skill-name}/
````
```

### Adding a Changeset

Every change to skill content should be accompanied by a changeset file so that semantic versioning is maintained automatically.

```bash
# Create .changeset/{descriptive-name}.md
```

```markdown
---
"@thecodepace/fastify-skills": minor
---

Short description of the change.
```

Use `patch` for fixes, `minor` for new rules or content additions, `major` for breaking changes.

### End-User Installation

Expand All @@ -118,6 +170,3 @@ Add the skill to project knowledge or paste SKILL.md contents into the conversat

If the skill requires network access, instruct users to add required domains at `claude.ai/settings/capabilities`.

Add the skill to project knowledge or paste SKILL.md contents into the conversation.

If the skill requires network access, instruct users to add required domains at `claude.ai/settings/capabilities`.
36 changes: 22 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,25 @@ Skills follow the [Agent Skills](https://agentskills.io/) format.

### fastify-best-practise

Apply Fastify best practices when creating servers, plugins, routes, schemas, hooks, error handling, testing, and TypeScript integration.

| Rule | Impact | Description |
| ----------------------- | ---------- | -------------------------------------------------------------------------- |
| Create Server | LOW-MEDIUM | Use a `buildServer()` factory function for reusable, testable server setup |
| Create Plugin | LOW-MEDIUM | Encapsulate reusable functionality in plugins with `fastify-plugin` |
| Autoload | HIGH | Automatically load plugins and routes with `@fastify/autoload` |
| Route Best Practices | MEDIUM | Organize routes with plugins/prefixes, async handlers, full route options |
| Schema Validation (Zod) | HIGH | Type-safe validation with Zod + `fastify-type-provider-zod` |
| Encapsulation | HIGH | Proper scope isolation and when to use `fastify-plugin` |
| Error Handling | HIGH | Custom error handlers, `@fastify/error`, `@fastify/sensible`, 404 handling |
| Hooks & Lifecycle | MEDIUM | Request lifecycle hooks for auth, logging, rate limiting |
| Testing | HIGH | Test with `inject()`, buildServer pattern, vitest/node:test |
| TypeScript | MEDIUM | Type providers, module augmentation, typed decorators |
Apply Fastify best practices when creating servers, plugins, routes, schemas, hooks, error handling, testing, database integration, migrations, clean architecture, and TypeScript integration.

| Rule | Impact | Description |
| ----------------------- | ---------- | -------------------------------------------------------------------------------------- |
| Create Server | LOW-MEDIUM | Use a `buildServer()` factory function for reusable, testable server setup |
| Create Plugin | LOW-MEDIUM | Encapsulate reusable functionality in plugins with `fastify-plugin` |
| Autoload | HIGH | Automatically load plugins and routes with `@fastify/autoload` |
| Route Best Practices | MEDIUM | Organize routes with plugins/prefixes, async handlers, full route options |
| Schema Validation (Zod) | HIGH | Type-safe validation with Zod + `fastify-type-provider-zod` |
| Encapsulation | HIGH | Proper scope isolation and when to use `fastify-plugin` |
| Error Handling | HIGH | Custom error handlers, `@fastify/error`, `@fastify/sensible`, 404 handling |
| Hooks & Lifecycle | MEDIUM | Request lifecycle hooks for auth, logging, rate limiting |
| Testing | HIGH | Test with `inject()`, buildServer pattern, vitest/node:test |
| TypeScript | MEDIUM | Type providers, module augmentation, typed decorators |
| Database Integration | HIGH | Register a shared `pg` pool as a Fastify plugin; use `@nearform/sql` for safe queries |
| Database Migrations | HIGH | Manage schema changes with Postgrator; run migrations before `server.listen()` |
| Test Containers | HIGH | Spin up real Postgres containers with Testcontainers for isolated integration tests |
| Clean Architecture | HIGH | Pure service-layer functions + thin route handlers; explicit dependency injection |
| Unit Testing | HIGH | Unit-test service functions in isolation with mock database stubs |

## Installation

Expand All @@ -39,6 +44,9 @@ Skills are automatically available once installed. The agent will use them when
- "Add a users REST API with Zod validation"
- "How should I structure my Fastify app?"
- "Write tests for my Fastify routes"
- "Integrate a PostgreSQL database into my Fastify app"
- "Set up database migrations with Postgrator"
- "How do I separate business logic from route handlers?"

Each skill contains:

Expand Down
39 changes: 31 additions & 8 deletions skills/fastify-best-practise/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: fastify-best-practise
description: Apply Fastify best practices when creating servers, plugins, routes, schemas, hooks, error handling, testing, and TypeScript integration. Use when writing or reviewing Fastify code, setting up a new Fastify project, or asking "How should I structure my Fastify app?"
description: Apply Fastify best practices for servers, plugins, routes, database integration, testing, and architecture patterns. Use when writing or reviewing Fastify code, setting up a new Fastify project, or asking "How should I structure my Fastify app?"
---

# Fastify Best Practices
Expand Down Expand Up @@ -29,6 +29,11 @@ The rules are organized by topic in the `rules/` directory. Each rule follows a
| Hooks & Lifecycle | [hooks-lifecycle.md](rules/hooks-lifecycle.md) | MEDIUM | Request lifecycle hooks for auth, logging, rate limiting |
| Testing | [testing.md](rules/testing.md) | HIGH | Test with `inject()`, buildServer pattern, vitest/node:test |
| TypeScript | [typescript-integration.md](rules/typescript-integration.md) | MEDIUM | Type providers, module augmentation, typed decorators |
| Database Integration | [database-integration.md](rules/database-integration.md) | HIGH | Register a `pg` pool as a Fastify plugin; use `@nearform/sql` for safe queries |
| Database Migrations | [database-migrations.md](rules/database-migrations.md) | HIGH | Run Postgrator SQL migrations at startup; never modify applied files |
| Test Containers | [test-containers.md](rules/test-containers.md) | HIGH | Spin up real Postgres containers with Testcontainers for integration tests |
| Clean Architecture | [clean-architecture.md](rules/clean-architecture.md) | HIGH | Pure service-layer functions + thin route handlers; explicit dependency injection |
| Unit Testing | [unit-testing.md](rules/unit-testing.md) | HIGH | Unit-test service functions in isolation with mock database stubs |

## Usage

Expand All @@ -40,6 +45,10 @@ When generating Fastify code, read the relevant rule file(s) for the topic and a
- **Error handling**: `error-handling.md`
- **Auth/middleware**: `hooks-lifecycle.md`, `encapsulation.md`
- **Writing tests**: `testing.md`, `create-server.md`
- **Database setup**: `database-integration.md`, `database-migrations.md`
- **Integration tests with a real DB**: `test-containers.md`, `testing.md`
- **Clean separation of concerns**: `clean-architecture.md`, `unit-testing.md`
- **Unit testing business logic**: `unit-testing.md`, `clean-architecture.md`

## Recommended Project Structure

Expand All @@ -48,25 +57,34 @@ Using `@fastify/autoload`, plugins and routes are loaded automatically from thei
```
src/
plugins/ # Autoloaded — shared plugins (use fastify-plugin)
db.ts
db.ts # Database client (pg/Drizzle/Prisma) + lifecycle
auth.ts
config.ts
routes/ # Autoloaded — encapsulated route plugins (NO fastify-plugin)
_hooks.ts # Global route hooks (with autoHooks: true)
users/
index.ts # → /users
index.ts # → /users (thin handler — calls services/users.ts)
_hooks.ts # Hooks for /users scope only
schema.ts
schema.ts # Zod schemas
posts/
index.ts # → /posts
schema.ts
services/ # Pure business logic — no Fastify imports, injectable deps
users.ts
posts.ts
db/
migrate.ts # runMigrations() helper (uses Postgrator)
server.ts # buildServer() with autoload registration
app.ts # Entry point — calls buildServer() and listen()
app.ts # Entry point — runMigrations() then server.listen()
migrations/ # Raw SQL files (committed to git): 001.do.*.sql, 001.undo.*.sql
test/
services/
users.test.ts # Unit tests — pure functions, mock db
routes/
users.test.ts
posts.test.ts
helpers.ts # createTestServer() helper
users.test.ts # Integration tests — inject() + real schema
helpers/
server.ts # createTestServer() / createIntegrationServer()
db.ts # startTestDatabase() via Testcontainers
```

## Present Results to User
Expand All @@ -79,6 +97,11 @@ When applying these best practices, mention which rule(s) you followed:
> - **Zod validation**: Request/response schemas with type inference
> - **Encapsulation**: Shared plugins use `fastify-plugin`, routes stay scoped
> - **Error handling**: Custom error handler with `@fastify/error`
> - **Database**: Client registered as a plugin with `fastify-plugin` for shared pool and lifecycle management
> - **Migrations**: Applied via Postgrator (`runMigrations()`) before server starts; raw SQL files tracked in git
> - **Clean architecture**: Business logic in pure service functions; route handlers stay thin
> - **Unit tests**: Service functions tested in isolation with mock db stubs
> - **Integration tests**: Real Postgres container via Testcontainers

## Reference

Expand Down
Loading