Skip to content

Embed on Your Site

With a public API key and widget ID, you can embed blog lists and article pages on any existing site. No npm install or build step required.

Related

When to use this approach

Good fitNot ideal
Add a blog section to WordPress or static HTMLYou need full routing / SSR under your control
Let luno widgets handle layout and stylingYou must not expose API keys in the browser → BFF sample

Quick start

Step 1: Publish a widget in LUNO

  1. Admin → form set → publish at least one entry
  2. Create a widget and save list settings
  3. Publish a widget revision to get the public id (luno-xxxxxxxx)
  4. Settings → Public API keys → issue a key (luno_pub_…)

The widget editor Embed tags panel shows a ready-to-copy snippet for your project.

Step 2: Paste into HTML

html
<div id="luno-list"
     data-api-key="luno_pub_xxxxxxxx"
     data-api-url="https://api.luno.rest"
     data-widget-id="luno-abcdef12">
</div>
<script src="https://api.luno.rest/public/v1/embed/luno-abcdef12.js?api_key=luno_pub_xxxxxxxx" async></script>
ts
const mount = document.getElementById('luno-list')!
mount.dataset.apiKey = 'luno_pub_xxxxxxxx'
mount.dataset.apiUrl = 'https://api.luno.rest'
mount.dataset.widgetId = 'luno-abcdef12'

const s = document.createElement('script')
s.src =
  'https://api.luno.rest/public/v1/embed/luno-abcdef12.js?api_key=luno_pub_xxxxxxxx'
s.async = true
document.body.appendChild(s)
bash
npx @luno-cms/mcp setup
# Agent prompt example: "Give me the embed snippet for the published widget"
Attribute / URLMeaning
data-api-urlAPI origin (no trailing slash)
data-api-keyPublic API key
data-widget-idPublished widget public id
embed/….jsInjects theme, page size, CSS, etc. from your published revision

Appearance and sort order come from widget settings in the admin—you do not need data-theme on the div.

Step 3: Deploy static HTML

Host on Cloudflare Pages, GitHub Pages, or any web server.

Clone starter-widget, replace placeholders (YOUR_PUBLIC_API_KEY, etc.), and deploy.

Replacing YOUR_API_DOMAIN

Templates use https://YOUR_API_DOMAIN. Replace with the hostname only (e.g. api.luno.rest). Do not include https:// twice.

Widget types

List — #luno-list / [data-luno-list]

Paginated entry list for main blog pages.

Latest entries — [data-luno-top]

Compact list for home or sidebar.

html
<div data-luno-top
     data-api-key="luno_pub_…"
     data-api-url="https://api.luno.rest"
     data-widget-id="luno-abcdef12"
     data-count="5"
     data-heading="Latest"
     data-link-pattern="article.html?entry={slug}"
     data-see-more-url="index.html">
</div>

Article detail — #luno-article / [data-luno-article]

Reads slug from URL, e.g. article.html?entry=my-post.

html
<div id="luno-article"
     data-api-key="luno_pub_…"
     data-api-url="https://api.luno.rest"
     data-widget-id="luno-abcdef12"
     data-show-back="true"
     data-back-label="← Back to list">
</div>

Filters — [data-luno-filter]

Use the same widget id in data-target.

data-typePurpose
searchKeyword
categoryCategory
monthlyMonth
tagsTags

One embed script per page is enough for list, detail, and filters.

Multi-page layout

FilePurpose
index.htmlList + filters
article.htmlDetail (?entry=)
home.htmlHome + latest entries

See starters/starter-widget.

Frameworks (React / Next.js)

Copy framework snippets from the widget editor Embed tags panel.

Next.js example:

tsx
"use client";

import Script from "next/script";

const API_URL = process.env.NEXT_PUBLIC_LUNO_API_URL!;
const API_KEY = process.env.NEXT_PUBLIC_LUNO_API_KEY!;
const WIDGET_ID = "luno-abcdef12";

export function ArticleList() {
  const scriptSrc = `${API_URL}/public/v1/embed/${WIDGET_ID}.js?api_key=${encodeURIComponent(API_KEY)}`;

  return (
    <>
      <div
        id="luno-list"
        data-api-key={API_KEY}
        data-api-url={API_URL}
        data-widget-id={WIDGET_ID}
      />
      <Script src={scriptSrc} strategy="afterInteractive" />
    </>
  );
}

For full SSR, use the Public API and SDK starters.

Troubleshooting

SymptomCheck
Blank / no entriesPlaceholders not replaced; key, widget id, published entries
401 / 403Key is luno_pub_…; same project as widget
Stale settingsWidget has a published revision
404 on embed JSWidget id and API URL in script src

Next steps