Skip to main content

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:

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

  1. Create file: app/new-page/page.tsx
  2. Export component:
    export default function NewPage() {
    return <div>New Page</div>;
    }
  3. Access at: /new-page

Creating Custom Component

  1. Create file: components/MyComponent.tsx
  2. Define component:
    interface MyComponentProps {
    title: string;
    }

    export function MyComponent({ title }: MyComponentProps) {
    return <div>{title}</div>;
    }
  3. Import and use

Adding WordPress Field

  1. Add field in WordPress (ACF or custom)
  2. Update GraphQL query:
    query GetPost($slug: ID!) {
    post(id: $slug, idType: SLUG) {
    id
    title
    customField # New field
    }
    }
  3. Regenerate types: pnpm graphql:codegen
  4. 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.tsx not Card.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

  1. Fork repository
  2. Create feature branch
  3. Make changes
  4. Write tests
  5. 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

Next Steps

Explore developer topics in detail:

  1. Project Structure - Understand the codebase
  2. Architecture - System design and patterns
  3. Extending FlatWP - Add custom functionality
  4. Testing - Test your code

See Also