Get up and running with Lynkow in under 10 minutes. This guide walks you through installing the SDK, connecting to your site, and fetching your first content.
Reference - This guide is a tutorial. For exhaustive, always-current signatures and field lists, see the auto-generated reference:
SDK:
ContentsServiceAPI: Storefront: Content
Prerequisites
Before you begin, make sure you have:
Node.js 18+ installed (download)
A Lynkow account with at least one site created
Your Site ID (found in your Lynkow dashboard under Site Settings)
Installation
Install the Lynkow SDK from npm:
npm install lynkowOr with your preferred package manager:
# yarn
yarn add lynkow
# pnpm
pnpm add lynkowEnvironment Setup
Create a .env.local file in the root of your project and add your Site ID:
NEXT_PUBLIC_LYNKOW_SITE_ID=your-site-id-hereYou can find your Site ID in the Lynkow dashboard by navigating to Settings > General. It is a UUID that looks like a1b2c3d4-e5f6-7890-abcd-ef1234567890.
Create the SDK Client
Create a shared client instance that you will import throughout your application. This avoids re-initializing the client on every request.
Create the file lib/lynkow.ts:
import { createClient } from 'lynkow'
export const lynkow = createClient({
siteId: process.env.NEXT_PUBLIC_LYNKOW_SITE_ID!,
// Optional: copied from the Lynkow dashboard, sent as the `X-Lynkow-Pk` header
publishableKey: process.env.NEXT_PUBLIC_LYNKOW_PUBLISHABLE_KEY,
fetchOptions: {
next: { revalidate: 60 },
},
})Configuration options:
Option | Type | Default | Description |
|---|---|---|---|
|
| required | Your Lynkow Site ID |
|
|
| Optional key copied from your Lynkow dashboard. Sent as the |
|
|
| Default locale for all requests (e.g., |
|
|
| Options passed to every |
|
|
| Auto-retry transient failures (429/503/network) on reads with backoff, honoring |
The SDK connects to https://api.lynkow.com by default. The revalidate: 60 setting tells Next.js to cache responses and revalidate them every 60 seconds via ISR. For near-instant updates, add a webhook endpoint (see Guide 11: Webhooks & Cache Revalidation).
First API Call: List Articles
Create a page that fetches and displays your published articles.
Create the file app/blog/page.tsx:
import { lynkow } from '@/lib/lynkow'
export default async function BlogPage() {
const { data: articles, meta } = await lynkow.contents.list({
limit: 10,
sort: 'published_at',
order: 'desc',
})
return (
<main style={{ maxWidth: '800px', margin: '0 auto', padding: '2rem' }}>
<h1>Blog</h1>
<p>{meta.total} articles published</p>
<ul style={{ listStyle: 'none', padding: 0 }}>
{articles.map((article) => (
<li key={article.id} style={{ marginBottom: '2rem' }}>
<a href={`/blog/${article.slug}`}>
<h2>{article.title}</h2>
</a>
{article.excerpt && <p>{article.excerpt}</p>}
<time dateTime={article.publishedAt}>
{new Date(article.publishedAt).toLocaleDateString()}
</time>
</li>
))}
</ul>
<p>
Page {meta.currentPage} of {meta.lastPage}
</p>
</main>
)
}The contents.list() method returns published articles with pagination metadata. Each article in the list includes its id, title, slug, path, excerpt, featuredImage, publishedAt, and locale -- but not the full body HTML, which keeps list responses fast.
Display a Single Article
Create a dynamic route to display a full article by its slug.
Create the file app/blog/[slug]/page.tsx:
import { lynkow } from '@/lib/lynkow'
import { notFound } from 'next/navigation'
type Params = Promise<{ slug: string }>
export default async function ArticlePage({ params }: { params: Params }) {
const { slug } = await params
let article
try {
article = await lynkow.contents.getBySlug(slug)
} catch {
notFound()
}
return (
<main style={{ maxWidth: '800px', margin: '0 auto', padding: '2rem' }}>
<article>
<h1>{article.title}</h1>
{article.author && (
<p>
By {article.author.fullName} ·{' '}
<time dateTime={article.publishedAt}>
{new Date(article.publishedAt).toLocaleDateString()}
</time>
</p>
)}
{article.featuredImage && (
<img
src={article.featuredImageVariants?.hero || article.featuredImage}
alt={article.title}
style={{ width: '100%', height: 'auto', borderRadius: '8px' }}
/>
)}
<div dangerouslySetInnerHTML={{ __html: article.body }} />
{article.categories.length > 0 && (
<div>
<strong>Categories:</strong>{' '}
{article.categories.map((cat) => cat.name).join(', ')}
</div>
)}
{article.tags.length > 0 && (
<div>
<strong>Tags:</strong>{' '}
{article.tags.map((tag) => tag.name).join(', ')}
</div>
)}
</article>
</main>
)
}The contents.getBySlug() method returns the full content object including the rendered HTML body, author, categories, tags, structuredData, and SEO fields like metaTitle and metaDescription.
Understanding the Response Types
ContentSummary (returned by contents.list())
Lightweight representation used in listing pages. The listing example above reads these fields:
interface ContentSummary {
id: string
title: string
slug: string
excerpt: string | null
publishedAt: string
// ...more fields
}See the full ContentSummary shape in the SDK Types reference.
Content (returned by contents.getBySlug())
Full content with body and relationships. The single-article example above reads these fields:
interface Content {
title: string
body: string // Rendered HTML
publishedAt: string
featuredImage: string | null
featuredImageVariants: Record<string, string> | null
author: { fullName: string } | null
categories: Array<{ name: string }>
tags: Array<{ name: string }>
// ...more fields (structuredData, metaTitle, metaDescription, ogImage, ...)
}See the full Content shape in the SDK Types reference.
PaginationMeta
Returned as meta in paginated responses. The example above reads these fields:
interface PaginationMeta {
total: number
currentPage: number
lastPage: number
// ...more fields
}See the full PaginationMeta shape in the SDK Types reference.
Next Steps
You now have a working integration with Lynkow. Here is where to go from here:
Build a Complete Blog with Next.js -- Full blog implementation with categories, tags, pagination, SEO metadata, JSON-LD, and responsive images.
API Reference -- Complete documentation of all SDK methods and response types.
Media & Images -- Learn how to use
lynkow.media.srcset()andlynkow.media.transform()for responsive, optimized images.Localization -- Serve content in multiple languages with locale-aware queries.