Getting Started
Get up and running with Foir in just a few minutes.
Prerequisites
- A Foir account with access to a project
- Node.js 18+ installed
- A React-based frontend (Next.js, Remix, etc.)
Step 1: Create an API Key
- Log in to the Foir admin
- Go to Project Settings > API Keys
- Click Create API Key
- Configure:
- Name: “Frontend” (or similar)
- Type: PUBLIC
- Environment: DEVELOPMENT
- Click Create
- Copy the key - it’s only shown once!
Add it to your environment:
# .env.local
FOIR_API_KEY=pk_test_abc123...
FOIR_API_URL=https://api.foir.ioStep 2: Install Packages
npm install @eide/foir-renderer
npm install -D @eide/uniformgenStep 3: Generate Types
# Login to Foir
npx uniformgen login
# Select your project
npx uniformgen setup
# Generate types
npx uniformgen pullThis creates TypeScript types and hooks in src/generated/.
Step 4: Create a Component Registry
Map your entity types to React components:
// lib/foir-registry.ts
import { createRegistry, DEFAULT_PRIMITIVES } from '@eide/foir-renderer';
import { PageComponent } from '@/components/foir/Page';
export const registry = createRegistry({
components: {
...DEFAULT_PRIMITIVES,
'page': PageComponent,
},
});Step 5: Create a Page Component
// components/foir/Page.tsx
import type { EntityComponentProps } from '@eide/foir-renderer';
export function PageComponent({
zones,
fields,
breadcrumbs,
}: EntityComponentProps) {
const title = fields.find(f => f.key === 'title');
return (
<article>
<nav>
{breadcrumbs?.map(crumb => (
<a key={crumb.url} href={crumb.url}>{crumb.label}</a>
))}
</nav>
{title && <h1>{String(title.value)}</h1>}
{zones.header}
<main>{zones.main}</main>
{zones.footer}
</article>
);
}Step 6: Fetch and Render Content
Next.js
// app/[...slug]/page.tsx
import { EntityRenderer } from '@eide/foir-renderer';
import { registry } from '@/lib/foir-registry';
async function getPage(path: string) {
const res = await fetch(`${process.env.FOIR_API_URL}/graphql`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.FOIR_API_KEY!,
},
body: JSON.stringify({
query: `
query ResolveRoute($path: String!) {
resolveRoute(path: $path) {
record { id modelKey naturalKey }
content { fields { key type value } }
breadcrumbs { label url }
gridConfig { breakpoints cols }
}
}
`,
variables: { path },
}),
});
const { data } = await res.json();
return data.resolveRoute;
}
export default async function Page({ params }: { params: { slug?: string[] } }) {
const path = '/' + (params.slug?.join('/') || '');
const route = await getPage(path);
if (!route) return <div>Page not found</div>;
return <EntityRenderer data={route} registry={registry} />;
}Step 7: Create Content
- Go to Content > Pages in the admin
- Click Create Page
- Fill in the title and content
- Click Publish
- Visit your frontend to see it!
Next Steps
Learn the Concepts
- Entities - How content is structured
- Field Types - Available field types
- Variants - Serve different content to different audiences
Expand Your Setup
- Using UniformGen - Deep dive into code generation
- Using Foir Renderer - Advanced rendering patterns
- Creating API Keys - Production key management
Build Features
- Add more entity types (blogs, products, etc.)
- Create inline schemas for reusable components
- Set up variants for A/B testing
- Configure market/locale routing
Common Issues
”API key required”
Make sure you’re passing the x-api-key header in fetch requests.
”Page not found”
- Check the page is published in the admin
- Verify the URL path matches the page slug
”Unknown component type”
Register all entity types in your registry:
const registry = createRegistry({
components: {
'page': PageComponent,
'hero-banner': HeroBannerComponent, // Add missing types
},
});Types out of date
Regenerate with npx uniformgen pull.
Last updated on