Skip to main content

Development Patterns

Reusable component patterns and coding conventions used across FLYPILOT projects.

WordPress Block Patterns

Block patterns are pre-built layouts that can be inserted into the WordPress block editor. They provide consistent, reusable designs across projects.

Pattern Categories

CategoryPurposeExamples
HeroPage headers and landing sectionsFull-width hero, Split hero, Video hero
Text + ImageContent sections with imagerySide-by-side, Overlapping, Card layout
Text + ButtonsCall-to-action sectionsCTA banner, Feature list, Pricing
CardsGrid-based contentTeam members, Services, Testimonials
FormsForm layoutsContact, Newsletter, Multi-step

Pattern Structure

patterns/
└── hero/
├── README.md # Pattern documentation
├── pattern.php # WordPress pattern registration
├── hero.scss # Pattern styles
└── examples/
├── bold-italic/
│ ├── pattern.php
│ └── readme.md
└── video-background/
├── pattern.php
└── readme.md

Creating a Pattern

1. Register Pattern (pattern.php)

<?php
/**
* Title: Hero with CTA
* Slug: theme/hero-cta
* Categories: hero
* Block Types: core/cover
* Viewport Width: 1400
*/
?>

<!-- wp:cover {"dimRatio":50,"overlayColor":"primary","align":"full","className":"hero-cta"} -->
<div class="wp-block-cover alignfull hero-cta">
<div class="wp-block-cover__inner-container">
<!-- wp:heading {"textAlign":"center","level":1} -->
<h1 class="wp-block-heading has-text-align-center">Welcome</h1>
<!-- /wp:heading -->

<!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} -->
<div class="wp-block-buttons">
<!-- wp:button -->
<div class="wp-block-button">
<a class="wp-block-button__link wp-element-button">Get Started</a>
</div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
</div>
</div>
<!-- /wp:cover -->

2. Add Styles (hero.scss)

.hero-cta {
min-height: 80vh;
padding: $space-120 0;

&__title {
font-size: clamp(2.5rem, 5vw, 4rem);
font-weight: 700;
margin-bottom: $space-40;
}

.wp-block-buttons {
margin-top: $space-40;
}
}

CSS/SCSS Patterns

BEM Methodology

FLYPILOT uses BEM (Block Element Modifier) for consistent CSS organization.

// Block
.card { }

// Element (double underscore)
.card__header { }
.card__body { }
.card__footer { }

// Modifier (double dash)
.card--featured { }
.card--compact { }
.card__header--dark { }

Utility Classes

Common utility patterns:

// Spacing utilities
.mt-20 { margin-top: 20px; }
.mb-40 { margin-bottom: 40px; }
.py-80 { padding-top: 80px; padding-bottom: 80px; }

// Text utilities
.text-center { text-align: center; }
.text-uppercase { text-transform: uppercase; }

// Display utilities
.d-none { display: none; }
.d-flex { display: flex; }

// Responsive utilities
.d-none-mobile {
@media (max-width: $breakpoint-sm) {
display: none;
}
}

Responsive Breakpoints

// Standard breakpoints
$breakpoint-xs: 320px;
$breakpoint-sm: 576px;
$breakpoint-md: 768px;
$breakpoint-lg: 992px;
$breakpoint-xl: 1200px;
$breakpoint-xxl: 1400px;

// Usage with mobile-first
.component {
padding: 20px;

@media (min-width: $breakpoint-md) {
padding: 40px;
}

@media (min-width: $breakpoint-lg) {
padding: 60px;
}
}

React/TypeScript Patterns

Component Structure

// components/Button/Button.tsx
import { cn } from '@/lib/utils';
import { ButtonProps } from './types';

export function Button({
children,
variant = 'primary',
size = 'md',
className,
...props
}: ButtonProps) {
return (
<button
className={cn(
'btn',
`btn--${variant}`,
`btn--${size}`,
className
)}
{...props}
>
{children}
</button>
);
}

Custom Hooks

// hooks/useLocalStorage.ts
import { useState, useEffect } from 'react';

export function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(() => {
if (typeof window === 'undefined') {
return initialValue;
}
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});

useEffect(() => {
if (typeof window !== 'undefined') {
window.localStorage.setItem(key, JSON.stringify(storedValue));
}
}, [key, storedValue]);

return [storedValue, setStoredValue] as const;
}

API Patterns

// lib/api/client.ts
const API_BASE = process.env.NEXT_PUBLIC_API_URL;

async function fetchAPI<T>(
endpoint: string,
options?: RequestInit
): Promise<T> {
const response = await fetch(`${API_BASE}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
});

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

return response.json();
}

// Usage
export const api = {
users: {
list: () => fetchAPI<User[]>('/users'),
get: (id: string) => fetchAPI<User>(`/users/${id}`),
create: (data: CreateUserInput) =>
fetchAPI<User>('/users', { method: 'POST', body: JSON.stringify(data) }),
},
};

File Organization Patterns

WordPress Theme

theme/
├── functions.php
├── style.css
├── theme.json
├── patterns/
│ └── [pattern-name]/
├── templates/
│ ├── index.html
│ ├── single.html
│ └── archive.html
├── parts/
│ ├── header.html
│ └── footer.html
└── dx/
├── scss/
├── ts/
└── acf-blocks/

Next.js Application

src/
├── app/
│ ├── layout.tsx
│ ├── page.tsx
│ ├── (auth)/
│ │ ├── login/
│ │ └── register/
│ └── api/
├── components/
│ ├── ui/
│ └── features/
├── lib/
│ ├── api/
│ └── utils/
├── hooks/
├── types/
└── styles/

Pattern Library

For a visual library of patterns, see the Component Library repository.