Embed a Changelog
Prerequisites
Section titled “Prerequisites”- 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.
Option A: Script-tag widget (zero code)
Section titled “Option A: Script-tag widget (zero code)”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:
| Attribute | Default | Description |
|---|---|---|
data-key | required | Your publishable key (nv_pub_...) |
data-theme | auto | light, dark, or auto (follows system preference) |
data-limit | 5 | Number of entries to show (max 50) |
data-show-badge | false | Show “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)”---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> );}Publish an entry
Section titled “Publish an entry”From the Nordva Launch dashboard → Changelog, or via the API:
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 }'Let users subscribe
Section titled “Let users subscribe”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', },});// 201: subscribed, 409: already subscribedSubscribers receive an email when you publish with notify_subscribers: true.