Skip to content

Embed a Changelog

  • Nordva Launch account with at least one published changelog entry
  • Any frontend framework (or plain HTML)

The public feed (GET /public/changelog/<your-project-slug>) needs no API key and allows any origin, so your visitors’ browsers can call it directly. Entries carry body_markdown; render it with the Markdown library you already use.

Drop this into any HTML page:

<script src="https://cdn.nordva.dev/v1/changelog.js"
data-key="nv_pub_live_YOUR_KEY"
data-theme="auto"
data-limit="5"
data-show-badge="true">
</script>
<nordva-changelog></nordva-changelog>

The widget renders inside a Shadow DOM — no style conflicts with your page. The data-show-badge="true" attribute shows a “New” badge when entries have been published since the user last visited.

Attributes:

AttributeDefaultDescription
data-keyrequiredYour publishable key (nv_pub_...)
data-themeautolight, dark, or auto (follows system preference)
data-limit5Number of entries to show (max 50)
data-show-badgefalseShow “New” badge when there are unseen entries

Option B: Fetch in Astro (server-side, no auth)

Section titled “Option B: Fetch in Astro (server-side, no auth)”
src/pages/changelog.astro
---
import { marked } from 'marked';
const res = await fetch('https://api.nordva.dev/public/changelog/your-project-slug');
const { data: entries } = await res.json();
---
<main>
{entries.map(entry => (
<article>
<time>{new Date(entry.published_at).toLocaleDateString()}</time>
<h2><a href={entry.public_url}>{entry.title}</a></h2>
<small>{entry.category}{entry.version ? ` · ${entry.version}` : ''}</small>
<div set:html={marked.parse(entry.body_markdown)} />
</article>
))}
</main>

No API key needed. This renders at build time in Astro’s static mode.

Option C: Fetch in React (client-side, no auth)

Section titled “Option C: Fetch in React (client-side, no auth)”
import { useEffect, useState } from 'react';
import { marked } from 'marked';
interface ChangelogEntry {
id: string;
title: string;
body_markdown: string;
category: 'feature' | 'fix' | 'improvement' | 'security' | 'breaking';
version: string | null;
published_at: string;
public_url: string;
}
export function Changelog() {
const [entries, setEntries] = useState<ChangelogEntry[]>([]);
useEffect(() => {
fetch('https://api.nordva.dev/public/changelog/your-project-slug')
.then(r => r.json())
.then(({ data }) => setEntries(data.slice(0, 10)));
}, []);
return (
<ul>
{entries.map(entry => (
<li key={entry.id}>
<time>{new Date(entry.published_at).toLocaleDateString()}</time>
<h3><a href={entry.public_url}>{entry.title}</a></h3>
<div dangerouslySetInnerHTML={{ __html: marked.parse(entry.body_markdown) }} />
</li>
))}
</ul>
);
}

From the Nordva Launch dashboardChangelog, or via the API:

Terminal window
curl -X POST https://api.nordva.dev/v1/changelog/entries \
-H "Authorization: Bearer nv_live_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Dark mode is here",
"body_markdown": "## Dark mode\n\nYou can now toggle dark mode from settings.",
"category": "feature",
"notify_subscribers": true
}'

Add an email subscription form using a publishable key:

const res = await fetch('https://api.nordva.dev/v1/changelog/subscribers', {
method: 'POST',
headers: {
'Authorization': 'Bearer nv_pub_live_YOUR_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: 'user@example.com' }),
});
// 201: subscribed, 409: already subscribed

Subscribers receive an email when you publish with notify_subscribers: true.