npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@poesius/editor

v0.1.2

Published

Embed the Poesius presentation editor in your product — full chat+canvas or canvas-only for partners with their own AI chat. Session-token iframe SDK for https://poe.poesius.com.

Readme

@poesius/editor

Embed the Poesius presentation editor in your product. Your backend mints a short-lived session token; this package mounts a hosted iframe and bridges events to your UI. You keep your users, auth, and product chrome — Poesius runs the slide editor and AI.

Production API base: https://poe.poesius.com/api/v1
Hosted editor: https://editor.poesius.com (default; override only for local/dev)


Which component should you use?

| Component | Mode | When to use | |-----------|------|-------------| | PoesiusEditor | full (default) | You want the Poesius chat + canvas experience in one embed. Best when Poesius is the AI surface for the deck. | | PoesiusCanvas | canvas | You already have your own chat / agent UI. Embed only the slide canvas; drive AI from your backend with the same session token. | | createPoesiusEditor | either | Vanilla JS / non-React hosts. Pass mode: 'full' or mode: 'canvas'. |

Partner with Poesius chat (PoesiusEditor)

Use when end users should talk to Poesius inside the iframe (ask, enhance, generate) while editing slides.

import { PoesiusEditor } from '@poesius/editor';

<PoesiusEditor
  sessionToken={token}
  apiBase="https://poe.poesius.com/api/v1"
  theme="light"
  onExport={({ blobUrl, format }) => { /* download PPTX/PDF */ }}
  onAuthRequired={() => { /* prompt login / upgrade path */ }}
  onCreditExhausted={() => { /* show plan / credits UI */ }}
/>

Partner with your own chat (PoesiusCanvas)

Use when your product owns the conversation UI. The iframe shows the deck canvas only. Your server (or your chat) calls Poesius session APIs — enhance, generate, ingest — with the same session_token. The canvas stays in sync with the bound presentation.

import { PoesiusCanvas } from '@poesius/editor';

<PoesiusCanvas
  sessionToken={token}
  apiBase="https://poe.poesius.com/api/v1"
  onExport={({ blobUrl }) => { /* download */ }}
  onInitialized={({ presentationId, capabilities }) => {
    // Wire your chat to this presentation / session
  }}
/>

Equivalent vanilla:

createPoesiusEditor({
  el: document.getElementById('editor'),
  sessionToken,
  apiBase: 'https://poe.poesius.com/api/v1',
  mode: 'canvas', // or 'full'
});

Install

npm install @poesius/editor

Peer dependencies (optional — only needed for the React components): react and react-dom ≥ 18.


End-to-end integration

1. Prerequisites

  • A Poesius organization API key (poe_org_…). Keep it on your server only — never ship it to the browser.
  • A presentation_id that belongs to your org and the end user you identify as external_user_id.
  • Your frontend can reach https://editor.poesius.com in an iframe (allow framing / CSP as needed).

2. Mint a session (server-side)

POST https://poe.poesius.com/api/v1/sessions

// NEVER put the org key in the browser
const API = 'https://poe.poesius.com/api/v1';

const mintRes = await fetch(`${API}/sessions`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': process.env.POESIUS_ORG_API_KEY, // poe_org_...
  },
  body: JSON.stringify({
    presentation_id,
    external_user_id: 'alice', // your stable user id in your system
    capabilities: ['read', 'write', 'enhance', 'generate', 'export', 'ingest', 'chat'],
    ttl_minutes: 120,
  }),
});

const { session_token, expires_at, capabilities } = await mintRes.json();
// Hand ONLY session_token to the browser
res.json({ sessionToken: session_token, expiresAt: expires_at, capabilities });

Rules:

  • Org key minting requires external_user_id.
  • The presentation must already be scoped to that org + external_user_id.
  • Effective capabilities = what you request ∩ what your org allowlist permits.
  • read is always required to open the editor.

3. Mount the embed (client-side)

Pass sessionToken and apiBase. The SDK loads https://editor.poesius.com/embed, waits for the iframe ready signal, then sends the session over postMessage (the token is not put in the iframe URL).

Give the container a real height (default React wrapper uses minHeight: 480 and height: 100%).

4. (Optional) Attach documents

If the session has ingest:

POST /api/v1/sessions/{session_token}/artifacts
Content-Type: multipart/form-data

file=<pdf>
artifact_type=document

Artifacts bind to the session’s conversation so generate/enhance can use them.

5. (Optional) Headless generate from your backend

If you use PoesiusCanvas (own chat) or want server-driven deck builds:

POST /api/v1/sessions/{session_token}/generate
Content-Type: multipart/form-data

instruction=Build an exec summary deck from the attached brief
artifact_ids=<optional comma-separated ids>

Requires the generate capability. You can also inline a doc with document_base64 + filename when ingest is granted.


Session capabilities

Grant only what the embed (and your server calls) need:

| Capability | What it unlocks | |------------|-----------------| | read | Open and render the bound deck (required) | | write | Manual canvas edits (move, reorder, structure) | | chat | Poesius agent chat on this deck (mainly for full mode) | | enhance | AI redesign / elevate / edit-slide style ops | | refine | Lighter AI polish | | generate | Build / expand slides from content or instructions | | export | PPTX / PDF download | | ingest | Upload documents/images into this session | | templates.read | List / use templates | | templates.create | Create custom templates (also plan-gated) |

Typical partner defaults: read, enhance, export, ingest (add chat for PoesiusEditor; add generate / write as needed).

Sessions do not grant org admin, billing, listing other users’ decks, or cross-account template admin. Those stay on your Poesius org credentials / first-party auth.


API reference (SDK)

PoesiusEditor / PoesiusCanvas props

| Prop | Type | Description | |------|------|-------------| | sessionToken | string | Short-lived token from POST /sessions | | apiBase | string | e.g. https://poe.poesius.com/api/v1 | | editorOrigin | string? | Default https://editor.poesius.com. Local: http://localhost:5174 | | mode | 'full' \| 'canvas'? | Only on PoesiusEditor / createPoesiusEditor. Canvas wrapper forces canvas. | | theme | 'light' \| 'dark'? | Initial theme; update later via handle setTheme | | capabilities | string[]? | Optional hint to the embed; server session is authoritative | | className / style | React | Container styling | | onReady | () => void | Iframe loaded and ready for init | | onInitialized | (info) => void | Session accepted; includes presentationId, conversationId, capabilities | | onExport | (info) => void | User/export finished; blobUrl / url, format: 'pptx' \| 'pdf' | | onCreditExhausted | () => void | Credits / quota exhausted — show your upgrade UI | | onAuthRequired | (info?) => void | Action needs auth or a missing capability | | onError | (message) => void | Embed error string | | onNavigate | (path) => void | Host should navigate (e.g. back to your dashboard). Embed cannot own your router. |

createPoesiusEditor(options) → handle

const handle = createPoesiusEditor({ el, sessionToken, apiBase, mode: 'full' });

handle.setTheme('dark');
handle.setSessionToken(newToken); // refresh before expiry
handle.requestExport('pptx');
handle.destroy();                 // unmount iframe + listeners

Security checklist

  1. Org API key (poe_org_…) stays on the server. Only session_token goes to the browser.
  2. Scope every deck with external_user_id so one end user cannot open another’s presentation under your org.
  3. Mint with the minimum capabilities you need; rotate sessions with TTL (ttl_minutes, 5–1440).
  4. Refresh the session before expires_at and call setSessionToken (or remount with a new token).
  5. Do not put long-lived secrets in the iframe URL or frontend env.

Full React example (own chat + canvas)

import { useEffect, useState } from 'react';
import { PoesiusCanvas } from '@poesius/editor';

export function DeckWorkspace({ presentationId }: { presentationId: string }) {
  const [sessionToken, setSessionToken] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      // Your backend mints with poe_org_* and returns only the session token
      const res = await fetch('/api/poesius/session', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ presentationId }),
      });
      const data = await res.json();
      if (!cancelled) setSessionToken(data.sessionToken);
    })();
    return () => {
      cancelled = true;
    };
  }, [presentationId]);

  if (!sessionToken) return <div>Loading editor…</div>;

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '360px 1fr', height: '100vh' }}>
      <YourChat
        // Your chat calls your backend → Poesius session APIs with the same token
        sessionToken={sessionToken}
      />
      <PoesiusCanvas
        sessionToken={sessionToken}
        apiBase="https://poe.poesius.com/api/v1"
        theme="light"
        onExport={({ blobUrl, format }) => {
          const a = document.createElement('a');
          a.href = blobUrl!;
          a.download = `deck.${format}`;
          a.click();
        }}
        onCreditExhausted={() => alert('Credits exhausted')}
        onError={(message) => console.error(message)}
      />
    </div>
  );
}

Vanilla example (full editor)

import { createPoesiusEditor } from '@poesius/editor';

const handle = createPoesiusEditor({
  el: document.getElementById('editor'),
  sessionToken,
  apiBase: 'https://poe.poesius.com/api/v1',
  mode: 'full',
  theme: 'light',
  onInitialized: ({ presentationId, capabilities }) => {
    console.log('ready', presentationId, capabilities);
  },
  onExport: ({ blobUrl, format }) => {
    // trigger download
  },
});

Local development

Point the iframe and API at your local stacks:

createPoesiusEditor({
  el,
  sessionToken,
  apiBase: 'http://localhost:8000/api/v1',
  editorOrigin: 'http://localhost:5174',
});

CDN

The same loader can be published as https://js.poesius.com/editor/v1/editor.js (Stripe.js-style). The npm package exposes the same API for bundlers.


Support

  • API host: https://poe.poesius.com
  • Editor host: https://editor.poesius.com
  • Package: @poesius/editor

If minting fails with 403, verify the presentation is tied to your org and the same external_user_id you send at mint time. If the iframe stays blank, check that apiBase is https://poe.poesius.com/api/v1 and that the session has not expired.