Developer Guide
Technical documentation for developers working with FlatWP.
Overview
This section is for developers who want to:
- Understand FlatWP architecture
- Extend FlatWP functionality
- Contribute to the project
- Build custom solutions
Who This Is For
You should read this if you:
- Want to customize FlatWP beyond settings
- Need to add custom post types
- Want to create custom components
- Are contributing to FlatWP
- Need to understand the codebase
If you just want to use FlatWP:
- See Getting Started
- See Content Management
- See Customization
Prerequisites
Required Knowledge
JavaScript/TypeScript:
- ES6+ features
- Async/await
- TypeScript basics
- Module systems
React:
- Functional components
- Hooks (useState, useEffect, etc.)
- Server Components (Next.js 15)
- Client Components
Next.js:
- App Router
- Server/Client Components
- Data fetching
- Routing
WordPress:
- Basic WordPress concepts
- WPGraphQL
- Custom post types
- Custom fields
Development Environment
- Node.js 20+
- pnpm 8+
- Git
- Code editor (VS Code recommended)
- Terminal/command line
Getting Started
Clone Repository
git clone https://github.com/flatwp/flatwp-starter.git my-site
cd my-site
Install Dependencies
pnpm install
Configure Environment
# Interactive setup (recommended)
pnpm run setup
# Or manual setup
cp .env.example .env.local
Start Development
pnpm dev
Architecture Overview
FlatWP is built on a modern, modular architecture:
Technology Stack
Frontend:
- Next.js 15.5.6 (App Router)
- React 19
- TypeScript
- TailwindCSS v4
Backend:
- WordPress 6.4+
- WPGraphQL
- Custom WordPress plugin
Build Tools:
- pnpm (package manager)
- GraphQL Code Generator
- Vite (WordPress plugin)
Project Structure
flatwp-starter/
├── app/ # Next.js App Router
│ ├── (pages)/ # Dynamic pages
│ ├── blog/ # Blog routes
│ └── api/ # API routes
├── components/ # React components
│ ├── blocks/ # WordPress blocks
│ ├── layout/ # Header, Footer
│ └── ui/ # Shadcn/ui components
├── lib/ # Utilities
│ └── wordpress/ # WordPress client
├── graphql/ # GraphQL queries
└── public/ # Static assets
Learn more: Project Structure
Data Flow
WordPress (Content)
↓ GraphQL API
Next.js (Query)
↓ Type-safe data
React Components (Render)
↓ Optimized HTML
User (View)
Architecture Principles
1. Type Safety
- TypeScript everywhere
- GraphQL code generation
- Runtime validation
2. Performance First
- ISR by default
- Image optimization
- Code splitting
- Edge caching
3. Developer Experience
- Hot module replacement
- Fast refresh
- Clear error messages
- Comprehensive docs
4. Modularity
- Reusable components
- Shared packages
- Clean interfaces
- Testable code
Learn more: Architecture
Key Concepts
Server Components
Default in Next.js 15 App Router:
// app/page.tsx - Server Component (default)
export default async function Page() {
// Can directly access databases, APIs
const posts = await getAllPosts();
return <PostList posts={posts} />;
}
Client Components
For interactivity:
'use client';
import { useState } from 'react';
export function InteractiveComponent() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Type-Safe GraphQL
Generated types from WordPress schema:
import type { Post, GetPostBySlugQuery } from '@/graphql/generated';
async function getPost(slug: string): Promise<Post> {
const result: GetPostBySlugQuery = await client.query(GET_POST, { slug });
return result.post;
}
ISR Configuration
Per-page revalidation:
// Static with on-demand revalidation
export const revalidate = false;
// Time-based revalidation (5 minutes)
export const revalidate = 300;
// Force dynamic (SSR)
export const dynamic = 'force-dynamic';
Development Workflow
1. Local Development
# Start development server
pnpm dev
# Build for production
pnpm build
# Run production build locally
pnpm start
2. Code Quality
# Type checking
pnpm typecheck
# Linting
pnpm lint
# Format code
pnpm format
3. Testing
# Run tests (when available)
pnpm test
# E2E tests
pnpm test:e2e
4. Building
# Build for production
pnpm build
# Build specific app
pnpm build:web
Common Development Tasks
Adding a New Page
- Create file:
app/new-page/page.tsx - Export component:
export default function NewPage() {
return <div>New Page</div>;
} - Access at:
/new-page
Creating Custom Component
- Create file:
components/MyComponent.tsx - Define component:
interface MyComponentProps {
title: string;
}
export function MyComponent({ title }: MyComponentProps) {
return <div>{title}</div>;
} - Import and use
Adding WordPress Field
- Add field in WordPress (ACF or custom)
- Update GraphQL query:
query GetPost($slug: ID!) {
post(id: $slug, idType: SLUG) {
id
title
customField # New field
}
} - Regenerate types:
pnpm graphql:codegen - Use in component
Learn more: Extending FlatWP
Debugging
Development Tools
1. React DevTools
- Inspect component tree
- View props and state
- Profile performance
2. Network Tab
- Monitor API calls
- Check GraphQL queries
- Verify caching
3. Next.js DevTools
- Fast Refresh status
- Build errors
- Route information
Common Debug Scenarios
GraphQL Issues:
// Log query and variables
console.log('Query:', query);
console.log('Variables:', variables);
console.log('Result:', result);
Render Issues:
// Check what's rendering
console.log('Rendering with props:', props);
Cache Issues:
# Clear Next.js cache
rm -rf .next
pnpm dev
Best Practices
Code Organization
1. Component Structure
components/
├── ui/ # Reusable UI components
├── blocks/ # WordPress block components
├── layout/ # Layout components
└── features/ # Feature-specific components
2. File Naming
- PascalCase for components:
MyComponent.tsx - kebab-case for routes:
my-route/page.tsx - Descriptive names:
PostCard.tsxnotCard.tsx
TypeScript
1. Define Interfaces
interface Post {
id: string;
title: string;
content: string;
}
2. Use Type Inference
// Good: Type inferred
const posts = await getAllPosts();
// Unnecessary: Explicit type
const posts: Post[] = await getAllPosts();
3. Avoid any
// Bad
const data: any = await fetchData();
// Good
interface Data {
posts: Post[];
}
const data: Data = await fetchData();
Performance
1. Dynamic Imports
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <Skeleton />,
});
2. Memoization
import { cache } from 'react';
const getPost = cache(async (slug: string) => {
return await fetchPost(slug);
});
3. Image Optimization
import Image from 'next/image';
<Image
src={imageUrl}
alt={altText}
width={800}
height={600}
quality={85}
/>
Contributing
Getting Started
- Fork repository
- Create feature branch
- Make changes
- Write tests
- Submit pull request
Contribution Guidelines
- Follow existing code style
- Write clear commit messages
- Add tests for new features
- Update documentation
- Be respectful and collaborative
Learn more: Contributing Guide
Resources
Official Documentation
FlatWP Resources
- FlatWP Starter - Next.js template
- WordPress Plugin - WordPress connector
- Issue Tracker
- Discussions
Next Steps
Explore developer topics in detail:
- Project Structure - Understand the codebase
- Architecture - System design and patterns
- Extending FlatWP - Add custom functionality
- Testing - Test your code
See Also
- GraphQL API - Working with GraphQL
- Customization - Customize your site
- Advanced Topics - Performance and optimization