Senior Fullstack Expert
Comprehensive skill designed for comprehensive, fullstack, development, skill. Includes structured workflows, validation checks, and reusable patterns for development.
Senior Fullstack Expert
A comprehensive skill for senior fullstack engineers covering frontend-backend integration, API design, database optimization, authentication flows, and end-to-end application architecture with modern web stacks.
When to Use This Skill
Choose this skill when:
- Building end-to-end features spanning frontend, API, and database layers
- Designing API contracts and data flows between client and server
- Implementing authentication/authorization across the full stack
- Optimizing database queries and frontend rendering together
- Setting up full-stack development environments and tooling
Consider alternatives when:
- Need deep frontend framework expertise → use a React/Vue/Angular skill
- Working only on backend APIs → use a backend/API design skill
- Need database design specifically → use a database design skill
- Building mobile apps → use a React Native or mobile skill
Quick Start
// Full-stack feature: User Profile with optimistic updates // 1. API Route (Next.js App Router) // app/api/profile/route.ts import { NextRequest, NextResponse } from 'next/server'; import { auth } from '@/lib/auth'; import { db } from '@/lib/db'; import { z } from 'zod'; const updateSchema = z.object({ name: z.string().min(1).max(100), bio: z.string().max(500).optional(), avatarUrl: z.string().url().optional(), }); export async function PUT(req: NextRequest) { const session = await auth(); if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); const body = updateSchema.parse(await req.json()); const user = await db.user.update({ where: { id: session.user.id }, data: body, select: { id: true, name: true, bio: true, avatarUrl: true }, }); return NextResponse.json(user); }
Core Concepts
Full-Stack Architecture Layers
| Layer | Technology | Responsibility |
|---|---|---|
| Client State | React Query / SWR | Server state cache, optimistic updates |
| UI Components | React + Tailwind | Rendering, user interaction |
| API Layer | Next.js Routes / Express | Request handling, validation, auth |
| Business Logic | Service classes | Domain rules, orchestration |
| Data Access | Prisma / Drizzle | Database queries, migrations |
| Database | PostgreSQL / MongoDB | Data persistence, indexing |
Optimistic Update Pattern (Full Stack)
// Frontend: React Query mutation with optimistic update function useUpdateProfile() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: ProfileUpdate) => fetch('/api/profile', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }).then(r => { if (!r.ok) throw new Error('Update failed'); return r.json(); }), onMutate: async (newData) => { await queryClient.cancelQueries({ queryKey: ['profile'] }); const previous = queryClient.getQueryData(['profile']); queryClient.setQueryData(['profile'], (old: Profile) => ({ ...old, ...newData })); return { previous }; }, onError: (err, variables, context) => { queryClient.setQueryData(['profile'], context?.previous); toast.error('Failed to update profile'); }, onSettled: () => { queryClient.invalidateQueries({ queryKey: ['profile'] }); }, }); }
Authentication Flow (Full Stack)
// Middleware for route protection // middleware.ts import { NextResponse } from 'next/server'; import { getToken } from 'next-auth/jwt'; export async function middleware(req) { const token = await getToken({ req }); const isAuth = !!token; const isAuthPage = req.nextUrl.pathname.startsWith('/auth'); const isApiRoute = req.nextUrl.pathname.startsWith('/api'); const isPublicApi = req.nextUrl.pathname.startsWith('/api/public'); if (isAuthPage && isAuth) { return NextResponse.redirect(new URL('/dashboard', req.url)); } if (!isAuth && !isAuthPage && !isPublicApi) { if (isApiRoute) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } return NextResponse.redirect(new URL('/auth/login', req.url)); } return NextResponse.next(); } export const config = { matcher: ['/dashboard/:path*', '/api/:path*', '/auth/:path*'], };
Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
framework | string | 'nextjs' | Fullstack framework: nextjs, remix, or nuxt |
orm | string | 'prisma' | ORM: prisma, drizzle, or typeorm |
authProvider | string | 'next-auth' | Auth: next-auth, clerk, or lucia |
stateManagement | string | 'react-query' | Server state: react-query, swr, or trpc |
cssFramework | string | 'tailwind' | Styling: tailwind, css-modules, or styled |
apiValidation | string | 'zod' | Schema validation: zod, yup, or joi |
Best Practices
-
Validate data at every boundary: client, API, and database — Client validation provides instant feedback. API validation prevents malicious input. Database constraints catch bugs in business logic. Each layer serves a different purpose and all three are necessary.
-
Use TypeScript end-to-end with shared types — Define API response types once and use them in both backend handlers and frontend consumers. Tools like tRPC or generated OpenAPI clients ensure type safety across the network boundary.
-
Implement optimistic updates for interactive features — Show the expected result immediately while the API call runs in the background. Roll back on failure with clear error messaging. This makes applications feel instant even with 200ms API latency.
-
Colocate related code across the stack — Keep the API route, database query, and frontend component for a feature in the same directory when your framework supports it. This makes features easy to find, modify, and delete as a unit.
-
Cache aggressively on the server, invalidate precisely — Use HTTP cache headers for static assets (immutable, long max-age). Cache database query results with short TTLs. Invalidate specific cache keys when data changes rather than flushing entire caches.
Common Issues
N+1 query problems across API endpoints — A list endpoint fetches users, then each user's posts individually. Use eager loading (Prisma include, SQL JOINs) for known relationships. Implement DataLoader for GraphQL to batch and deduplicate requests.
Authentication state inconsistent between client and server — Token expiration causes the client to think the user is logged in while the server rejects requests. Handle 401 responses globally: redirect to login, refresh the token, or show a re-authentication prompt.
Frontend and backend type definitions drift apart — Manual type duplication inevitably diverges. Generate frontend types from the API schema (OpenAPI generator, tRPC inference, GraphQL codegen). A single source of truth eliminates an entire category of integration bugs.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.