Next.js Integration
Add an Instagram feed to a Next.js App Router project with a single fetch in a server component. Your dashboard gives you a username and a publicKey; pass them as query parameters. ISR handles caching. No npm package, no Authorization header. Normal Next.js.
The integration is a fetch call. Your dashboard exposes the two values you need: an Instagram username and a publicKey (a 32-character hex string). The Server Component below shows the full pattern.
Fetch the feed
Drop the two values into env vars:
FEEDFUSION_USERNAME=your-instagram-handle
FEEDFUSION_PUBLIC_KEY=your-32-char-public-key-from-dashboardThen fetch from a Server Component. ISR keeps the response cached for an hour between requests, which matches FeedFusion's own edge-cache window (Section 3).
type Post = {
id: string
timestamp: string
permalink: string
mediaType: 'IMAGE' | 'VIDEO' | 'CAROUSEL_ALBUM'
mediaUrl: string
thumbnailUrl: string | null
caption: string | null
}
export default async function InstagramPage() {
const res = await fetch(
`https://www.feed-fusion.com/api/feeds/${process.env.FEEDFUSION_USERNAME}` +
`?publicKey=${process.env.FEEDFUSION_PUBLIC_KEY}&limit=12`,
{ next: { revalidate: 3600 } },
)
if (!res.ok) {
throw new Error(`FeedFusion fetch failed: ${res.status}`)
}
const { posts } = (await res.json()) as { posts: Post[] }
return (
<ul className="grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-4">
{posts.map((post) => (
<li key={post.id}>
<a href={post.permalink} target="_blank" rel="noopener noreferrer">
<img
src={post.thumbnailUrl ?? post.mediaUrl}
alt={post.caption?.slice(0, 120) ?? 'Instagram post'}
loading="lazy"
/>
</a>
</li>
))}
</ul>
)
}Server + client split
If the grid needs client-side interactivity (hover state, a lightbox, click tracking), fetch in the Server Component and pass posts as props to a Client Component. The publicKey is safe to expose either way (it's public by design), but keeping the fetch server-side means ISR caches the response for you.
import { InstagramGrid } from './instagram-grid'
import type { Post } from '@/types/feedfusion'
export default async function InstagramPage() {
const res = await fetch(
`https://www.feed-fusion.com/api/feeds/${process.env.FEEDFUSION_USERNAME}` +
`?publicKey=${process.env.FEEDFUSION_PUBLIC_KEY}&limit=24`,
{ next: { revalidate: 3600 } },
)
const { posts } = (await res.json()) as { posts: Post[] }
return <InstagramGrid posts={posts} />
}Caching with ISR
FeedFusion caches at the edge for one hour. The meta.cacheTtl field in the response tells you exactly how long. Setting next.revalidate below 3600 won't make the feed fresher; it just refetches the same cached payload more often. Match your revalidate to the edge cache TTL for the most efficient setup.
Tune the cadence to how often the connected Instagram account actually posts:
- Daily posters:
revalidate: 3600(one hour) keeps the feed current. - Weekly posters:
revalidate: 86400(24 hours) keeps usage low without making the grid stale. - Multiple-times-a-day posters:
revalidate: 1800(30 min) is reasonable, but the upstream edge cache is still hourly, so you may serve the same payload twice.
TypeScript types
Extract the response types to a shared file so every callsite stays consistent:
export type MediaType = 'IMAGE' | 'VIDEO' | 'CAROUSEL_ALBUM'
export type Post = {
id: string
timestamp: string // ISO 8601
permalink: string // Instagram URL
mediaType: MediaType
mediaUrl: string
thumbnailUrl: string | null // null for IMAGE, populated for VIDEO/CAROUSEL
caption: string | null
}
export type FeedMeta = {
tier: 'free' | 'pro' | 'agency'
total: number // total posts available before slice
limit: number // posts returned in this response
offset: number // starting index of this slice
cacheTtl: number // edge cache TTL in seconds
}
export type FeedResponse = {
username: string
meta: FeedMeta
posts: Post[]
}Pagination and limits
Add &offset=N to step through the cached posts beyond the first page. limit accepts 1 to 100. The meta.total field tells you when there are more pages to load. See the API Reference for the full query-parameter surface.
Questions? hello@feed-fusion.com
Continue reading