:::note
**TL;DR**
- Paste one snippet, add a browser-safe publishable key (pk_live_...), and a self-fetching web component renders live spiritual readings with no backend and no build step.
- A publishable key is safe in public page source: it cannot read your account, and an exact-host origin allowlist plus a frame-ancestors guard stop key theft.
- One key powers widgets across every RoxyAPI domain, from horoscopes and natal charts to Vedic kundli, human design, tarot, and numerology.
- Copy-paste widgets run in the browser; the npm component library is the framework-app path where your secret key stays on the server.
:::

Most tutorials for adding a horoscope or a natal chart to a website assume you will stand up a server. You provision a backend, hide an API key, write a fetch handler, and wire a form to it. For a marketing site, a Linktree page, or a Squarespace store, that is a lot of infrastructure for one reading. RoxyAPI shipped a no-code path this month that removes all of it. You paste one snippet, drop in a browser-safe publishable key, and a self-fetching web component draws its own input form, calls the API from the visitor browser, and renders the reading. This guide covers the architecture, the publishable-key security model that makes a key safe in public page source, and which delivery mode fits each platform. Browse the full set on the [widgets gallery](/widgets "copy-paste embeddable widgets for every RoxyAPI domain"), all built on the [Astrology API](/products/astrology-api "production-ready astrology API with natal charts, horoscopes, and transits").

## How do you embed a live spiritual widget with no backend?

You add two lines of HTML. A script tag loads the component bundle from the jsDelivr CDN, and a roxy element names the widget and carries your publishable key. The component renders its own input form, fetches live data from the API when a visitor submits, and shows the reading. There is no server, no build step, and no framework to install.

The lead example is the daily horoscope card, a globally accessible surface. Each widget is a self-fetching web component named `<roxy-{slug}>`, built with Lit and delivered from the jsDelivr CDN. Point it at an endpoint, give it a key, and it handles the rest: a sign picker or a birth-date form for coordinate readings, a loading state, an error state, and the result. RoxyAPI ships four delivery modes for the same widget, so you can match the one your platform accepts. The web-component snippet also links an optional theme stylesheet, so the reading matches a warm practitioner look out of the box.

:::tabs
### Hosted embed URL
```text
https://roxyapi.com/embed/horoscope-card?pk=pk_live_YOUR_KEY
```

### Iframe
```html
<iframe src="https://roxyapi.com/embed/horoscope-card?pk=pk_live_YOUR_KEY" title="Horoscope card widget" style="border:0;width:100%;height:600px" loading="lazy"></iframe>
```

### Web component
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/styles/themes/practitioner.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js"></script>
<roxy-horoscope-card data-endpoint="astrology/horoscope/{sign}/daily" method="GET" publishable-key="pk_live_YOUR_KEY" lang="en"></roxy-horoscope-card>
```

### One tag, auto-mount
```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/widgets.js"></script>
<div data-roxy-widget="horoscope-card" data-publishable-key="pk_live_YOUR_KEY"></div>
```
:::

Ready to ship one? The [Astrology API](/products/astrology-api "production-ready astrology API with natal charts, horoscopes, and transits") powers every widget from one account, and a single subscription unlocks all domains. [See pricing](/pricing "RoxyAPI plans and flat all-inclusive pricing").

## Why is a publishable key safe to put in public page source?

A publishable key starts with pk_live_ or pk_test_ and is designed to live in HTML anyone can view. It carries only a signed subscription reference, so it cannot read your account, change billing, or reach any admin surface. You bind it to an exact-host origin allowlist, so a request from any other domain is rejected. And a secret key, the class meant for servers, is refused by the widget in the browser.

RoxyAPI uses two key classes. Secret keys have full access, stay on your server, and drive the SDKs and the Remote MCP server. Publishable keys are the browser class. When you mint one in your account dashboard, you list the exact origins allowed to use it, such as https://yourdomain.com and https://www.yourdomain.com, with no wildcards. The API refuses a publishable key on the MCP endpoint entirely, because server-side agent traffic has no origin to check and a leaked key there would be the worst case. Every failed origin check still counts against your monthly quota, so a stolen key cannot be brute-forced for free from a wrong origin.

:::warning
A secret key is never safe in page source, and the widget refuses it in the browser. Use a publishable key for anything a visitor can view, and keep secret keys on your server for SDK and Remote MCP calls.
:::

## How does the origin allowlist protect a script tag versus an iframe?

The two delivery modes enforce the allowlist differently, because the fetch starts from a different place. A script-tag widget fetches from the page it lives on, so the request carries the real origin of your site and the allowlist checks it directly. An iframe fetches from roxyapi.com, so the allowlist cannot see your site, and the route gates on the parent page instead.

For the script tag and one-tag modes, the browser sends the origin of the embedding page on every call. If that origin is on the allowlist the request passes; if not, the API returns a 403 with code origin_not_allowed. This is the same guard the SDKs and server calls rely on, applied to a browser key. The hosted embed URL is different. Because the widget runs inside an iframe served from roxyapi.com, its fetch looks same-origin to the API, so the origin allowlist cannot protect it. The embed route closes this two ways. Server-side, it turns the allowlist for your key into a frame-ancestors content-security-policy, so the browser refuses to frame the widget on any page not on the list. Client-side, an inline guard checks the ancestor origins and the referrer against the same list before the component loads, and fails closed with a visible message when it cannot verify the parent.

| Delivery mode | Where the fetch starts | How the origin is enforced |
|---|---|---|
| Script tag or one-tag | The embedding page | Real page origin checked against the allowlist; a wrong origin returns 403 origin_not_allowed |
| Hosted embed URL or iframe | roxyapi.com (the iframe) | frame-ancestors policy built from the allowlist, plus a client ancestor guard that fails closed |

A key with an empty allowlist frames anywhere and is protected by the per-key quota and rate limit alone. List your exact site origins the moment you go live.

## Which widget delivery mode should you use for your platform?

Pick the mode by what your platform lets you paste. A site builder that runs custom JavaScript takes the script tag. A page that accepts only a link or an HTML embed block takes the hosted embed URL or the iframe. The hosted URL is what unlocks paste-one-link surfaces that never run scripts, the reach an npm install can never match.

Squarespace takes a copy-paste browser widget in a Code Block, on a plan that runs custom JavaScript. Wix uses an Embed-HTML element. Notion, Linktree, and Stan Store accept the hosted embed URL as a single link, which is the surface a package install cannot reach. WordPress has its own path through the plugin. These platforms are not interchangeable, so read the platform walkthrough for yours rather than guessing at the paste target.

| Platform | What to paste | Guide |
|---|---|---|
| Squarespace | Script tag in a Code Block (custom-JS plan) | [Squarespace guide](/docs/integrations/squarespace "embed RoxyAPI widgets on Squarespace step by step") |
| Wix | Hosted embed URL in an Embed-HTML element | [Wix guide](/docs/integrations/wix "embed RoxyAPI widgets on Wix step by step") |
| Notion, Linktree, Stan Store | The hosted embed URL as one link | Covered on the widgets gallery |
| WordPress | The plugin path | [WordPress guide](/docs/integrations/wordpress "add RoxyAPI readings to WordPress") |

## When should you use a widget instead of the npm component library?

Use a widget when you have no backend and want to paste and ship. Use the npm component library when you are building an app in a framework and want to fetch the data yourself. The widget is self-fetching and uses a publishable key in the browser. The npm component takes the data you already fetched, so your secret key stays on your server and never touches the page.

The two surfaces share the same rendered output but differ in who fetches and where the key lives. The copy-paste widgets on the widgets gallery draw their own form, call the API from the browser with a publishable key, and need no build step. The npm components, installed for React, Vue, or any framework, are props-in and events-out: you fetch the reading with a secret key on your server, then pass the response as a data prop. That keeps the key server-side and gives an app full control over loading and caching. Both surfaces cover the full catalog. One key powers widgets across 12 insight domains and 164 plus endpoints, from Western astrology and Vedic kundli to human design, forecast, tarot, and numerology. Swapping the horoscope card for a natal chart is one attribute change to the element line:

```html
<roxy-natal-chart data-endpoint="astrology/natal-chart" method="POST" publishable-key="pk_live_YOUR_KEY" lang="en"></roxy-natal-chart>
```

| Question | Copy-paste widget | npm component library |
|---|---|---|
| Fetches data | Yes, self-fetching in the browser | No, you fetch and pass a data prop |
| Key class | Publishable (pk_) in the page | Secret, kept on your server |
| Build step | None | Framework build (React, Vue, or any) |
| Best for | No-code sites, embeds, one-link pages | Apps where you control fetching and caching |

## FAQ

**Do I need a backend to embed a spiritual widget?**

No. RoxyAPI widgets are self-fetching web components. You paste one snippet, add a publishable key, and the component renders its own form and calls the API from the visitor browser. There is no server, no build step, and no framework to install.

**Is a publishable key safe to put in my website source?**

Yes. A publishable key (pk_live_ or pk_test_) is browser-safe by design. It cannot read your account or change billing, and you bind it to an exact-host origin allowlist so only your domains can use it. Keep secret keys on your server for SDK and Remote MCP calls.

**Can I embed a RoxyAPI widget on Squarespace, Wix, or Notion?**

Yes. Squarespace takes the script tag in a Code Block, Wix uses an Embed-HTML element, and Notion, Linktree, and Stan Store accept the hosted embed URL as a single link. Every RoxyAPI domain is available from the same publishable key.

**How many widgets can one publishable key power?**

One key powers widgets across all 12 RoxyAPI insight domains and 164 plus endpoints, including Western astrology, Vedic kundli, human design, forecast, tarot, and numerology. A single subscription unlocks every domain, with no per-widget or per-domain fee.

**What is the difference between a RoxyAPI widget and the npm component?**

A widget is self-fetching and uses a publishable key in the browser, so you paste and ship with no backend. The npm component takes data you fetch yourself with a secret key on your server, which suits framework apps that control their own fetching and caching.

## Conclusion

Live spiritual readings no longer require a backend. Paste one snippet, add a publishable key that is safe in public source, and one account powers every widget across the catalog. Browse the set on the [widgets gallery](/widgets "copy-paste embeddable widgets for every RoxyAPI domain"), build on the [Astrology API](/products/astrology-api "production-ready astrology API with natal charts, horoscopes, and transits"), and check the flat [pricing](/pricing "RoxyAPI plans and flat all-inclusive pricing").