typescript

ABOUTME: TypeScript skill for ecommerce monorepo with Next.js and Fastify

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "typescript" with this command: npx skills add lorenzogirardi/ai-ecom-demo/lorenzogirardi-ai-ecom-demo-typescript

ABOUTME: TypeScript skill for ecommerce monorepo with Next.js and Fastify

ABOUTME: Covers type patterns, Prisma, Zod, React Query, and testing conventions

TypeScript Skill (Ecommerce)

Quick Reference

Rule Convention

Strict mode Always enabled

Null checks strictNullChecks: true

Return types Explicit for public APIs

Zod schemas Validation at boundaries

Prisma types Auto-generated, never manual

Project Structure

apps/ ├── frontend/ # Next.js 16 │ ├── src/ │ │ ├── app/ # App Router pages │ │ ├── components/ # React components │ │ ├── hooks/ # Custom hooks (useProducts, useCart, etc.) │ │ ├── lib/ # Utilities (api.ts, auth-context.tsx) │ │ └── types/ # Type definitions │ └── tests/ # Frontend tests │ └── backend/ # Fastify API ├── src/ │ ├── config/ # Configuration │ ├── middleware/ # Auth guard, error handler │ ├── modules/ # Feature modules (auth, catalog, orders) │ └── utils/ # Prisma, Redis, logger ├── prisma/ # Schema and migrations └── tests/ # Backend tests

Type Patterns

API Response Types

// types/api.ts export interface ApiResponse<T> { data: T; meta?: { total: number; page: number; pageSize: number; }; }

export interface ApiError { statusCode: number; error: string; message: string; }

Zod Schemas (Validation)

// schemas/product.ts import { z } from 'zod';

export const ProductSchema = z.object({ id: z.string().uuid(), name: z.string().min(1).max(255), price: z.number().positive(), categoryId: z.string().uuid(), });

export type Product = z.infer<typeof ProductSchema>;

// Use at API boundaries const validated = ProductSchema.parse(requestBody);

Prisma Integration

// DON'T manually define DB types // DO use Prisma generated types import { User, Product, Order } from '@prisma/client';

// Include relations explicitly import { Prisma } from '@prisma/client';

type OrderWithItems = Prisma.OrderGetPayload<{ include: { items: { include: { product: true } } }; }>;

React Patterns

Custom Hooks

// hooks/useProducts.ts import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

export function useProducts(categoryId?: string) { return useQuery({ queryKey: ['products', categoryId], queryFn: () => api.getProducts(categoryId), staleTime: 5 * 60 * 1000, // 5 minutes }); }

export function useCreateProduct() { const queryClient = useQueryClient();

return useMutation({ mutationFn: api.createProduct, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['products'] }); }, }); }

Component Props

// components/ProductCard.tsx interface ProductCardProps { product: Product; onAddToCart?: (productId: string) => void; className?: string; }

export function ProductCard({ product, onAddToCart, className }: ProductCardProps) { // ... }

Fastify Patterns

Route Types

// modules/catalog/catalog.routes.ts import { FastifyPluginAsync } from 'fastify'; import { z } from 'zod';

const GetProductParams = z.object({ id: z.string().uuid(), });

const catalogRoutes: FastifyPluginAsync = async (fastify) => { fastify.get<{ Params: z.infer<typeof GetProductParams>; }>('/products/:id', { schema: { params: GetProductParams, }, }, async (request, reply) => { const { id } = request.params; // ... }); };

export default catalogRoutes;

Error Handling

// middleware/error-handler.ts import { FastifyError, FastifyReply, FastifyRequest } from 'fastify';

export function errorHandler( error: FastifyError, request: FastifyRequest, reply: FastifyReply ) { const statusCode = error.statusCode ?? 500;

reply.status(statusCode).send({ statusCode, error: error.name, message: error.message, }); }

Testing Patterns

Unit Tests (Vitest)

// tests/hooks/useProducts.test.tsx import { renderHook, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useProducts } from '@/hooks/useProducts';

const wrapper = ({ children }: { children: React.ReactNode }) => ( <QueryClientProvider client={new QueryClient()}> {children} </QueryClientProvider> );

describe('useProducts', () => { it('fetches products', async () => { const { result } = renderHook(() => useProducts(), { wrapper });

await waitFor(() => {
  expect(result.current.isSuccess).toBe(true);
});

expect(result.current.data).toHaveLength(18);

}); });

Integration Tests (Testcontainers)

// tests/integration/catalog.test.ts import { PostgreSqlContainer } from '@testcontainers/postgresql'; import { buildApp } from '../../src/app';

describe('Catalog API', () => { let container: StartedPostgreSqlContainer; let app: FastifyInstance;

beforeAll(async () => { container = await new PostgreSqlContainer().start(); process.env.DATABASE_URL = container.getConnectionUri(); app = await buildApp(); });

afterAll(async () => { await app.close(); await container.stop(); });

it('GET /products returns products', async () => { const response = await app.inject({ method: 'GET', url: '/api/products', });

expect(response.statusCode).toBe(200);

}); });

Commands

Type checking

npm run typecheck # All workspaces npm run typecheck -w apps/backend

Linting

npm run lint npm run lint:fix

Testing

npm run test # All tests npm run test -w apps/backend

Prisma

npm run db:generate -w apps/backend # Generate types npm run db:push -w apps/backend # Push schema npm run db:seed -w apps/backend # Seed data

Anti-Patterns

Anti-Pattern Problem Solution

any type No type safety Use unknown

  • type guards

Manual DB types Drift from schema Use Prisma generated types

Implicit returns Unclear API Explicit return types

No validation Runtime errors Zod at boundaries

// @ts-ignore

Hidden bugs Fix the type issue

Checklist

Before committing TypeScript changes:

  • No any types (use unknown if needed)

  • Zod schemas for API inputs

  • Prisma types for DB entities

  • Tests cover new functionality

  • npm run typecheck passes

  • npm run lint passes

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

spec-driven-dev

No summary provided by upstream source.

Repository SourceNeeds Review
General

trivy

No summary provided by upstream source.

Repository SourceNeeds Review
General

scm

No summary provided by upstream source.

Repository SourceNeeds Review
General

design-patterns

No summary provided by upstream source.

Repository SourceNeeds Review