Apply production-ready Framer SDK patterns for TypeScript and Python. Use when implementing Framer integrations, refactoring SDK usage, or establishing team coding standards for Framer. Trigger with phrases like "framer SDK patterns", "framer best practices", "framer code patterns", "idiomatic framer".
Production-ready patterns for Framer plugins, Server API, code components, and CMS integrations. Covers plugin architecture, type-safe CMS operations, and reusable component patterns.
framer-install-auth setup// src/cms/types.ts — type-safe field definitions
interface BlogPost {
title: string;
body: string;
author: string;
publishDate: string;
featured: boolean;
slug: string;
}
const BLOG_FIELDS = [
{ id: 'title' as const, name: 'Title', type: 'string' as const },
{ id: 'body' as const, name: 'Body', type: 'formattedText' as const },
{ id: 'author' as const, name: 'Author', type: 'string' as const },
{ id: 'publishDate' as const, name: 'Published', type: 'date' as const },
{ id: 'featured' as const, name: 'Featured', type: 'boolean' as const },
{ id: 'slug' as const, name: 'Slug', type: 'slug' as const, userEditable: false },
] as const;
function toBlogItem(post: BlogPost) {
return { fieldData: { ...post } };
}
// src/hooks/usePluginState.ts
import { useState, useCallback } from 'react';
import { framer } from 'framer-plugin';
type SyncStatus = 'idle' | 'fetching' | 'syncing' | 'success' | 'error';
export function useSyncState() {
const [status, setStatus] = useState<SyncStatus>('idle');
const [error, setError] = useState<string | null>(null);
const [count, setCount] = useState(0);
const sync = useCallback(async (fn: () => Promise<number>) => {
setStatus('syncing');
setError(null);
try {
const synced = await fn();
setCount(synced);
setStatus('success');
framer.notify(`Synced ${synced} items`);
} catch (err: any) {
setError(err.message);
setStatus('error');
framer.notify(`Sync failed: ${err.message}`);
}
}, []);
return { status, error, count, sync };
}
// Responsive container pattern
import { addPropertyControls, ControlType } from 'framer';
export default function ResponsiveCard({ title, description, imageUrl, ctaText, ctaUrl }) {
return (
<div style={{ display: 'flex', flexDirection: 'column', borderRadius: 12, overflow: 'hidden', boxShadow: '0 2px 8px rgba(0,0,0,0.1)' }}>
{imageUrl && <img src={imageUrl} style={{ width: '100%', aspectRatio: '16/9', objectFit: 'cover' }} />}
<div style={{ padding: 20, display: 'flex', flexDirection: 'column', gap: 8 }}>
<h3 style={{ margin: 0, fontSize: 20 }}>{title}</h3>
<p style={{ margin: 0, color: '#666', fontSize: 14 }}>{description}</p>
{ctaText && <a href={ctaUrl} style={{ color: '#007AFF', fontWeight: 600, textDecoration: 'none' }}>{ctaText}</a>}
</div>
</div>
);
}
addPropertyControls(ResponsiveCard, {
title: { type: ControlType.String, defaultValue: 'Card Title' },
description: { type: ControlType.String, defaultValue: 'Card description here' },
imageUrl: { type: ControlType.String, defaultValue: '' },
ctaText: { type: ControlType.String, defaultValue: 'Learn More' },
ctaUrl: { type: ControlType.String, defaultValue: '#' },
});
// src/server/framer-client.ts
import { framer } from 'framer-api';
export class FramerCMSClient {
private client: any;
async connect() {
this.client = await framer.connect({
apiKey: process.env.FRAMER_API_KEY!,
siteId: process.env.FRAMER_SITE_ID!,
});
}
async syncCollection(name: string, fields: any[], items: any[]) {
const collections = await this.client.getCollections();
let collection = collections.find(c => c.name === name);
if (!collection) {
collection = await this.client.createManagedCollection({ name, fields });
}
await collection.setItems(items);
return items.length;
}
async publish() {
await this.client.publish();
}
}
// src/overrides/factory.ts — generate overrides programmatically
import { Override } from 'framer';
export function createFadeIn(delay = 0, duration = 0.6): () => Override {
return () => ({
initial: { opacity: 0, y: 20 },
whileInView: { opacity: 1, y: 0 },
transition: { duration, delay, ease: [0.25, 0.1, 0.25, 1] },
viewport: { once: true },
});
}
// Usage in overrides file:
export const FadeIn1 = createFadeIn(0);
export const FadeIn2 = createFadeIn(0.1);
export const FadeIn3 = createFadeIn(0.2);
| Pattern | Use Case | Benefit |
|---|---|---|
| Type-safe fields | CMS collections | Catch schema errors at compile time |
| State hook | Plugin UI | Consistent loading/error states |
| Component patterns | Design systems | Reusable across projects |
| Override factory | Staggered animations | DRY animation code |
Apply patterns in framer-core-workflow-a for CMS sync plugins.