### Basic Usage Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/nextjs-best-practices/references/route-handlers.md Demonstrates the basic setup for GET and POST requests using `route.ts` files. ```APIDOC ## GET /api/users ### Description Handles GET requests to retrieve users. ### Method GET ### Endpoint `/api/users` ### Response #### Success Response (200) - `users` (array) - A list of users. #### Response Example ```json [ { "id": "1", "name": "John Doe" } ] ``` ## POST /api/users ### Description Handles POST requests to create a new user. ### Method POST ### Endpoint `/api/users` ### Parameters #### Request Body - `body` (object) - Required - The user data to create. ### Request Example ```json { "name": "Jane Doe" } ``` ### Response #### Success Response (201) - `user` (object) - The newly created user. #### Response Example ```json { "id": "2", "name": "Jane Doe" } ``` ``` -------------------------------- ### Dockerfile Setup Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/yolo/references/dockerfile.md This Dockerfile configures a Node.js 20 environment, installs development and network tools, sets up a non-root user, installs Claude Code, and configures ZSH with fzf and Powerlevel10k. ```dockerfile FROM node:20 ARG TZ ENV TZ="$TZ" ARG CLAUDE_CODE_VERSION=latest # Install basic development tools and iptables/ipset RUN apt-get update && apt-get install -y --no-install-recommends \ less \ git \ procps \ sudo \ fzf \ zsh \ man-db \ unzip \ gnupg2 \ gh \ iptables \ ipset \ iproute2 \ dnsutils \ aggregate \ jq \ nano \ vim \ && apt-get clean && rm -rf /var/lib/apt/lists/* # Ensure default node user has access to /usr/local/share RUN mkdir -p /usr/local/share/npm-global && \ chown -R node:node /usr/local/share ARG USERNAME=node # Persist bash history. RUN SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \ && mkdir /commandhistory \ && touch /commandhistory/.bash_history \ && chown -R $USERNAME /commandhistory # Set `DEVCONTAINER` environment variable to help with orientation ENV DEVCONTAINER=true # Create workspace and config directories and set permissions RUN mkdir -p /workspace /home/node/.claude && \ chown -R node:node /workspace /home/node/.claude WORKDIR /workspace ARG GIT_DELTA_VERSION=0.18.2 RUN ARCH=$(dpkg --print-architecture) && \ wget "https://github.com/dandavison/delta/releases/download/${GIT_DELTA_VERSION}/git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \ sudo dpkg -i "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" && \ rm "git-delta_${GIT_DELTA_VERSION}_${ARCH}.deb" # Set up non-root user USER node # Install global packages ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global ENV PATH=$PATH:/usr/local/share/npm-global/bin # Set the default shell to zsh rather than sh ENV SHELL=/bin/zsh # Set the default editor and visual ENV EDITOR=nano ENV VISUAL=nano # Default powerline10k theme ARG ZSH_IN_DOCKER_VERSION=1.2.0 RUN sh -c "$(wget -O- https://github.com/deluan/zsh-in-docker/releases/download/v${ZSH_IN_DOCKER_VERSION}/zsh-in-docker.sh)" -- \ -p git \ -p fzf \ -a "source /usr/share/doc/fzf/examples/key-bindings.zsh" \ -a "source /usr/share/doc/fzf/examples/completion.zsh" \ -a "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" \ -x # Install Claude RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION} # Copy and set up firewall script COPY init-firewall.sh /usr/local/bin/ USER root RUN chmod +x /usr/local/bin/init-firewall.sh && \ echo "node ALL=(root) NOPASSWD: /usr/local/bin/init-firewall.sh" > /etc/sudoers.d/node-firewall && \ chmod 0440 /etc/sudoers.d/node-firewall USER node ``` -------------------------------- ### Install ts-dev-kit Plugin Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Use these commands to add the ts-dev-kit plugin to your marketplace and then install it. ```bash /plugin marketplace add jgamaraalv/ts-dev-kit ``` ```bash /plugin install ts-dev-kit@ts-dev-kit ``` -------------------------------- ### Install Event: Pre-cache Assets Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/service-worker/SKILL.md Use the 'install' event to pre-cache static assets. `event.waitUntil()` ensures the installation process completes successfully before the service worker becomes active. If the promise rejects, installation fails. ```javascript // sw.js const CACHE_NAME = "v1"; const PRECACHE_URLS = ["/", "/index.html", "/style.css", "/app.js"]; self.addEventListener("install", (event) => { event.waitUntil(caches.open(CACHE_NAME).then((cache) => cache.addAll(PRECACHE_URLS))); }); ``` -------------------------------- ### Start Docker Daemon on Linux Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/yolo/SKILL.md Starts the Docker daemon using systemctl on Linux systems. This is used when the Docker daemon is installed but not running. ```bash sudo systemctl start docker ``` -------------------------------- ### Install all skills using skills.sh Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Install all skills from the ts-dev-kit using the skills.sh script. This method installs skills only and works with various editors. ```bash npx skills add jgamaraalv/ts-dev-kit ``` -------------------------------- ### Provider Setup for Next.js App Router Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/tanstack-query/references/ssr-nextjs.md Set up a `QueryClientProvider` in `app/providers.tsx` for the App Router. This example uses a singleton pattern for the query client on the browser to maintain state across renders. ```tsx 'use client' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { useState } from 'react' function makeQueryClient() { return new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000, // must be > 0 for SSR }, }, }) } let browserQueryClient: QueryClient | undefined function getQueryClient() { if (typeof window === 'undefined') { // Server: always make a new query client return makeQueryClient() } // Browser: reuse singleton if (!browserQueryClient) browserQueryClient = makeQueryClient() return browserQueryClient } export default function Providers({ children }: { children: React.ReactNode }) { const queryClient = getQueryClient() return ( {children} ) } ``` -------------------------------- ### Start Docker on macOS Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/yolo/SKILL.md Opens the Docker application on macOS to start the Docker daemon. This is used when Docker is installed but not running. ```bash open -a Docker ``` -------------------------------- ### Install context7 MCP Server Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Install the context7 MCP server using the 'mcp add' command. This server is used for querying up-to-date library documentation and does not require an API key. ```bash claude mcp add context7 -- npx -y @upstash/context7-mcp@latest ``` -------------------------------- ### Setup QueryClient and QueryClientProvider Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/tanstack-query/SKILL.md Demonstrates how to set up the QueryClient with default options and provide it to the application using QueryClientProvider. ```APIDOC ## Setup ```tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000, // 1 min (default is 0) gcTime: 5 * 60 * 1000, // 5 min (default) retry: 3, // 3 retries with exponential backoff (default) refetchOnWindowFocus: true, // default }, }, }) function App() { return ( ) } ``` ``` -------------------------------- ### Example: Get Errors via MCP Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/nextjs-best-practices/references/debug-tricks.md A concrete example of using curl to request errors from the `/_next/mcp` endpoint. Replace `` with the correct development server port. ```bash curl -X POST http://localhost:/_next/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"get_errors","arguments":{}}}' ``` -------------------------------- ### Interpreting EXPLAIN Output Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/performance.md This example shows typical output from `EXPLAIN (ANALYZE, BUFFERS)`. Pay attention to actual times, row counts, and buffer usage. ```text Seq Scan on orders (cost=0.00..45231.00 rows=2000001 width=88) (actual time=0.028..312.483 rows=2000001 loops=1) Buffers: shared hit=22727 read=4615 Planning Time: 0.086 ms Execution Time: 401.123 ms ``` -------------------------------- ### Install ts-dev-kit from GitHub Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Clone the ts-dev-kit repository from GitHub and configure the Claude plugin directory. ```bash git clone https://github.com/jgamaraalv/ts-dev-kit.git claude --plugin-dir ./ts-dev-kit ``` -------------------------------- ### PostgreSQL List Partitioning Setup Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/ddl-schema.md Sets up a table partitioned by list on a text column, defining partitions for specific regions. ```sql -- List partitioning CREATE TABLE orders (id bigint, region text, ...) PARTITION BY LIST (region); CREATE TABLE orders_br PARTITION OF orders FOR VALUES IN ('BR', 'PT'); CREATE TABLE orders_us PARTITION OF orders FOR VALUES IN ('US', 'CA'); ``` -------------------------------- ### Integration Test Example with Vitest and Fastify Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/agents/test-generator.md Shows an integration test for a Fastify application endpoint. Requires setting up the application instance before tests and closing it afterwards. Ensure Fastify and necessary types are installed. ```typescript import { describe, it, expect, beforeAll, afterAll } from "vitest"; import { buildApp } from "../../app"; import type { FastifyInstance } from "fastify"; describe("GET /health", () => { let app: FastifyInstance; beforeAll(async () => { app = await buildApp({ logger: false }); }); afterAll(async () => { await app.close(); }); it("returns ok status", async () => { const response = await app.inject({ method: "GET", url: "/health" }); expect(response.statusCode).toBe(200); }); }); ``` -------------------------------- ### Install skills globally using skills.sh Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Install skills from the ts-dev-kit globally using the skills.sh script. ```bash npx skills add jgamaraalv/ts-dev-kit --global ``` -------------------------------- ### Install ts-dev-kit via CLI Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Alternative method to install the ts-dev-kit using the Claude CLI. ```bash claude plugin install ts-dev-kit --scope user ``` -------------------------------- ### Custom Migration SQL Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/drizzle-pg/references/migrations.md Example of SQL content for a custom migration, including inserting data into the 'users' table. ```sql -- Custom migration: seed-users INSERT INTO "users" ("name", "email") VALUES ('Dan', 'dan@example.com'); INSERT INTO "users" ("name", "email") VALUES ('Andrew', 'andrew@example.com'); ``` -------------------------------- ### Install MCP Plugins Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Install recommended MCP servers as Claude Code plugins to enhance skill functionality for tasks like documentation lookup and browser debugging. ```bash claude plugin add context7 claude plugin add playwright claude plugin add firecrawl ``` -------------------------------- ### List PostgreSQL Extensions Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/psql-cli.md Use \dx to list installed extensions. ```sql -- Extensions \dx -- installed extensions ``` -------------------------------- ### Install a specific skill using skills.sh Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Install a specific skill from the ts-dev-kit using the skills.sh script. ```bash npx skills add jgamaraalv/ts-dev-kit --skill fastify-best-practices ``` -------------------------------- ### Install TS Dev Kit Skills Only Source: https://context7.com/jgamaraalv/ts-dev-kit/llms.txt Install only the skills from TS Dev Kit using the 'skills.sh' utility. This can be used to install all skills, a single skill, or globally. ```bash # All skills npx skills add jgamaraalv/ts-dev-kit # A single skill npx skills add jgamaraalv/ts-dev-kit --skill fastify-best-practices # Global install npx skills add jgamaraalv/ts-dev-kit --global ``` -------------------------------- ### Install ts-dev-kit via npm Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Install the ts-dev-kit package globally using npm and configure the Claude plugin directory. ```bash npm install -g @jgamaraalv/ts-dev-kit claude --plugin-dir ./node_modules/@jgamaraalv/ts-dev-kit ``` -------------------------------- ### Dispatch Task Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/execute-task/references/agent-dispatch.md Example of dispatching an agent to build resource API routes. Specify the agent, model, and a detailed prompt including task, patterns, and success criteria. ```typescript // Use the agent name as registered in your context. // Project-scoped: "api-builder". Plugin-scoped: "ts-dev-kit:api-builder". Task( description: "Build resource API routes", subagent_type: "api-builder", // or "ts-dev-kit:api-builder" if plugin-scoped model: "sonnet", prompt: """ ## Your task Create REST endpoints for the [feature name]: - POST /api/ — create a new resource - GET /api//:id — get resource details - PATCH /api//:id — update resource ## Existing patterns to follow Discover from the codebase: - Route structure: look for existing route handlers and follow the same pattern - Shared schemas: look for existing schema/type definitions in shared packages - Use case pattern: look for existing use case or service implementations ## Success criteria - All endpoints respond with correct status codes - Request/response validated with shared schemas - Endpoints follow the project's routing conventions """ ) ``` -------------------------------- ### Multi-Agent Dispatch Plan Example Source: https://context7.com/jgamaraalv/ts-dev-kit/llms.txt An example output from the multi-agent-coordinator, detailing a phased dispatch plan for a workflow involving shared types, database schema, and quality gates. ```markdown # Example output from multi-agent-coordinator: ## Dispatch Plan ### Phase 1: Foundation + Data Layer > Dependencies: none > Parallel: yes #### Task 1.1: Shared types and Zod schemas - **subagent_type**: typescript-pro - **model**: haiku - **isolation**: worktree - **description**: Define shared user schemas - **prompt**: | Create `packages/shared/src/schemas/user.ts` with Zod schemas for CreateUser and User. Run: pnpm --filter @acme/shared typecheck #### Task 1.2: Database schema and migration - **subagent_type**: database-expert - **model**: sonnet - **isolation**: worktree - **description**: Add users table schema - **prompt**: | Add `users` table to `apps/api/src/db/schema/users.ts`. Run: npx drizzle-kit generate ### Phase 2: Quality Gates > Dependencies: Phase 1 > Parallel: no #### Task 2.1: Verify integration - **subagent_type**: Bash - **prompt**: pnpm typecheck && pnpm lint && pnpm build ``` -------------------------------- ### Verify Devcontainer Installation Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/yolo/SKILL.md These commands can be used to verify that the `.devcontainer` directory and its contents have been created correctly. ```bash ls -la .devcontainer/ cat .devcontainer/devcontainer.json | head -5 ``` -------------------------------- ### Fix Commit with Body and Footers Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/conventional-commits/SKILL.md A detailed example of a fix commit, including a multi-line body and various footers like 'Reviewed-by' and 'Refs'. ```text fix: prevent racing of requests Introduce a request id and a reference to latest request. Dismiss incoming responses other than from latest request. Remove timeouts which were used to mitigate the racing issue but are obsolete now. Reviewed-by: Z Refs: #123 ``` -------------------------------- ### Install playwright MCP Server Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/README.md Install the playwright MCP server using the 'mcp add' command. This server is used for browser automation and E2E testing and does not require an API key. ```bash claude mcp add playwright -- npx -y @playwright/mcp@latest ``` -------------------------------- ### Add Project Dependencies Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/yolo/SKILL.md To install project-specific dependencies, add `RUN` commands to the `Dockerfile` before the `USER node` line. ```dockerfile RUN apt-get update && apt-get install -y your-package ``` -------------------------------- ### BullMQ Quick Start: Producer, Consumer, and Events Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/bullmq/SKILL.md Sets up a basic BullMQ producer to add jobs and a consumer (worker) to process them. Includes global event listeners for job completion and failure. ```typescript import { Queue, Worker, QueueEvents } from "bullmq"; // --- Producer --- const queue = new Queue("my-queue", { connection: { host: "localhost", port: 6379 }, }); await queue.add("job-name", { foo: "bar" }); // --- Consumer --- const worker = new Worker( "my-queue", async (job) => { // process job await job.updateProgress(50); return { result: "done" }; }, { connection: { host: "localhost", port: 6379 } }, ); worker.on("completed", (job, returnvalue) => { console.log(`${job.id} completed with`, returnvalue); }); worker.on("failed", (job, err) => { console.error(`${job.id} failed with`, err.message); }); // IMPORTANT: always attach an error handler worker.on("error", (err) => { console.error(err); }); // --- Global event listener (all workers) --- const queueEvents = new QueueEvents("my-queue", { connection: { host: "localhost", port: 6379 }, }); queueEvents.on("completed", ({ jobId, returnvalue }) => { console.log(`Job ${jobId} completed`); }); queueEvents.on("failed", ({ jobId, failedReason }) => { console.error(`Job ${jobId} failed: ${failedReason}`); }); ``` -------------------------------- ### Request Timing Hook Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/fastify-best-practices/references/hooks-and-lifecycle.md Measure request duration by recording a start time in `onRequest` and calculating the difference in `onResponse`. ```typescript fastify.addHook("onRequest", async (request) => { request.startTime = Date.now(); }); fastify.addHook("onResponse", async (request, reply) => { request.log.info({ ms: Date.now() - request.startTime }, "request completed"); }); ``` -------------------------------- ### Cluster Pub/Sub Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/ioredis/references/cluster-sentinel.md Standard Pub/Sub works in a cluster. One node handles subscriptions, broadcasting messages cluster-wide. ```typescript const pub = new Cluster(nodes); const sub = new Cluster(nodes); sub.on("message", (channel, message) => console.log(channel, message)); await sub.subscribe("news"); pub.publish("news", "hello"); ``` -------------------------------- ### Prevent Waterfall Chains in API Routes (TypeScript) Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/react-best-practices/references/async-patterns.md Start independent operations immediately in API routes and Server Actions. This example shows how to fetch authentication and configuration concurrently. ```typescript export async function GET(request: Request) { const session = await auth(); const config = await fetchConfig(); const data = await fetchData(session.user.id); return Response.json({ data, config }); } ``` ```typescript export async function GET(request: Request) { const sessionPromise = auth(); const configPromise = fetchConfig(); const session = await sessionPromise; const [config, data] = await Promise.all([configPromise, fetchData(session.user.id)]); return Response.json({ data, config }); } ``` -------------------------------- ### Redis Cluster Initialization Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/ioredis/references/cluster-sentinel.md Demonstrates how to initialize a new ioredis Cluster instance with startup nodes and perform basic operations like SET and GET. ```APIDOC ## Redis Cluster Initialization ### Description Initializes a new ioredis Cluster instance with a list of startup nodes. ioredis will automatically discover the rest of the cluster topology. ### Method `new Cluster(nodes: ClusterNode[], options?: ClusterOptions)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript import { Cluster } from "ioredis"; const cluster = new Cluster([ { host: "127.0.0.1", port: 6380 }, { host: "127.0.0.1", port: 6381 }, ]); await cluster.set("foo", "bar"); const val = await cluster.get("foo"); // "bar" ``` ### Response #### Success Response (200) N/A (This is a constructor) #### Response Example N/A ``` -------------------------------- ### Apply Fastify Best Practices Source: https://context7.com/jgamaraalv/ts-dev-kit/llms.txt This command loads Fastify 5 best practices as a reference, covering request lifecycle, anti-patterns, plugin encapsulation, hooks, validation, and serialization. It's automatically used by `api-builder`. ```bash /fastify-best-practices # load as reference ``` ```typescript // Global error handler (enforced pattern) fastify.setErrorHandler((error, request, reply) => { request.log.error(error); const statusCode = error.statusCode ?? 500; reply.code(statusCode).send({ error: statusCode >= 500 ? "Internal Server Error" : error.message, }); }); // Request lifecycle (exact hook order): // onRequest → preParsing → Content-Type Parsing → preValidation // → Schema Validation (400 on failure) → preHandler // → Route Handler → preSerialization → onSend → Response → onResponse ``` -------------------------------- ### Mock API Responses with nock Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/tanstack-query/references/testing.md Use the nock library to mock HTTP requests in your tests. This example shows how to mock a GET request to an API endpoint and assert that the hook fetches the data correctly. ```tsx import nock from 'nock' test('fetches data from API', async () => { nock('http://example.com') .get('/api/todos') .reply(200, [{ id: 1, title: 'Test' }]) const { result } = renderHook(() => useTodos(), { wrapper: createWrapper(), }) await waitFor(() => expect(result.current.isSuccess).toBe(true)) expect(result.current.data).toEqual([{ id: 1, title: 'Test' }]) }) ``` -------------------------------- ### Repeatable Read Isolation Level Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/transactions.md Shows how to set the Repeatable Read isolation level for a transaction. This ensures that all reads within the transaction see a consistent snapshot of the database taken at the start of the transaction. ```sql BEGIN ISOLATION LEVEL REPEATABLE READ; SELECT SUM(balance) FROM accounts; -- snapshot taken here -- Other transactions' commits won't affect our subsequent reads COMMIT; ``` -------------------------------- ### PostgreSQL Range Partitioning Setup Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/ddl-schema.md Defines a parent table partitioned by range on a timestamp column and creates monthly partitions with specific value ranges. Includes creating a default partition. ```sql -- Create parent table CREATE TABLE metrics ( id bigint GENERATED ALWAYS AS IDENTITY, recorded_at timestamptz NOT NULL, value numeric ) PARTITION BY RANGE (recorded_at); ``` ```sql -- Create monthly partitions CREATE TABLE metrics_2025_01 PARTITION OF metrics FOR VALUES FROM ('2025-01-01') TO ('2025-02-01'); CREATE TABLE metrics_2025_02 PARTITION OF metrics FOR VALUES FROM ('2025-02-01') TO ('2025-03-01'); ``` ```sql -- Default partition (catches anything not matched) CREATE TABLE metrics_default PARTITION OF metrics DEFAULT; ``` -------------------------------- ### Redis Cache Handler for Next.js Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/nextjs-best-practices/references/self-hosting.md Implement a custom cache handler using Redis for Next.js ISR. This example provides `get`, `set`, and a placeholder for `revalidateTag` to manage shared caching across distributed instances. ```javascript import { Redis } from "ioredis"; const redis = new Redis(process.env.REDIS_URL); const CACHE_PREFIX = "nextjs:"; export default class CacheHandler { constructor(options) { this.options = options; } async get(key) { const data = await redis.get(CACHE_PREFIX + key); if (!data) return null; const parsed = JSON.parse(data); return { value: parsed.value, lastModified: parsed.lastModified, }; } async set(key, data, ctx) { const cacheData = { value: data, lastModified: Date.now(), }; if (ctx?.revalidate) { await redis.setex(CACHE_PREFIX + key, ctx.revalidate, JSON.stringify(cacheData)); } else { await redis.set(CACHE_PREFIX + key, JSON.stringify(cacheData)); } } async revalidateTag(tags) { // Implement tag-based invalidation // This requires tracking which keys have which tags } } ``` -------------------------------- ### PostgreSQL LATERAL Joins Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/queries.md Shows how to use LATERAL joins to reference columns from preceding tables in a FROM clause subquery. Includes examples for getting the latest N records per group and using LEFT JOIN LATERAL. ```sql -- Get latest N orders per customer SELECT c.name, o.* FROM customers c, LATERAL ( SELECT * FROM orders WHERE customer_id = c.id ORDER BY created_at DESC LIMIT 3 ) o; -- With LEFT JOIN LATERAL (include customers with no orders) SELECT c.name, o.id FROM customers c LEFT JOIN LATERAL ( SELECT id FROM orders WHERE customer_id = c.id ORDER BY created_at DESC LIMIT 1 ) o ON true; ``` -------------------------------- ### Multi-Stage Dockerfile for Yarn 4 Monorepo Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/docker/references/monorepo-dockerfile.md This Dockerfile uses multiple stages to build a production-ready API image. It starts with a base Node.js image, installs dependencies, builds workspaces, and finally copies only necessary artifacts to a lean runtime image. ```dockerfile # ============================================ # Stage 1: Base with Yarn 4 Berry # ============================================ FROM node:22-alpine AS base ENV YARN_ENABLE_GLOBAL_CACHE=false WORKDIR /app # Install Yarn Berry COPY .yarnrc.yml ./ COPY .yarn/ .yarn/ COPY package.json yarn.lock ./ # ============================================ # Stage 2: Install ALL dependencies (for building) # ============================================ FROM base AS deps # Copy all workspace package.json files COPY apps/api/package.json apps/api/ COPY apps/web/package.json apps/web/ COPY packages/shared/package.json packages/shared/ COPY packages/config/package.json packages/config/ RUN yarn install --immutable # ============================================ # Stage 3: Build shared packages first # ============================================ FROM deps AS builder COPY . . # Build in dependency order RUN yarn workspace @myapp/shared build RUN yarn workspace @myapp/api build # Or for web: RUN yarn workspace @myapp/web build # ============================================ # Stage 4: Production runtime (API) # ============================================ FROM node:22-alpine AS api-runner WORKDIR /app # Security: non-root user RUN addgroup --system app && adduser --system --ingroup app app # Copy only production dependencies and built output COPY --from=builder /app/apps/api/dist ./apps/api/dist COPY --from=builder /app/apps/api/package.json ./apps/api/ COPY --from=builder /app/packages/shared/dist ./packages/shared/dist COPY --from=builder /app/packages/shared/package.json ./packages/shared/ COPY --from=builder /app/package.json ./ COPY --from=builder /app/yarn.lock ./ COPY --from=builder /app/.yarnrc.yml ./ COPY --from=builder /app/.yarn/ ./.yarn/ # Install production dependencies only RUN yarn workspaces focus @myapp/api --production && yarn cache clean USER app EXPOSE 3001 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 CMD wget --no-verbose --tries=1 --spider http://localhost:3001/health || exit 1 CMD ["node", "apps/api/dist/index.js"] ``` -------------------------------- ### PostgreSQL Schema Creation and Usage Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/ddl-schema.md Shows how to create a new schema, create tables within it, and manage the search path to include the new schema. ```sql CREATE SCHEMA analytics; CREATE TABLE analytics.events (...); ``` ```sql -- Search path (which schemas to look in, in order) SET search_path TO myapp, public; SHOW search_path; ``` -------------------------------- ### Next.js Parallel Routes Setup Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/nextjs-best-practices/references/file-conventions.md Shows how to set up parallel routes using named slots and how the layout receives these slots as props. ```typescript app/ ├── @analytics/ │ └── page.tsx ├── @sidebar/ │ └── page.tsx └── layout.tsx # Receives { analytics, sidebar } as props ``` -------------------------------- ### Install TS Dev Kit Plugin Source: https://context7.com/jgamaraalv/ts-dev-kit/llms.txt Install the TS Dev Kit as a Claude Code plugin via the marketplace or CLI. This installs both agents and skills. ```bash # Via Claude Code plugin marketplace /plugin marketplace add jgamaraalv/ts-dev-kit /plugin install ts-dev-kit@ts-dev-kit # Or via CLI claude plugin install ts-dev-kit --scope user ``` -------------------------------- ### Basic Fastify Logging Setup Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/fastify-best-practices/references/typescript-and-logging.md Enable Pino logging in Fastify by setting the `logger` option to `true` or configuring it with a specific log level. ```typescript const fastify = Fastify({ logger: true, // default Pino with info level }); // Or with options: const fastify = Fastify({ logger: { level: "info", }, }); ``` -------------------------------- ### Basic GET and POST Route Handlers Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/nextjs-best-practices/references/route-handlers.md Define GET and POST request handlers for an API endpoint. The GET handler fetches users, and the POST handler creates a user from the request body. ```typescript // app/api/users/route.ts export async function GET() { const users = await getUsers(); return Response.json(users); } export async function POST(request: Request) { const body = await request.json(); const user = await createUser(body); return Response.json(user, { status: 201 }); } ``` -------------------------------- ### Initialize ioredis Cluster Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/ioredis/references/cluster-sentinel.md Instantiate a new ioredis Cluster client. Provide startup nodes; ioredis will auto-discover the rest. This is the basic setup for connecting to a Redis Cluster. ```typescript import { Cluster } from "ioredis"; const cluster = new Cluster([ { host: "127.0.0.1", port: 6380 }, { host: "127.0.0.1", port: 6381 }, ]); await cluster.set("foo", "bar"); const val = await cluster.get("foo"); // "bar" ``` -------------------------------- ### Select Queries Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/drizzle-pg/references/queries.md Demonstrates various ways to select data, from basic all-column selects to partial selects, selects with SQL expressions, and using WHERE, ORDER BY, LIMIT, and OFFSET clauses. ```APIDOC ## Select Queries ### Basic Select Selects all columns from a table. ```typescript // All columns await db.select().from(users); // Partial select (flat result) await db.select({ id: users.id, name: users.name }).from(users); // With SQL expression await db .select({ id: users.id, lowerName: sql`lower(${users.name})`.as("lower_name"), }) .from(users); ``` ### Select with Filtering, Ordering, and Pagination Applies WHERE, ORDER BY, LIMIT, and OFFSET clauses to refine query results. ```typescript await db.select().from(users) .where(eq(users.id, 42)) .orderBy(asc(users.name)) .limit(10) .offset(20); // Multiple order columns .orderBy(desc(users.createdAt), asc(users.name)) ``` ### Conditional WHERE Clause Builds WHERE clauses dynamically based on input conditions. ```typescript async function getProducts({ name, category, maxPrice }: Filters) { const filters: SQL[] = []; if (name) filters.push(ilike(products.name, `%${name}%`)); if (category) filters.push(eq(products.category, category)); if (maxPrice) filters.push(lte(products.price, maxPrice)); return db .select() .from(products) .where(and(...filters)); } ``` ### Subqueries Utilizes subqueries within a select statement. ```typescript const subquery = db .select({ avgPrice: sql`avg(${products.price})`.as("avg_price") }) .from(products) .as("sub"); await db.select().from(subquery); ``` ### WITH Clause (CTEs) Implements Common Table Expressions (CTEs) for complex queries. ```typescript const topUsers = db.$with("top_users").as(db.select().from(users).where(gt(users.score, 100))); await db.with(topUsers).select().from(topUsers); ``` ### DISTINCT Clause Selects unique rows, with an option for `DISTINCT ON` (PostgreSQL specific). ```typescript await db.selectDistinct().from(users); await db.selectDistinctOn([users.name]).from(users); // PG-specific ``` ### Aggregations Performs aggregate functions like COUNT and AVG, with GROUP BY and HAVING clauses. ```typescript await db .select({ category: products.category, count: sql`count(*)`.mapWith(Number), avgPrice: sql`avg(${products.price})`.mapWith(Number), }) .from(products) .groupBy(products.category) .having(sql`count(*) > 5`); ``` ### Prepared Statements Defines and executes prepared statements for efficiency and security. ```typescript const prepared = db .select() .from(users) .where(eq(users.id, sql.placeholder("id"))) .prepare("get_user"); await prepared.execute({ id: 42 }); ``` ``` -------------------------------- ### Simple Fix Commit Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/conventional-commits/SKILL.md A basic example of a commit message for a bug fix. ```text fix: prevent racing of requests ``` -------------------------------- ### PostgreSQL EXPLAIN Options Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/performance.md Use `EXPLAIN (ANALYZE, BUFFERS)` for real data analysis. Other options provide different levels of detail or output formats. ```sql EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT ...; ``` ```sql EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) SELECT ...; ``` ```sql EXPLAIN (ANALYZE, BUFFERS, SETTINGS) SELECT ...; ``` ```sql EXPLAIN (ANALYZE, VERBOSE, BUFFERS) SELECT ...; ``` -------------------------------- ### PostgreSQL BRIN Index Examples Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/indexes.md Shows how to create BRIN indexes, which have a small footprint and are effective for columns with values correlated to their physical storage order, like timestamps on append-only tables. Avoid BRIN for frequently updated or randomly distributed data. ```sql CREATE INDEX idx_logs_created ON logs USING BRIN (created_at); ``` ```sql -- pages_per_range controls granularity (default 128) CREATE INDEX idx_metrics_time ON metrics USING BRIN (recorded_at) WITH (pages_per_range = 32); ``` -------------------------------- ### PostgreSQL GiST Index Examples Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/indexes.md Demonstrates creating GiST indexes for geometric types, range types, full-text search, and PostGIS geometry. Use GiST for custom index types and specialized data. ```sql CREATE INDEX idx_locations_point ON locations USING GIST (coordinates); -- Query: SELECT * FROM locations ORDER BY coordinates <-> '(0,0)'::point LIMIT 10; ``` ```sql -- Range type (no overlap) CREATE INDEX idx_reservations_period ON reservations USING GIST (period); -- Query: WHERE period && '[2025-01-01, 2025-01-07)'::daterange ``` ```sql -- Full-text (alternative to GIN — smaller index, slower search) CREATE INDEX idx_posts_fts ON posts USING GIST (to_tsvector('english', body)); ``` ```sql -- PostGIS CREATE INDEX idx_geom ON places USING GIST (geom); ``` -------------------------------- ### Docs Commit with No Body Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/conventional-commits/SKILL.md A simple example of a commit message for documentation changes, without a body. ```text docs: correct spelling of CHANGELOG ``` -------------------------------- ### Get PostgreSQL Database Size Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/psql-cli.md Query pg_size_pretty(pg_database_size(current_database())) to get the human-readable size of the current database. ```sql -- Database size SELECT pg_size_pretty(pg_database_size(current_database())); ``` -------------------------------- ### Drizzle-ORM Studio Command Options Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/drizzle-pg/references/migrations.md Options for the 'studio' command, which launches the Drizzle Studio visual database explorer. Specify the '--port' and '--host' for the studio, or use '--config' to point to the config file. ```bash --port= Studio port (default: 4983) --host= Studio host (default: localhost) --config= Config file path ``` -------------------------------- ### Run Lighthouse Audit via CLI Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/core-web-vitals/references/tools.md Install Lighthouse globally and run an audit on a specified URL, outputting the report to an HTML file. Use `--throttling-method=simulate` for reproducible scores. ```bash npm install -g lighthouse lighthouse https://example.com --output html --output-path ./report.html ``` -------------------------------- ### PostgreSQL Self-Join Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/postgresql/references/queries.md Illustrates a self-join where a table is joined with itself to query hierarchical data. This example shows employees and their managers. ```sql -- Self-join SELECT e.name, m.name AS manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.id; ``` -------------------------------- ### Queue Class Operations Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/bullmq/SKILL.md Demonstrates how to instantiate and use the Queue class for adding jobs with various options, and performing queue-level operations. ```APIDOC ## Queue Class ### Description Provides methods to interact with a BullMQ queue, including adding jobs with specific options and managing the queue's state. ### Methods #### `add(name: string, data: any, opts?: AddJobOptions): Promise Adds a single job to the queue. **Parameters** - `name` (string) - The name of the job. - `data` (any) - The payload of the job. - `opts` (AddJobOptions) - Optional configuration for the job, such as `delay`, `priority`, `attempts`, `backoff`, `removeOnComplete`, `removeOnFail`. ### Request Example ```ts const queue = new Queue("paint", { connection }); // Add a job await queue.add("job-name", { color: "red" }); // Add with options await queue.add( "job-name", { color: "blue" }, { delay: 5000, // wait 5s before processing priority: 1, // lower = higher priority (0 is highest, max 2^21) attempts: 3, // retry up to 3 times backoff: { type: "exponential", delay: 1000 }, removeOnComplete: true, // or { count: 100 } to keep last 100 removeOnFail: 1000, // keep last 1000 failed jobs }, ); ``` #### `addBulk(jobs: AddJobOptions[]): Promise Adds multiple jobs to the queue in a single operation. **Parameters** - `jobs` (Array) - An array of job objects, each potentially including `name`, `data`, and `opts`. ### Request Example ```ts await queue.addBulk([ { name: "job1", data: { x: 1 } }, { name: "job2", data: { x: 2 }, opts: { priority: 1 } }, ]); ``` #### `pause(): Promise Pauses the processing of jobs in the queue. #### `resume(): Promise Resumes the processing of jobs in the queue. #### `obliterate(opts?: { force: boolean }): Promise Removes all data associated with the queue. Requires `force: true` to proceed. #### `close(): Promise Closes the connection to the queue and cleans up resources. ``` -------------------------------- ### Feature Commit with Scope Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/conventional-commits/SKILL.md An example of a commit message for a new feature, including a scope to specify the affected section. ```text feat(lang): add Polish language ``` -------------------------------- ### MCP Tool: Get Logs Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/nextjs-best-practices/references/debug-tricks.md Get the file path to the Next.js development log file, typically located within the `distDir`. ```json { "name": "get_logs", "arguments": {} } ``` -------------------------------- ### Initialize Firewall Script Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/yolo/SKILL.md This script sets up a strict, default-deny firewall policy. It whitelists essential outbound traffic and preserves Docker DNS rules. Ensure this script is executable and run with sudo. ```bash set -euo pipefail # Default-deny policy iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP # Preserve Docker DNS rules DNS_RULES="$(iptables -S OUTPUT | grep 'dpt:53')" if [ -n "$DNS_RULES" ]; then echo "Preserving DNS rules: $DNS_RULES" echo "$DNS_RULES" | while IFS= read -r line; do iptables -I OUTPUT 1 <<< "$line" done fi # Allow loopback iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -i lo -j ACCEPT # Allow established connections iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Whitelist specific domains and services # Note: Use ipset for efficient CIDR matching. Do NOT add fallback logic. # npm registry for domain in "registry.npmjs.org"; do for ip in $(dig +short "$domain"); do ipset add npm_registry "$ip" done iptables -A OUTPUT -m set --match-set npm_registry dst -j ACCEPT done # GitHub API (dynamic IP fetch) for domain in "api.github.com"; do for ip in $(dig +short "$domain"); do ipset add github_api "$ip" done iptables -A OUTPUT -m set --match-set github_api dst -j ACCEPT done # Anthropic API for domain in "api.anthropic.com"; do for ip in $(dig +short "$domain"); do ipset add anthropic_api "$ip" done iptables -A OUTPUT -m set --match-set anthropic_api dst -j ACCEPT done # Sentry for domain in "sentry.io"; do for ip in $(dig +short "$domain"); do ipset add sentry "$ip" done iptables -A OUTPUT -m set --match-set sentry dst -j ACCEPT done # StatsIG for domain in "statsig.com"; do for ip in $(dig +short "$domain"); do ipset add statsig "$ip" done iptables -A OUTPUT -m set --match-set statsig dst -j ACCEPT done # VS Code Marketplace for domain in "marketplace.visualstudio.com"; do for ip in $(dig +short "$domain"); do ipset add vscode_marketplace "$ip" done iptables -A OUTPUT -m set --match-set vscode_marketplace dst -j ACCEPT done # Allow DNS resolution for whitelisted domains iptables -A OUTPUT -p udp --dport 53 -j ACCEPT iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT # Allow SSH (if needed for external access) iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT # Allow localhost communication iptables -A OUTPUT -d 127.0.0.1 -j ACCEPT iptables -A INPUT -s 127.0.0.1 -j ACCEPT # Allow host network access iptables -A OUTPUT -o docker0 -j ACCEPT iptables -A INPUT -i docker0 -j ACCEPT # --- Startup Verification --- # Verify example.com is blocked if curl --silent --fail http://example.com > /dev/null; then echo "ERROR: example.com is reachable, but should be blocked." exit 1 fi # Verify GitHub API is reachable if ! curl --silent --fail https://api.github.com > /dev/null; then echo "ERROR: GitHub API is not reachable." exit 1 fi echo "Firewall initialized successfully." exit 0 ``` -------------------------------- ### Revert Commit with Footer References Example Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/conventional-commits/SKILL.md An example of a revert commit message that references the original commits using the 'Refs' footer. ```text revert: let us never again speak of the noodle incident Refs: 676104e, a215868 ``` -------------------------------- ### Set and Get Redis Keys Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/ioredis/SKILL.md Perform basic key-value operations using `set` to store a value and `get` to retrieve it. These operations are asynchronous. ```javascript await redis.set("key", "val") await redis.get("key") ``` -------------------------------- ### Start Docker Compose Services Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/docker/SKILL.md Starts all services defined in your docker-compose.yml file in detached mode. Use '-d' to run containers in the background. ```bash docker compose up -d ``` -------------------------------- ### Install VS Code Dev Containers Extension Source: https://github.com/jgamaraalv/ts-dev-kit/blob/main/skills/yolo/SKILL.md Installs the VS Code Remote - Containers extension, which is required for working with devcontainers. This command is idempotent. ```bash code --install-extension ms-vscode-remote.remote-containers ```