Installation & Setup
Adding blocks to your project is a two-part process: a one-time foundation setup, then a simple copy-paste workflow for each block.
Part 1: Foundation Setup (One Time)
Before copying your first block, add the shared files that all blocks depend on. These files provide the design system that keeps blocks visually consistent — handling spacing, typography, and layout so you do not have to configure each block individually.
This is a one-time step. Once these files are in your project, every block you add works out of the box.
What to Copy
The foundation consists of three groups of files. Copy each one into the specified location in your project:
CSS files — Add tokens.css to your styles directory and import it in your globals.css. Then add the fluid utility classes and base typography styles directly in your globals.css. Together, these give every block a consistent spacing and typography scale that adapts smoothly to any screen size.
| File | Copy to | Purpose |
|---|---|---|
tokens.css | src/styles/tokens.css | Fluid spacing and type scale (CSS variables) |
| Fluid utilities + typography | Inline in globals.css | Utility classes like my-section, gap-stack, p-surface |
Layout components — Add the Fluid/ and Typography/ directories to src/components/. These are small React components that blocks use for page layout (sections, grids, containers) and text hierarchy (titles, descriptions, labels).
| Directory | Copy to | Purpose |
|---|---|---|
Fluid/ | src/components/Fluid/ | FluidSection, FluidGrid, FluidStack, and other layout components |
Typography/ | src/components/Typography/ | SectionHeader, SectionTitle, Eyebrow, and other text components |
Payload helpers — These connect the design system to the Payload admin panel, giving content editors controls for spacing, background color, and text alignment on every block.
| File | Copy to | Purpose |
|---|---|---|
blockDesign.ts | src/payload/fields/blockDesign.ts | Adds the Design collapsible to block configs |
blockDesignClasses.ts | src/lib/helpers/blockDesignClasses.ts | Maps admin field values to CSS classes |
Want to understand how these pieces fit together? The Fluid Design System page explains the full architecture. You do not need to read it to start using blocks — everything works out of the box.
Get the Foundation Files
Download all foundation files as a single ZIP, or expand individual files below to view and copy the source code:
Or copy individual files below. Each section can be expanded to view and copy the source code.
CSS
Layout Components
Typography Components
Payload Helpers
Check Block Dependencies
Individual blocks may have their own dependencies beyond the shared foundation. Each block page lists what it needs. Common dependencies include:
- lucide-react — icons used in some blocks
- shadcn/ui components — Badge, Accordion, etc.
- Media component — for rendering uploaded images (included in the Payload website template)
- Modified link field — an improved version of the Payload website template's link field, with localization and validation support
Part 2: Adding a Block
With the foundation in place, adding any block is a four-step process. Here is an example using Hero 1.
Step 1: Copy the Block Files
Each block has two files: config.ts (the Payload block configuration) and component.tsx (the React component that renders it).
Create a folder for the block in your project. Organizing by category keeps things manageable as your collection grows:
1src/blocks/
2├── heros/
3│ └── hero-1/
4│ ├── config.ts
5│ └── component.tsxGo to the block's page on LayoutBlocks, open the Code section, and copy both files into your project. You can also use the Copy Config and Copy Component buttons in the quick action bar, or download both files as a ZIP.
Step 2: Register the Block in Payload
Import the block config and add it to a blocks field on your collection (usually Pages). This tells Payload to show the block in the admin panel:
1import type { Block, CollectionConfig } from 'payload';
2import { Hero1Config } from '@/blocks/heros/hero-1/config';
3
4const Pages: CollectionConfig = {
5 slug: 'pages',
6 fields: [
7 {
8 name: 'layout',
9 type: 'blocks',
10 blocks: [Hero1Config],
11 },
12 ],
13};What is a
blocksfield? In Payload, ablocksfield is a flexible content area where editors can add, reorder, and remove different block types. Each block type has its own set of fields. Think of it as a page builder — editors pick from your available blocks to compose a page. See the Payload blocks field docs for more.
Step 3: Render the Block on the Frontend
When Payload stores a page, each block in the layout array includes a blockType property that identifies which block it is. You need a renderer component that maps each block type to its React component:
1import type { Hero1Type } from '@/payload-types';
2import Hero1Component from '@/blocks/heros/hero-1/component';
3
4const blockComponents: Record<string, React.FC<any>> = {
5 hero1Config: Hero1Component,
6};
7
8export function RenderBlocks({ blocks }: { blocks: (Hero1Type | any)[] }) {
9 return blocks?.map((block, i) => {
10 const Component = blockComponents[block.blockType];
11 if (!Component) return null;
12 return <Component key={i} {...block} />;
13 });
14}The key in blockComponents must match the block's config slug. For Hero 1, the config has slug: 'hero1Config', so you use hero1Config as the key. Payload saves this slug as blockType in the stored page data — that is how the renderer knows which component to use.
As you add more blocks, add more entries to blockComponents. That is all there is to it.
Step 4: Generate TypeScript Types
After adding a new block config, run:
1pnpm payload generate:typesThis regenerates payload-types.ts with typed interfaces for your new block, giving you full autocomplete and type safety in your component.
Dependencies & Helpers
Modified Fields
Some blocks use improved versions of the standard Payload link and linkGroup fields. These add a localizedLabel option for multi-language projects and a required option for field validation — features the originals do not have.
- Link field — adds
localizedLabelandrequiredprops - Link Group field — adds
localizedLabelprop
If a block lists "link field (modified)" as a dependency, copy this modified field into your project.
CMSLink Component
Blocks render links using the CMSLink component from the Payload website template. This component handles both internal (relationship) and external (URL) link types that Payload's link field produces. If you started from the website template, you already have it.
The cn Utility
Blocks use cn() for combining CSS class names conditionally. This is a small utility that comes with shadcn/ui — if you have shadcn set up, you already have it.