Want to bring your community directly into your existing website? Outpost’s embeddable widget lets you integrate discussions without sending users to a separate site — and with Embed SSO, your users stay signed in seamlessly.
Quick Start
Add this snippet wherever you want your community to appear:
<div id="outpost-embed"></div>
<script
src="https://outpost.ninja/embed.js"
data-community="your-community-slug"
></script>
That’s it. One script tag, and your entire community loads inside an auto-resizing iframe.
Enabling Embedding
- Go to Admin Settings → Embeddings
- Toggle Enable Embedding on
- Copy the embed code from the Getting Started tab
Optionally, configure Allowed Domains to restrict which websites can embed your community. If left empty, any domain can embed it.
Three Embed Modes
Full Community (Default)
The complete community experience — sidebar navigation, categories, search, profiles, and all features:
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
></script>
Feed Widget
A compact topic list, perfect for sidebars or specific content sections. Filter by category, tag, or keyword:
<!-- Filter by category -->
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
data-mode="feed"
data-category="feature-requests"
></script>
<!-- Filter by tag -->
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
data-mode="feed"
data-tag="bug-report"
></script>
<!-- Filter by keyword -->
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
data-mode="feed"
data-context="pricing"
></script>
Single Topic
Embed one specific discussion thread — ideal for docs pages, knowledge base articles, or blog post comments:
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
data-mode="topic"
data-topic="your-topic-slug"
></script>
Theme & Styling
Make the embed match your website’s design with data attributes. All are optional — only override what you need:
| Attribute | Description | Example |
|---|---|---|
data-theme-mode |
Force light or dark | "light" or "dark" |
data-theme-primary |
Accent/brand color | "#6366f1" |
data-theme-bg |
Base background | "#ffffff" |
data-theme-surface |
Card background | "#f8fafc" |
data-theme-elevated |
Elevated elements | "#f1f5f9" |
data-theme-text |
Primary text color | "#0f172a" |
data-theme-border |
Border color | "rgba(0,0,0,0.1)" |
data-theme-font |
Font family | "'Inter', sans-serif" |
data-theme-radius |
Border radius (px) | "8" |
data-theme-transparent |
Transparent background | "true" |
data-css |
Custom CSS URL | "https://your-site.com/outpost.css" |
data-compact |
Dense spacing | "true" |
Full example:
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
data-theme-mode="light"
data-theme-primary="#6366f1"
data-theme-bg="#ffffff"
data-theme-surface="#f8fafc"
data-theme-text="#0f172a"
data-theme-font="'Inter', sans-serif"
data-theme-radius="8"
></script>
Sizing & Layout
Auto Height (Default)
The iframe automatically resizes to match its content. No scroll bars, no fixed height — it just fits.
Fixed Height with Scroll
For a contained widget with internal scrolling:
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
data-height="calc(100vh - 80px)"
></script>
Custom Container
Target a specific div instead of the default:
<div id="my-forum"></div>
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
data-container="my-forum"
></script>
Centered, Constrained Width
<div style="max-width: 1200px; margin: 0 auto;">
<div id="outpost-embed"></div>
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
></script>
</div>
Authentication in Embeds
By default, when a user clicks "Sign In" inside the embed:
- A popup window opens with the Outpost login page
- The user authenticates via magic link
- The popup closes and the embed refreshes with the authenticated session
This works out of the box with no configuration. But for a seamless experience where users are already signed into your app, use Embed SSO.
Embed SSO (Single Sign-On)
Embed SSO lets your users access the community without a separate login. If they’re signed into your app, they’re signed into Outpost.
How SSO Works
Your Frontend → Your Backend → Outpost API → Embed iframe
- Your frontend requests an Outpost SSO token from your backend
- Your backend calls Outpost’s token endpoint with the user’s email and name
- Outpost returns a one-time token (valid for 120 seconds)
- You pass the token to the embed script via
data-user-token - The embed exchanges it for a session — the user is logged in
Step 1: Generate an SSO Secret
- Go to Admin Settings → Embeddings → SSO tab
- Click Generate Secret
- Copy the secret (format:
opsk_...) — it’s only shown once - Store it securely in your backend’s environment variables
Step 2: Create a Backend Endpoint
Your backend mints Outpost tokens for authenticated users. Here are examples for common stacks:
Node.js / Express:
app.post('/outpost-token', requireAuth, async (req, res) => {
const response = await fetch(
'https://outpost.ninja/api/community/YOUR_SLUG/embed/sso/token',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: process.env.OUTPOST_SSO_SECRET,
email: req.user.email,
display_name: req.user.name,
}),
}
);
const data = await response.json();
res.json({ token: data.token });
});
Next.js (App Router):
import { getServerSession } from 'next-auth';
export async function POST(req: Request) {
const session = await getServerSession();
if (!session?.user?.email) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
const res = await fetch(
`https://outpost.ninja/api/community/YOUR_SLUG/embed/sso/token`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: process.env.OUTPOST_SSO_SECRET,
email: session.user.email,
display_name: session.user.name ?? '',
}),
}
);
return Response.json(await res.json());
}
Step 3: Pass the Token to the Embed
On your frontend, fetch the token and inject it into the embed script:
async function loadOutpostEmbed() {
let ssoToken = null;
if (userIsSignedIn) {
try {
const res = await fetch('/outpost-token', {
method: 'POST',
headers: { Authorization: `Bearer ${idToken}` },
});
if (res.ok) {
const data = await res.json();
ssoToken = data.token;
}
} catch (err) {
console.warn('SSO token fetch failed:', err);
}
}
const script = document.createElement('script');
script.src = 'https://outpost.ninja/embed.js';
script.setAttribute('data-community', 'YOUR_SLUG');
if (ssoToken) {
script.setAttribute('data-user-token', ssoToken);
}
document.body.appendChild(script);
}
Or if the token is available at render time:
<script
src="https://outpost.ninja/embed.js"
data-community="your-slug"
data-user-token="the-token-from-your-backend"
></script>
SSO Security Details
- Tokens are single-use — deleted from Redis immediately after exchange
- Tokens expire after 120 seconds
- The SSO secret is stored as a SHA-256 hash — Outpost never stores the raw secret
- Session cookies are set as
httpOnly,SameSite=None,Secure - If the user doesn’t exist in Outpost, they’re automatically created and added to the community
Allowed Origins
Restrict which domains can embed your community:
- Go to Embeddings → Getting Started tab
- Add your domains under Allowed Domains (one per line):
https://your-website.com https://app.your-website.com https://docs.your-website.com - If left empty, any domain can embed your community
The Embed Layout
The embedded community uses a minimal layout optimized for iframe display:
- Streamlined header with logo, title, theme toggle, and sign-in
- No full-width banner image
- Collapsible mobile navigation
- "Powered by Outpost" footer (removable on paid plans)
- Transparent background option for blending with your site
All community features work inside the embed — posting, reactions, search, DMs, profiles, and notifications.
Use Cases
| Scenario | Recommended Setup |
|---|---|
| Documentation site | Feed widget filtered by category below each doc page |
| Product page | Feed widget with data-tag="feature-requests" |
| Blog comments | Single topic mode per blog post |
| Course platform | Full community or feed filtered by lesson category |
| SaaS dashboard | Full community with SSO for seamless auth |
| Knowledge base | Single topic mode for each article’s discussion |
PostMessage API
For advanced integrations, the embed communicates with your page via window.postMessage:
| Message Type | Direction | Purpose |
|---|---|---|
outpost-resize |
Embed → Parent | Height change notification |
outpost-url-change |
Embed → Parent | Internal navigation (for deep linking) |
outpost-auth |
Embed → Parent | User clicked sign in (triggers popup) |
outpost-auth-complete |
Parent → Embed | Auth popup closed successfully |
outpost-sso-token |
Parent → Embed | Deliver SSO token on load |
You can listen to these events to sync your app’s URL, track navigation, or trigger custom behaviors.
Tips
- Use SSO if your users are already authenticated — the seamless experience is worth the setup
- Match your theme using the data-theme attributes for a native feel
- Use feed mode for focused, contextual discussions on specific pages
- Set allowed origins in production to prevent unauthorized embedding
- Test in incognito to verify the non-authenticated experience works correctly
Embedding transforms Outpost from a standalone platform into a composable building block for your web presence.