Quick Start
Build your first Trident-powered blog page in 5 minutes.
This guide assumes you have a Next.js 14+ project with the App Router. For other frameworks, see the examples.
Step 1: Create the client
Create a shared client instance in your lib folder:
// lib/trident.ts
import { createTridentClient } from "@trident/client";
export const trident = createTridentClient({
apiKey: process.env.TRIDENT_API_KEY!,
});Step 2: Create the blog listing page
Create a page that lists all your articles:
// app/blog/page.tsx
import { trident } from "@/lib/trident";
import Link from "next/link";
export default async function BlogPage() {
const { data: articles, pagination } = await trident.getArticles({
product: "my-product",
limit: 20,
});
return (
<div className="mx-auto max-w-4xl py-12">
<h1 className="text-3xl font-bold">Blog</h1>
<div className="mt-8 space-y-6">
{articles.map((article) => (
<article key={article.id} className="border-b pb-6">
<Link href={`/blog/${article.slug}`}>
<h2 className="text-xl font-semibold hover:text-blue-600">
{article.title}
</h2>
</Link>
<p className="mt-2 text-gray-600">{article.excerpt}</p>
<time className="mt-2 text-sm text-gray-500">
{new Date(article.publishedAt!).toLocaleDateString()}
</time>
</article>
))}
</div>
</div>
);
}
// Enable ISR with 1 hour revalidation
export const revalidate = 3600;Step 3: Create the article page
Create a dynamic page that renders article content:
// app/blog/[slug]/page.tsx
import { trident } from "@/lib/trident";
import { ArticleRenderer } from "@trident/client/components";
import { generateArticleMetadata } from "@trident/client/nextjs";
import { notFound } from "next/navigation";
interface Props {
params: { slug: string };
}
export async function generateMetadata({ params }: Props) {
try {
const article = await trident.getArticle(params.slug);
return generateArticleMetadata(article, {
baseUrl: "https://yourdomain.com",
});
} catch {
return { title: "Article Not Found" };
}
}
export default async function ArticlePage({ params }: Props) {
try {
const article = await trident.getArticle(params.slug);
return (
<article className="mx-auto max-w-3xl py-12">
<h1 className="text-4xl font-bold">{article.title}</h1>
{article.content && (
<ArticleRenderer article={article} className="mt-8" />
)}
</article>
);
} catch {
notFound();
}
}
// Generate static paths at build time
export async function generateStaticParams() {
const entries = await trident.getSitemap();
return entries.map((entry) => ({ slug: entry.slug }));
}
export const revalidate = 3600;Step 4: Add the sitemap
Generate a sitemap.xml automatically:
// app/sitemap.ts
import { trident } from "@/lib/trident";
import { generateSitemapEntries } from "@trident/client/nextjs";
export default async function sitemap() {
const entries = await trident.getSitemap();
return generateSitemapEntries(entries, {
baseUrl: "https://yourdomain.com",
urlPattern: "/blog/:slug",
});
}
export const revalidate = 3600;Step 5: Style the components
All components render with data-trident-* attributes for easy CSS targeting:
/* styles/trident.css */
[data-trident-paragraph] {
@apply text-gray-700 leading-relaxed mb-4;
}
[data-trident-heading="2"] {
@apply text-2xl font-bold mt-8 mb-4;
}
[data-trident-heading="3"] {
@apply text-xl font-semibold mt-6 mb-3;
}
[data-trident-list] {
@apply my-4 pl-6;
}
[data-trident-list="ordered"] {
@apply list-decimal;
}
[data-trident-list="unordered"] {
@apply list-disc;
}
[data-trident-callout] {
@apply my-4 p-4 rounded-lg border-l-4;
}
[data-trident-callout="tip"] {
@apply bg-green-50 border-green-500;
}
[data-trident-callout="warning"] {
@apply bg-yellow-50 border-yellow-500;
}
[data-trident-table] {
@apply w-full my-4 border-collapse;
}
[data-trident-th],
[data-trident-td] {
@apply border border-gray-300 px-4 py-2;
}