Integration Examples
Copy-paste code for Next.js, React, and plain HTML/JS.
Next.js
Install react-markdown for rendering article content.
bash
npm install react-markdownts
// lib/morphinglabs.ts
const API_URL = process.env.MORPHINGLABS_API_URL || 'https://www.morphinglabs.com/api/v1';
const API_KEY = process.env.MORPHINGLABS_API_KEY!;
export async function getArticles(page = 1, limit = 10) {
const res = await fetch(
`${API_URL}/articles?page=${page}&limit=${limit}`,
{
headers: { 'x-api-key': API_KEY },
next: { revalidate: 3600 } // Cache 1 hour
}
);
if (!res.ok) throw new Error('Failed to fetch articles');
return res.json();
}
export async function getArticle(slug: string) {
const res = await fetch(`${API_URL}/articles/${slug}`, {
headers: { 'x-api-key': API_KEY },
next: { revalidate: 3600 }
});
if (!res.ok) throw new Error('Article not found');
return (await res.json()).data;
}tsx
// app/blog/page.tsx
import { getArticles } from '@/lib/morphinglabs';
import Link from 'next/link';
export default async function BlogPage() {
const { data: articles } = await getArticles();
return (
<div className="max-w-3xl mx-auto py-12">
<h1 className="text-3xl font-bold mb-8">Blog</h1>
{articles.map((article) => (
<Link key={article.slug} href={`/blog/${article.slug}`}>
<article className="mb-8 group">
{article.featured_image_url && (
<img
src={article.featured_image_url}
alt={article.headline}
className="w-full h-48 object-cover rounded-lg mb-4"
/>
)}
<h2 className="text-xl font-semibold group-hover:underline">
{article.headline}
</h2>
<p className="text-gray-600 mt-2">{article.meta_description}</p>
</article>
</Link>
))}
</div>
);
}tsx
// app/blog/[slug]/page.tsx
import { getArticle, getArticles } from '@/lib/morphinglabs';
import ReactMarkdown from 'react-markdown';
export async function generateStaticParams() {
const { data } = await getArticles(1, 100);
return data.map((a) => ({ slug: a.slug }));
}
export async function generateMetadata({ params }) {
const { slug } = await params;
const article = await getArticle(slug);
return {
title: article.meta_title,
description: article.meta_description,
openGraph: {
images: article.featured_image_url ? [article.featured_image_url] : [],
},
};
}
export default async function ArticlePage({ params }) {
const { slug } = await params;
const article = await getArticle(slug);
return (
<article className="max-w-3xl mx-auto py-12">
<h1 className="text-3xl font-bold mb-4">{article.headline}</h1>
<p className="text-gray-500 mb-8">
{article.byline} · {new Date(article.published_at).toLocaleDateString('en-US')}
</p>
{article.sections.map((section) => (
<section key={section.id} className="mb-8">
<h2 className="text-2xl font-semibold mb-3">{section.heading}</h2>
<div className="prose max-w-none">
<ReactMarkdown>{section.body}</ReactMarkdown>
</div>
</section>
))}
<footer className="border-t pt-6 mt-12">
<h3 className="font-semibold mb-2">Sources</h3>
<ul>
{article.sources.map((s, i) => (
<li key={i}>
<a href={s.url} className="text-blue-600 hover:underline">{s.title}</a>
</li>
))}
</ul>
</footer>
</article>
);
}React (Vite / CRA)
ts
// hooks/useArticles.ts
import { useState, useEffect } from 'react';
const API_URL = 'https://www.morphinglabs.com/api/v1';
interface Article {
id: string;
headline: string;
slug: string;
meta_description: string;
featured_image_url: string | null;
sections: Array<{ id: string; heading: string; body: string }>;
sources: Array<{ title: string; url: string }>;
published_at: string;
}
export function useArticles(apiKey: string) {
const [articles, setArticles] = useState<Article[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch(`${API_URL}/articles`, { headers: { 'x-api-key': apiKey } })
.then((r) => r.json())
.then((data) => setArticles(data.data))
.catch((e) => setError(e.message))
.finally(() => setLoading(false));
}, [apiKey]);
return { articles, loading, error };
}tsx
// components/BlogList.tsx
import { useArticles } from '../hooks/useArticles';
export function BlogList() {
const { articles, loading } = useArticles(import.meta.env.VITE_MORPHINGLABS_API_KEY);
if (loading) return <p>Loading...</p>;
return (
<div>
{articles.map((article) => (
<a key={article.slug} href={`/blog/${article.slug}`}>
<h2>{article.headline}</h2>
<p>{article.meta_description}</p>
</a>
))}
</div>
);
}HTML / JavaScript
Pure HTML/JavaScript — no framework needed.
html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Blog</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
</head>
<body>
<div id="articles"></div>
<script>
const API_KEY = 'ask_your_api_key_here';
const API_URL = 'https://www.morphinglabs.com/api/v1';
fetch(`${API_URL}/articles`, { headers: { 'x-api-key': API_KEY } })
.then(r => r.json())
.then(({ data }) => {
document.getElementById('articles').innerHTML = data
.map(article => `
<article>
${article.featured_image_url
? `<img src="${article.featured_image_url}" alt="${article.headline}" style="width:100%;max-height:300px;object-fit:cover">`
: ''}
<h2>${article.headline}</h2>
<p><em>${article.byline} · ${new Date(article.published_at).toLocaleDateString('en-US')}</em></p>
${article.sections.map(s => `
<h3>${s.heading}</h3>
<div>${marked.parse(s.body)}</div>
`).join('')}
<hr>
<h4>Sources</h4>
<ul>
${article.sources.map(s => `<li><a href="${s.url}">${s.title}</a></li>`).join('')}
</ul>
</article>
`).join('<hr>');
});
</script>
</body>
</html>