Skip to content

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-markdown
ts
// 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>