Agent skill

Fullstack Dev

by HHU3637kr in HHU3637kr/skills

Full-stack backend architecture and frontend-backend integration guide.

MITAuto-check: notesBackend & APIs

Install Fullstack Dev

skills CLI
$ npx skills add HHU3637kr/skills --skill fullstack-dev -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install HHU3637kr/skills fullstack-dev --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/HHU3637kr/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/fullstack-dev .claude/skills/fullstack-dev && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
fullstack-dev
GitHub stars
145
Used in
3 other repos
Token cost
~8.6k tokens
SKILL.md length
1,519 words
Files
9 (incl. references)
Skills in repo
37
Repo updated
First seen
Licence
MIT

At a glance

Full-stack backend architecture and frontend-backend integration guide.

  • Works in 6 steps: Gather Requirements → Architectural Decisions → Scaffold with Checklist → …
  • : building a full-stack app
  • SKILL.md covers MANDATORY WORKFLOW — Follow…, Scope, Quick Start — New Backend… and Quick Start — Frontend-Backend…, plus 7 more sections
  • Calls npx, npm and curl; needs JWT_SECRET

What it does

Fullstack Dev is an agent skill from HHU3637kr/skills. Full-stack backend architecture and frontend-backend integration guide. TRIGGER when: building a full-stack app, creating REST API with frontend, scaffolding backend service, building todo app, building CRUD app, building real-time app, building chat app, Express + React, Next.js API, Node.js backend, Python backend, Go backend, designing service layers, implementing error handling, managing config/auth, setting up API clients, implementing auth flows, handling file uploads, adding real-time features…

Its SKILL.md is about 8.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 9 other files, including reference files (for example `references/api-design.md`, `references/auth-flow.md` and `references/db-schema.md`).

It sits in Backend & APIs, covering Realtime and WebSockets, Authentication and Project scaffolding. It works with React, Next.js, Python and Node.js. The licence is MIT.

When your agent uses it

  • : building a full-stack app
  • Creating REST API with frontend
  • Scaffolding backend service
  • Building todo app

Example prompts

  • “/fullstack-dev”

Requirements

  • Python 3
  • Node.js
  • A credential in JWT_SECRET

Workflow steps

6 steps, taken from the step headings in SKILL.md.

  1. Gather Requirements
  2. Architectural Decisions
  3. Scaffold with Checklist
  4. Implement Following Patterns
  5. Test & Verify
  6. Handoff Summary

What it can do on your machine

Read from SKILL.md and the folder at commit a2cccf6. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npx
    • npm
    • curl

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use npx, npm and curl, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • JWT_SECRET

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Fullstack Dev loads about 8.6k tokens when it runs, and up to ~30k if it reads all its reference files. Until then it costs about 162 tokens; SKILL.md has 1,519 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~162
When it runs · the whole SKILL.md, loaded when a task matches
~8.6k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~30k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:282
    env_file = ".env"
  • NoteMentions a .env fileSKILL.md:296
    ❌ Never commit .env files

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from HHU3637kr/skills at commit a2cccf6, republished under its MIT licence (© HHU3637kr). 1,519 words, ~8,626 tokens.

Download SKILL.mdSave it as .claude/skills/fullstack-dev/SKILL.md (or your agent's skills folder). This skill also uses 8 other files; get the full folder from GitHub.
name
fullstack-dev
description
Full-stack backend architecture and frontend-backend integration guide. TRIGGER when: building a full-stack app, creating REST API with frontend, scaffolding backend service, building todo app, building CRUD app, building real-time app, building chat app, Express + React, Next.js API, Node.js backend, Python backend, Go backend, designing service layers, implementing error handling, managing config/auth, setting up API clients, implementing auth flows, handling file uploads, adding real-time features (SSE/WebSocket), hardening for production. DO NOT TRIGGER when: pure frontend UI work, pure CSS/styling, database schema only.
disable-model-invocation
true
license
MIT
metadata.category
full-stack
metadata.version
1.0.0
metadata.sources
The Twelve-Factor App (12factor.net), Clean Architecture (Robert C. Martin), Domain-Driven Design (Eric Evans), Patterns of Enterprise Application…

Full-Stack Development Practices

MANDATORY WORKFLOW — Follow These Steps In Order

When this skill is triggered, you MUST follow this workflow before writing any code.

Step 0: Gather Requirements

Before scaffolding anything, ask the user to clarify (or infer from context):

  1. Stack: Language/framework for backend and frontend (e.g., Express + React, Django + Vue, Go + HTMX)
  2. Service type: API-only, full-stack monolith, or microservice?
  3. Database: SQL (PostgreSQL, SQLite, MySQL) or NoSQL (MongoDB, Redis)?
  4. Integration: REST, GraphQL, tRPC, or gRPC?
  5. Real-time: Needed? If yes — SSE, WebSocket, or polling?
  6. Auth: Needed? If yes — JWT, session, OAuth, or third-party (Clerk, Auth.js)?

If the user has already specified these in their request, skip asking and proceed.

Step 1: Architectural Decisions

Based on requirements, make and state these decisions before coding:

DecisionOptionsReference
Project structureFeature-first (recommended) vs layer-firstSection 1
API client approachTyped fetch / React Query / tRPC / OpenAPI codegenSection 5
Auth strategyJWT + refresh / session / third-partySection 6
Real-time methodPolling / SSE / WebSocketSection 11
Error handlingTyped error hierarchy + global handlerSection 3

Briefly explain each choice (1 sentence per decision).

Step 2: Scaffold with Checklist

Use the appropriate checklist below. Ensure ALL checked items are implemented — do not skip any.

Step 3: Implement Following Patterns

Write code following the patterns in this document. Reference specific sections as you implement each part.

Step 4: Test & Verify

After implementation, run these checks before claiming completion:

  1. Build check: Ensure both backend and frontend compile without errors
    bash
    # Backend
    cd server && npm run build
    # Frontend
    cd client && npm run build
  2. Start & smoke test: Start the server, verify key endpoints return expected responses
    bash
    # Start server, then test
    curl http://localhost:3000/health
    curl http://localhost:3000/api/<resource>
  3. Integration check: Verify frontend can connect to backend (CORS, API base URL, auth flow)
  4. Real-time check (if applicable): Open two browser tabs, verify changes sync

If any check fails, fix the issue before proceeding.

Step 5: Handoff Summary

Provide a brief summary to the user:

  • What was built: List of implemented features and endpoints
  • How to run: Exact commands to start backend and frontend
  • What's missing / next steps: Any deferred items, known limitations, or recommended improvements
  • Key files: List the most important files the user should know about

Scope

USE this skill when:

  • Building a full-stack application (backend + frontend)
  • Scaffolding a new backend service or API
  • Designing service layers and module boundaries
  • Implementing database access, caching, or background jobs
  • Writing error handling, logging, or configuration management
  • Reviewing backend code for architectural issues
  • Hardening for production
  • Setting up API clients, auth flows, file uploads, or real-time features

NOT for:

  • Pure frontend/UI concerns (use your frontend framework's docs)
  • Pure database schema design without backend context

Quick Start — New Backend Service Checklist

  • Project scaffolded with feature-first structure
  • Configuration centralized, env vars validated at startup (fail fast)
  • Typed error hierarchy defined (not generic Error)
  • Global error handler middleware
  • Structured JSON logging with request ID propagation
  • Database: migrations set up, connection pooling configured
  • Input validation on all endpoints (Zod / Pydantic / Go validator)
  • Authentication middleware in place
  • Health check endpoints (/health, /ready)
  • Graceful shutdown handling (SIGTERM)
  • CORS configured (explicit origins, not *)
  • Security headers (helmet or equivalent)
  • .env.example committed (no real secrets)

Quick Start — Frontend-Backend Integration Checklist

  • API client configured (typed fetch wrapper, React Query, tRPC, or OpenAPI generated)
  • Base URL from environment variable (not hardcoded)
  • Auth token attached to requests automatically (interceptor / middleware)
  • Error handling — API errors mapped to user-facing messages
  • Loading states handled (skeleton/spinner, not blank screen)
  • Type safety across the boundary (shared types, OpenAPI, or tRPC)
  • CORS configured with explicit origins (not * in production)
  • Refresh token flow implemented (httpOnly cookie + transparent retry on 401)

Quick Navigation

Need to…Jump to
Organize project folders1. Project Structure
Manage config + secrets2. Configuration
Handle errors properly3. Error Handling
Write database code4. Database Access Patterns
Set up API client from frontend5. API Client Patterns
Add auth middleware6. Auth & Middleware
Set up logging7. Logging & Observability
Add background jobs8. Background Jobs
Implement caching9. Caching
Upload files (presigned URL, multipart)10. File Upload Patterns
Add real-time features (SSE, WebSocket)11. Real-Time Patterns
Handle API errors in frontend UI12. Cross-Boundary Error Handling
Harden for production13. Production Hardening
Design API endpointsAPI Design
Design database schemaDatabase Schema
Auth flow (JWT, refresh, Next.js SSR, RBAC)references/auth-flow.md
CORS, env vars, environment managementreferences/environment-management.md

Core Principles (7 Iron Rules)

1. ✅ Organize by FEATURE, not by technical layer
2. ✅ Controllers never contain business logic
3. ✅ Services never import HTTP request/response types
4. ✅ All config from env vars, validated at startup, fail fast
5. ✅ Every error is typed, logged, and returns consistent format
6. ✅ All input validated at the boundary — trust nothing from client
7. ✅ Structured JSON logging with request ID — not console.log

1. Project Structure & Layering (CRITICAL)

Feature-First Organization
✅ Feature-first                    ❌ Layer-first
src/                                src/
  orders/                             controllers/
    order.controller.ts                 order.controller.ts
    order.service.ts                    user.controller.ts
    order.repository.ts               services/
    order.dto.ts                        order.service.ts
    order.test.ts                       user.service.ts
  users/                              repositories/
    user.controller.ts                  ...
    user.service.ts
  shared/
    database/
    middleware/
Three-Layer Architecture
Controller (HTTP) → Service (Business Logic) → Repository (Data Access)
LayerResponsibility❌ Never
ControllerParse request, validate, call service, format responseBusiness logic, DB queries
ServiceBusiness rules, orchestration, transaction mgmtHTTP types (req/res), direct DB
RepositoryDatabase queries, external API callsBusiness logic, HTTP types
Dependency Injection (All Languages)

TypeScript:

typescript
class OrderService {
  constructor(
    private readonly orderRepo: OrderRepository,    // ✅ injected interface
    private readonly emailService: EmailService,
  ) {}
}

Python:

python
class OrderService:
    def __init__(self, order_repo: OrderRepository, email_service: EmailService):
        self.order_repo = order_repo                 # ✅ injected
        self.email_service = email_service

Go:

go
type OrderService struct {
    orderRepo    OrderRepository                      // ✅ interface
    emailService EmailService
}

func NewOrderService(repo OrderRepository, email EmailService) *OrderService {
    return &OrderService{orderRepo: repo, emailService: email}
}

2. Configuration & Environment (CRITICAL)

Centralized, Typed, Fail-Fast

TypeScript:

typescript
const config = {
  port: parseInt(process.env.PORT || '3000', 10),
  database: { url: requiredEnv('DATABASE_URL'), poolSize: intEnv('DB_POOL_SIZE', 10) },
  auth: { jwtSecret: requiredEnv('JWT_SECRET'), expiresIn: process.env.JWT_EXPIRES_IN || '1h' },
} as const;

function requiredEnv(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Missing required env var: ${name}`);  // fail fast
  return value;
}

Python:

python
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    database_url: str                        # required — app won't start without it
    jwt_secret: str                          # required
    port: int = 3000                         # optional with default
    db_pool_size: int = 10
    class Config:
        env_file = ".env"

settings = Settings()                        # fails fast if DATABASE_URL missing
Rules
✅ All config via environment variables (Twelve-Factor)
✅ Validate required vars at startup — fail fast
✅ Type-cast at config layer, not at usage sites
✅ Commit .env.example with dummy values

❌ Never hardcode secrets, URLs, or credentials
❌ Never commit .env files
❌ Never scatter process.env / os.environ throughout code

3. Error Handling & Resilience (HIGH)

Typed Error Hierarchy
typescript
// Base (TypeScript)
class AppError extends Error {
  constructor(
    message: string,
    public readonly code: string,
    public readonly statusCode: number,
    public readonly isOperational: boolean = true,
  ) { super(message); }
}
class NotFoundError extends AppError {
  constructor(resource: string, id: string) {
    super(`${resource} not found: ${id}`, 'NOT_FOUND', 404);
  }
}
class ValidationError extends AppError {
  constructor(public readonly errors: FieldError[]) {
    super('Validation failed', 'VALIDATION_ERROR', 422);
  }
}
python
# Base (Python)
class AppError(Exception):
    def __init__(self, message: str, code: str, status_code: int):
        self.message, self.code, self.status_code = message, code, status_code

class NotFoundError(AppError):
    def __init__(self, resource: str, id: str):
        super().__init__(f"{resource} not found: {id}", "NOT_FOUND", 404)
Global Error Handler
typescript
// TypeScript (Express)
app.use((err, req, res, next) => {
  if (err instanceof AppError && err.isOperational) {
    return res.status(err.statusCode).json({
      title: err.code, status: err.statusCode,
      detail: err.message, request_id: req.id,
    });
  }
  logger.error('Unexpected error', { error: err.message, stack: err.stack, request_id: req.id });
  res.status(500).json({ title: 'Internal Error', status: 500, request_id: req.id });
});
Rules
✅ Typed, domain-specific error classes
✅ Global error handler catches everything
✅ Operational errors → structured response
✅ Programming errors → log + generic 500
✅ Retry transient failures with exponential backoff

❌ Never catch and ignore errors silently
❌ Never return stack traces to client
❌ Never throw generic Error('something')

4. Database Access Patterns (HIGH)

Migrations Always
bash
# TypeScript (Prisma)           # Python (Alembic)              # Go (golang-migrate)
npx prisma migrate dev          alembic revision --autogenerate  migrate -source file://migrations
npx prisma migrate deploy       alembic upgrade head             migrate -database $DB up
✅ Schema changes via migrations, never manual SQL
✅ Migrations must be reversible
✅ Review migration SQL before production
❌ Never modify production schema manually
N+1 Prevention
typescript
// ❌ N+1: 1 query + N queries
const orders = await db.order.findMany();
for (const o of orders) { o.items = await db.item.findMany({ where: { orderId: o.id } }); }

// ✅ Single JOIN query
const orders = await db.order.findMany({ include: { items: true } });
Transactions for Multi-Step Writes
typescript
await db.$transaction(async (tx) => {
  const order = await tx.order.create({ data: orderData });
  await tx.inventory.decrement({ productId, quantity });
  await tx.payment.create({ orderId: order.id, amount });
});
Connection Pooling

Pool size = (CPU cores × 2) + spindle_count (start with 10-20). Always set connection timeout. Use PgBouncer for serverless.


5. API Client Patterns (MEDIUM)

The "glue layer" between frontend and backend. Choose the approach that fits your team and stack.

Option A: Typed Fetch Wrapper (Simple, No Dependencies)
typescript
// lib/api-client.ts
const BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';

class ApiError extends Error {
  constructor(public status: number, public body: any) {
    super(body?.detail || body?.message || `API error ${status}`);
  }
}

async function api<T>(path: string, options: RequestInit = {}): Promise<T> {
  const token = getAuthToken();  // from cookie / memory / context

  const res = await fetch(`${BASE_URL}${path}`, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...options.headers,
    },
  });

  if (!res.ok) {
    const body = await res.json().catch(() => null);
    throw new ApiError(res.status, body);
  }

  if (res.status === 204) return undefined as T;
  return res.json();
}

export const apiClient = {
  get: <T>(path: string) => api<T>(path),
  post: <T>(path: string, data: unknown) => api<T>(path, { method: 'POST', body: JSON.stringify(data) }),
  put: <T>(path: string, data: unknown) => api<T>(path, { method: 'PUT', body: JSON.stringify(data) }),
  patch: <T>(path: string, data: unknown) => api<T>(path, { method: 'PATCH', body: JSON.stringify(data) }),
  delete: <T>(path: string) => api<T>(path, { method: 'DELETE' }),
};
typescript
// hooks/use-orders.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/lib/api-client';

interface Order { id: string; total: number; status: string; }
interface CreateOrderInput { items: { productId: string; quantity: number }[] }

export function useOrders() {
  return useQuery({
    queryKey: ['orders'],
    queryFn: () => apiClient.get<{ data: Order[] }>('/api/orders'),
    staleTime: 1000 * 60,  // 1 min
  });
}

export function useCreateOrder() {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: (data: CreateOrderInput) =>
      apiClient.post<{ data: Order }>('/api/orders', data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['orders'] });
    },
  });
}

// Usage in component:
function OrdersPage() {
  const { data, isLoading, error } = useOrders();
  const createOrder = useCreateOrder();
  if (isLoading) return <Skeleton />;
  if (error) return <ErrorBanner error={error} />;
  // ...
}
Option C: tRPC (Same Team Owns Both Sides)
typescript
// server: trpc/router.ts
export const appRouter = router({
  orders: router({
    list: publicProcedure.query(async () => {
      return db.order.findMany({ include: { items: true } });
    }),
    create: protectedProcedure
      .input(z.object({ items: z.array(orderItemSchema) }))
      .mutation(async ({ input, ctx }) => {
        return orderService.create(ctx.user.id, input);
      }),
  }),
});
export type AppRouter = typeof appRouter;

// client: automatic type safety, no code generation
const { data } = trpc.orders.list.useQuery();
const createOrder = trpc.orders.create.useMutation();
Option D: OpenAPI Generated Client (Public / Multi-Consumer APIs)
bash
npx openapi-typescript-codegen \
  --input http://localhost:3001/api/openapi.json \
  --output src/generated/api \
  --client axios
Decision: Which API Client?
ApproachWhenType SafetyEffort
Typed fetch wrapperSimple apps, small teamsManual typesLow
React Query + fetchReact apps, server stateManual typesMedium
tRPCSame team, TypeScript both sidesAutomaticLow
OpenAPI generatedPublic API, multi-consumerAutomaticMedium
GraphQL codegenGraphQL APIsAutomaticMedium

Show full SKILL.md (603 more words)Show less

6. Authentication & Middleware (HIGH)

Full reference: references/auth-flow.md — JWT bearer flow, automatic token refresh, Next.js server-side auth, RBAC pattern, backend middleware order.

Standard Middleware Order
Request → 1.RequestID → 2.Logging → 3.CORS → 4.RateLimit → 5.BodyParse
       → 6.Auth → 7.Authz → 8.Validation → 9.Handler → 10.ErrorHandler → Response
JWT Rules
✅ Short expiry access token (15min) + refresh token (server-stored)
✅ Minimal claims: userId, roles (not entire user object)
✅ Rotate signing keys periodically

❌ Never store tokens in localStorage (XSS risk)
❌ Never pass tokens in URL query params
RBAC Pattern
typescript
function authorize(...roles: Role[]) {
  return (req, res, next) => {
    if (!req.user) throw new UnauthorizedError();
    if (!roles.some(r => req.user.roles.includes(r))) throw new ForbiddenError();
    next();
  };
}
router.delete('/users/:id', authenticate, authorize('admin'), deleteUser);
Auth Token Automatic Refresh
typescript
// lib/api-client.ts — transparent refresh on 401
async function apiWithRefresh<T>(path: string, options: RequestInit = {}): Promise<T> {
  try {
    return await api<T>(path, options);
  } catch (err) {
    if (err instanceof ApiError && err.status === 401) {
      const refreshed = await api<{ accessToken: string }>('/api/auth/refresh', {
        method: 'POST',
        credentials: 'include',  // send httpOnly cookie
      });
      setAuthToken(refreshed.accessToken);
      return api<T>(path, options);  // retry
    }
    throw err;
  }
}

7. Logging & Observability (MEDIUM-HIGH)

Structured JSON Logging
typescript
// ✅ Structured — parseable, filterable, alertable
logger.info('Order created', {
  orderId: order.id, userId: user.id, total: order.total,
  items: order.items.length, duration_ms: Date.now() - startTime,
});
// Output: {"level":"info","msg":"Order created","orderId":"ord_123",...}

// ❌ Unstructured — useless at scale
console.log(`Order created for user ${user.id} with total ${order.total}`);
Log Levels
LevelWhenProduction?
errorRequires immediate attention✅ Always
warnUnexpected but handled✅ Always
infoNormal operations, audit trail✅ Always
debugDev troubleshooting❌ Dev only
Rules
✅ Request ID in every log entry (propagated via middleware)
✅ Log at layer boundaries (request in, response out, external call)
❌ Never log passwords, tokens, PII, or secrets
❌ Never use console.log in production code

8. Background Jobs & Async (MEDIUM)

Rules
✅ All jobs must be IDEMPOTENT (same job running twice = same result)
✅ Failed jobs → retry (max 3) → dead letter queue → alert
✅ Workers run as SEPARATE processes (not threads in API server)

❌ Never put long-running tasks in request handlers
❌ Never assume job runs exactly once
Idempotent Job Pattern
typescript
async function processPayment(data: { orderId: string }) {
  const order = await orderRepo.findById(data.orderId);
  if (order.paymentStatus === 'completed') return;  // already processed
  await paymentGateway.charge(order);
  await orderRepo.updatePaymentStatus(order.id, 'completed');
}

9. Caching Patterns (MEDIUM)

Cache-Aside (Lazy Loading)
typescript
async function getUser(id: string): Promise<User> {
  const cached = await redis.get(`user:${id}`);
  if (cached) return JSON.parse(cached);

  const user = await userRepo.findById(id);
  if (!user) throw new NotFoundError('User', id);

  await redis.set(`user:${id}`, JSON.stringify(user), 'EX', 900);  // 15min TTL
  return user;
}
Rules
✅ ALWAYS set TTL — never cache without expiry
✅ Invalidate on write (delete cache key after update)
✅ Use cache for reads, never for authoritative state

❌ Never cache without TTL (stale data is worse than slow data)
Data TypeSuggested TTL
User profile5-15 min
Product catalog1-5 min
Config / feature flags30-60 sec
SessionMatch session duration

10. File Upload Patterns (MEDIUM)

Client → GET /api/uploads/presign?filename=photo.jpg&type=image/jpeg
Server → { uploadUrl: "https://s3.../presigned", fileKey: "uploads/abc123.jpg" }
Client → PUT uploadUrl (direct to S3, bypasses your server)
Client → POST /api/photos { fileKey: "uploads/abc123.jpg" }  (save reference)

Backend:

typescript
app.get('/api/uploads/presign', authenticate, async (req, res) => {
  const { filename, type } = req.query;
  const key = `uploads/${crypto.randomUUID()}-${filename}`;
  const url = await s3.getSignedUrl('putObject', {
    Bucket: process.env.S3_BUCKET, Key: key,
    ContentType: type, Expires: 300,  // 5 min
  });
  res.json({ uploadUrl: url, fileKey: key });
});

Frontend:

typescript
async function uploadFile(file: File) {
  const { uploadUrl, fileKey } = await apiClient.get<PresignResponse>(
    `/api/uploads/presign?filename=${file.name}&type=${file.type}`
  );
  await fetch(uploadUrl, { method: 'PUT', body: file, headers: { 'Content-Type': file.type } });
  return apiClient.post('/api/photos', { fileKey });
}
Option B: Multipart (Small Files < 10MB)
typescript
// Frontend
const formData = new FormData();
formData.append('file', file);
formData.append('description', 'Profile photo');
const res = await fetch('/api/upload', { method: 'POST', body: formData });
// Note: do NOT set Content-Type header — browser sets boundary automatically
Decision
MethodFile SizeServer LoadComplexity
Presigned URLAny (recommended > 5MB)None (direct to storage)Medium
Multipart< 10MBHigh (streams through server)Low
Chunked / Resumable> 100MBMediumHigh

11. Real-Time Patterns (MEDIUM)

Option A: Server-Sent Events (SSE) — One-Way Server → Client

Best for: notifications, live feeds, streaming AI responses.

Backend (Express):

typescript
app.get('/api/events', authenticate, (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    Connection: 'keep-alive',
  });
  const send = (event: string, data: unknown) => {
    res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
  };
  const unsubscribe = eventBus.subscribe(req.user.id, (event) => {
    send(event.type, event.payload);
  });
  req.on('close', () => unsubscribe());
});

Frontend:

typescript
function useServerEvents(userId: string) {
  useEffect(() => {
    const source = new EventSource(`/api/events?userId=${userId}`);
    source.addEventListener('notification', (e) => {
      showToast(JSON.parse(e.data).message);
    });
    source.onerror = () => { source.close(); setTimeout(() => /* reconnect */, 3000); };
    return () => source.close();
  }, [userId]);
}
Option B: WebSocket — Bidirectional

Best for: chat, collaborative editing, gaming.

Backend (ws library):

typescript
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ server: httpServer, path: '/ws' });
wss.on('connection', (ws, req) => {
  const userId = authenticateWs(req);
  if (!userId) { ws.close(4001, 'Unauthorized'); return; }
  ws.on('message', (raw) => handleMessage(userId, JSON.parse(raw.toString())));
  ws.on('close', () => cleanupUser(userId));
  const interval = setInterval(() => ws.ping(), 30000);
  ws.on('pong', () => { /* alive */ });
  ws.on('close', () => clearInterval(interval));
});

Frontend:

typescript
function useWebSocket(url: string) {
  const [ws, setWs] = useState<WebSocket | null>(null);
  useEffect(() => {
    const socket = new WebSocket(url);
    socket.onopen = () => setWs(socket);
    socket.onclose = () => setTimeout(() => /* reconnect */, 3000);
    return () => socket.close();
  }, [url]);
  const send = useCallback((data: unknown) => ws?.send(JSON.stringify(data)), [ws]);
  return { ws, send };
}
Option C: Polling (Simplest, No Infrastructure)
typescript
function useOrderStatus(orderId: string) {
  return useQuery({
    queryKey: ['order-status', orderId],
    queryFn: () => apiClient.get<Order>(`/api/orders/${orderId}`),
    refetchInterval: (query) => {
      if (query.state.data?.status === 'completed') return false;
      return 5000;
    },
  });
}
Decision
MethodDirectionComplexityWhen
PollingClient → ServerLowSimple status checks, < 10 clients
SSEServer → ClientMediumNotifications, feeds, AI streaming
WebSocketBidirectionalHighChat, collaboration, gaming

12. Cross-Boundary Error Handling (MEDIUM)

API Error → User-Facing Message
typescript
// lib/error-handler.ts
export function getErrorMessage(error: unknown): string {
  if (error instanceof ApiError) {
    switch (error.status) {
      case 401: return 'Please log in to continue.';
      case 403: return 'You don\'t have permission to do this.';
      case 404: return 'The item you\'re looking for doesn\'t exist.';
      case 409: return 'This conflicts with an existing item.';
      case 422:
        const fields = error.body?.errors;
        if (fields?.length) return fields.map((f: any) => f.message).join('. ');
        return 'Please check your input.';
      case 429: return 'Too many requests. Please wait a moment.';
      default: return 'Something went wrong. Please try again.';
    }
  }
  if (error instanceof TypeError && error.message === 'Failed to fetch') {
    return 'Cannot connect to server. Check your internet connection.';
  }
  return 'An unexpected error occurred.';
}
React Query Global Error Handler
typescript
const queryClient = new QueryClient({
  defaultOptions: {
    mutations: { onError: (error) => toast.error(getErrorMessage(error)) },
    queries: {
      retry: (failureCount, error) => {
        if (error instanceof ApiError && error.status < 500) return false;
        return failureCount < 3;
      },
    },
  },
});
Rules
✅ Map every API error code to a human-readable message
✅ Show field-level validation errors next to form inputs
✅ Auto-retry on 5xx (max 3, with backoff), never on 4xx
✅ Redirect to login on 401 (after refresh attempt fails)
✅ Show "offline" banner when fetch fails with TypeError

❌ Never show raw API error messages to users ("NullPointerException")
❌ Never silently swallow errors (show toast or log)
❌ Never retry 4xx errors (client is wrong, retrying won't help)
Integration Decision Tree
Same team owns frontend + backend?
│
├─ YES, both TypeScript
│   └─ tRPC (end-to-end type safety, zero codegen)
│
├─ YES, different languages
│   └─ OpenAPI spec → generated client (type safety via codegen)
│
├─ NO, public API
│   └─ REST + OpenAPI → generated SDKs for consumers
│
└─ Complex data needs, multiple frontends
    └─ GraphQL + codegen (flexible queries per client)

Real-time needed?
│
├─ Server → Client only (notifications, feeds, AI streaming)
│   └─ SSE (simplest, auto-reconnect, works through proxies)
│
├─ Bidirectional (chat, collaboration)
│   └─ WebSocket (need heartbeat + reconnection logic)
│
└─ Simple status polling (< 10 clients)
    └─ React Query refetchInterval (no infrastructure needed)

13. Production Hardening (MEDIUM)

Health Checks
typescript
app.get('/health', (req, res) => res.json({ status: 'ok' }));           // liveness
app.get('/ready', async (req, res) => {                                   // readiness
  const checks = {
    database: await checkDb(), redis: await checkRedis(), 
  };
  const ok = Object.values(checks).every(c => c.status === 'ok');
  res.status(ok ? 200 : 503).json({ status: ok ? 'ok' : 'degraded', checks });
});
Graceful Shutdown
typescript
process.on('SIGTERM', async () => {
  logger.info('SIGTERM received');
  server.close();              // stop new connections
  await drainConnections();    // finish in-flight
  await closeDatabase();
  process.exit(0);
});
Security Checklist
✅ CORS: explicit origins (never '*' in production)
✅ Security headers (helmet / equivalent)
✅ Rate limiting on public endpoints
✅ Input validation on ALL endpoints (trust nothing)
✅ HTTPS enforced
❌ Never expose internal errors to clients

Anti-Patterns

#❌ Don't✅ Do Instead
1Business logic in routes/controllersMove to service layer
2process.env scattered everywhereCentralized typed config
3console.log for loggingStructured JSON logger
4Generic Error('oops')Typed error hierarchy
5Direct DB calls in controllersRepository pattern
6No input validationValidate at boundary (Zod/Pydantic)
7Catching errors silentlyLog + rethrow or return error
8No health check endpoints/health + /ready
9Hardcoded config/secretsEnvironment variables
10No graceful shutdownHandle SIGTERM properly
11Hardcode API URL in frontendEnvironment variable (NEXT_PUBLIC_API_URL)
12Store JWT in localStorageMemory + httpOnly refresh cookie
13Show raw API errors to usersMap to human-readable messages
14Retry 4xx errorsOnly retry 5xx (server failures)
15Skip loading statesSkeleton/spinner while fetching
16Upload large files through API serverPresigned URL → direct to S3
17Poll for real-time dataSSE or WebSocket
18Duplicate types frontend + backendShared types, tRPC, or OpenAPI codegen

Common Issues

Issue 1: "Where does this business rule go?"

Rule: If it involves HTTP (request parsing, status codes, headers) → controller. If it involves business decisions (pricing, permissions, rules) → service. If it touches the database → repository.

Issue 2: "Service is getting too big"

Symptom: One service file > 500 lines with 20+ methods.

Fix: Split by sub-domain. OrderService → OrderCreationService + OrderFulfillmentService + OrderQueryService. Each focused on one workflow.

Issue 3: "Tests are slow because they hit the database"

Fix: Unit tests mock the repository layer (fast). Integration tests use test containers or transaction rollback (real DB, still fast). Never mock the service layer in integration tests.


Reference Documents

This skill includes deep-dive references for specialized topics. Read the relevant reference when you need detailed guidance.

Need to…Reference
Write backend tests (unit, integration, e2e, contract, performance)references/testing-strategy.md
Validate a release before deployment (6-gate checklist)references/release-checklist.md
Choose a tech stack (language, framework, database, infra)references/technology-selection.md
Build with Django / DRF (models, views, serializers, admin)references/django-best-practices.md
Design REST/GraphQL/gRPC endpoints (URLs, status codes, pagination)references/api-design.md
Design database schema, indexes, migrations, multi-tenancyreferences/db-schema.md
Auth flow (JWT bearer, token refresh, Next.js SSR, RBAC, middleware order)references/auth-flow.md
CORS config, env vars per environment, common CORS issuesreferences/environment-management.md

© HHU3637kr, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 8 other files (references) in fullstack-dev of HHU3637kr/skills.

  • SKILL.md
  • references/api-design.md
  • references/auth-flow.md
  • references/db-schema.md
  • references/django-best-practices.md
  • references/environment-management.md
  • references/release-checklist.md
  • references/technology-selection.md
  • references/testing-strategy.md

Open the folder on GitHubat commit a2cccf6

Used in 3 other repositories

We found 8 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 3 other GitHub owners. This page covers the copy in HHU3637kr/skills, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Fullstack Dev next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Fullstack Dev compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Fullstack Dev this skillHHU3637kr/skills1453 repos~8.6kAutomated safety check: NotesMIT
Fullstack Devinfometa/workbuddyskills342—~1kAutomated safety check: PassMIT
Vercel Functionsvercel/vercel-plugin301—~12kAutomated safety check: NotesCustom licence
Clerk Setupgrowupanand/ConvoForm101—~3kAutomated safety check: PassMIT
Documentation LookupKaimingWan/oh-my-kiro107—~616Automated safety check: PassMIT
FastAPI ExpertJeffallan/claude-skills12k—~1.8kAutomated safety check: PassMIT

Similar skills

  • Fullstack Dev

    infometa/workbuddyskills

    Full-stack backend architecture and frontend-backend integration guide.

    342 GitHub stars~1k tokensUpdated yesterday
    Backend & APIsAuto-check passed
  • Vercel Functions

    vercel/vercel-plugin

    Official

    Vercel Functions expert guidance — Node.js/Bun/Python runtimes, Fluid Compute, long-duration (30 min) functions, large functions (5 GB bundles), Docker/OCI container images, plan limits, streaming…

    301 GitHub stars~12k tokensUpdated yesterday
    Backend & APIsAuto-check: notes
  • Clerk Setup

    growupanand/ConvoForm

    Set up Clerk authentication in any project with the Clerk CLI and official framework quickstarts.

    101 GitHub stars~3k tokensUpdated yesterday
    Backend & APIsAuto-check passed
  • Documentation Lookup

    KaimingWan/oh-my-kiro

    Fetch current library/framework documentation via Context7. An agent skill from KaimingWan/oh-my-kiro.

    107 GitHub stars~616 tokensUpdated 6 mo ago
    Backend & APIsAuto-check passed
  • FastAPI Expert

    Jeffallan/claude-skills

    Builds async Python APIs with FastAPI and Pydantic V2, covering endpoints, JWT authentication, async SQLAlchemy, WebSockets and pytest checks against the OpenAPI docs.

    12k GitHub stars~1.8k tokensUpdated 4 days ago
    Backend & APIsAuto-check passed
  • Senior Backend

    davila7/claude-code-templates

    Comprehensive backend development skill for building scalable backend systems using NodeJS, Express, Go, Python, Postgres, GraphQL, REST APIs.

    32k GitHub starsUsed in 1 repo~1.1k tokens
    Backend & APIsAuto-check: notes

More from HHU3637kr/skills

All 37 skills in this repo
  • Gif Sticker Maker

    HHU3637kr/skills

    Convert photos (people, pets, objects, logos) into 4 animated GIF stickers with captions.

    145 GitHub starsUsed in 3 repos~1.3k tokens
    Auto-check passed
  • Agent Browser

    HHU3637kr/skills

    Headless browser automation for AI agents using agent-browser CLI.

    145 GitHub stars~1.9k tokensUpdated 14 days ago
    Auto-check passed
  • Darwin Skill

    HHU3637kr/skills

    Darwin Skill (达尔文.skill): autonomous skill optimizer inspired by Karpathy's autoresearch.

    145 GitHub starsUsed in 1 repo~2.2k tokens
    Auto-check passed
  • Token Efficiency

    HHU3637kr/skills

    Cross-platform token audit and optimization for AI coding agents (Cursor, Codex, Claude Code, Hermes, Windsurf, Cline, OpenClaw, Gemini CLI, Aider).

    145 GitHub stars~842 tokensUpdated 14 days ago
    Auto-check passed
  • Guizang Ppt Skill

    HHU3637kr/skills

    生成横向翻页网页 PPT(单 HTML 文件),含 WebGL 背景、章节幕封、数据大字报、图片网格等模板。提供两种风格:① "电子杂志 × 电子墨水"(衬线 + 流体背景 + 暖色) ② "瑞士国际主义"(无衬线 + 网格点阵 + IKB/柠檬黄/柠檬绿/安全橙高亮)。当用户需要制作分享 / 演讲 / 发布会风格的网页 PPT,或提到"杂志风 PPT"、"瑞士风 PPT"、"Swiss…

    145 GitHub starsUsed in 1 repo~4.7k tokens
    Auto-check passed
  • Huashu Nuwa

    HHU3637kr/skills

    女娲造人:输入人名/主题/甚至只是模糊需求,自动深度调研→思维框架提炼→生成可运行的人物Skill. An agent skill from HHU3637kr/skills.

    145 GitHub starsUsed in 1 repo~4k tokens
    Auto-check passed

Categories

Questions about Fullstack Dev

What does Fullstack Dev do?

Full-stack backend architecture and frontend-backend integration guide. Fullstack Dev is an agent skill from HHU3637kr/skills. Full-stack backend architecture and frontend-backend integration guide.

When should I use Fullstack Dev?

Fullstack Dev fits situations like: : building a full-stack app; creating REST API with frontend; scaffolding backend service; building todo app.

How do I install Fullstack Dev in Claude Code?

Run `npx skills add HHU3637kr/skills --skill fullstack-dev -a claude-code`. Or copy the skill folder (fullstack-dev in HHU3637kr/skills) into .claude/skills/fullstack-dev in your project. Claude Code loads it when a task matches its description.

How do I install Fullstack Dev in Codex?

Run `npx skills add HHU3637kr/skills --skill fullstack-dev -a codex`. Or copy the skill folder (fullstack-dev in HHU3637kr/skills) into .agents/skills/fullstack-dev in your project. Codex loads it when a task matches its description.

Can I use Fullstack Dev in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add HHU3637kr/skills --skill fullstack-dev -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/fullstack-dev, .gemini/skills/fullstack-dev, .github/skills/fullstack-dev and .opencode/skills/fullstack-dev in your project.

What does Fullstack Dev need to run?

Going by SKILL.md and its folder, Fullstack Dev needs the command-line tools its instructions call (npx, npm and curl) and credentials named JWT_SECRET. Our summary lists: Python 3; Node.js; A credential in JWT_SECRET.

Does Fullstack Dev access the network?

SKILL.md contains no URLs. Its commands use npx, npm and curl, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Fullstack Dev safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Fullstack Dev use?

Fullstack Dev is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Fullstack Dev use?

About 8.6k tokens (SKILL.md is roughly 35k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 22k tokens, read only when the agent opens those files.

What are the alternatives to Fullstack Dev?

Skills that share tags, products or a category with Fullstack Dev: Fullstack Dev (infometa/workbuddyskills, 342 stars), Vercel Functions (vercel/vercel-plugin, 301 stars), Clerk Setup (growupanand/ConvoForm, 101 stars) and Documentation Lookup (KaimingWan/oh-my-kiro, 107 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Fullstack Dev?

HHU3637kr (a GitHub user) maintains it in HHU3637kr/skills, which has 145 GitHub stars. The repository holds 37 skills in this directory. The repository was last updated on September 23, 2026.

Source: HHU3637kr/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.