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

@meetreeve/preview-embed

v2.4.0

Published

Remotion preview editor + UMD preview surface. Substrate (auth, theme, brand, postMessage, surfaces) moved to @meetreeve/embed — see DEV-791.

Readme

@meetreeve/preview-embed

Embed a Reeve composition preview in any site. React component + vanilla <script> drop-in.

Looking for the substrate SDK?

Previously this package was named @meetreeve/embed (1.0–1.3.1). In 2.0.0 (DEV-791) it was split:

| Concern | Package | Repo | |---|---|---| | Remotion preview editor (PreviewFrame, useReevePreview, ReevePreviewEditor, UMD bundle, schemas, presets) | @meetreeve/preview-embed | MindFortressInc/reeve-remotion/packages/preview-embed/ | | Embed tokens (mintEmbedToken, mintAnonEmbedToken), surface components (<ReeveSurface>, <ReeveCommsAdmin>), HostAppBrand registry, postMessage protocol primitives | @meetreeve/embed | MindFortressInc/reeve-embed |

If you only need the preview editor, you're in the right place. If you need auth tokens, brand chrome, or iframe surface components, install @meetreeve/embed.

The @meetreeve/[email protected]+/react module still ships <ReeveSurface> and <ReeveCommsAdmin>, but calling PreviewFrame / useReevePreview from there throws — they live here now.

Install (React)

pnpm add @meetreeve/preview-embed
# or: npm install @meetreeve/preview-embed
import { PreviewFrame } from '@meetreeve/preview-embed/react';

<PreviewFrame
  presetId="imessage-conversation"
  props={{
    contactName: 'Alex',
    messages: [{ sender: 'them', text: 'hey!' }],
    format: 'portrait',
    statusBarTime: '9:41',
  }}
/>

<PreviewFrame> reads aspect ratio from /presets automatically and sizes the wrapper accordingly. The iframe loads from https://videoapi.meetreeve.com by default; override with host prop.

Hook (lower-level)

import { useReevePreview } from '@meetreeve/preview-embed/react';

function MyPreview({ conversation }) {
  const { iframeRef, ready, error } = useReevePreview({
    presetId: 'imessage-conversation',
    props: conversation,
  });
  return <iframe ref={iframeRef} src="https://videoapi.meetreeve.com/preview/imessage-conversation" sandbox="allow-scripts allow-same-origin" />;
}

Install (vanilla — for non-React sites)

<script src="https://videoapi.meetreeve.com/embed/v1/reeve-preview.umd.js"></script>
<div id="my-preview" style="width: 360px"></div>
<script>
  const handle = ReevePreview.mount('#my-preview', {
    presetId: 'imessage-conversation',
    props: { /* ... */ },
  });
  // Update later
  // handle.update({ props: newProps });
  // handle.unmount();
</script>

The UMD bundle has zero runtime dependencies — drop it on any HTML page, including WordPress, Webflow, plain static sites.

Available presets

Fetch the full list:

import { fetchPresets } from '@meetreeve/preview-embed';
const { presets } = await fetchPresets();

Returns 28 compositions: ads, organic social, site content, messaging (iMessage, Slack), data viz, branding, utility, 3D scenes.

postMessage protocol

The component handles this for you. If you want to wire raw iframes:

| Direction | Type | Payload | |----------------|---------|-----------------------------| | iframe→parent | ready | {} | | parent→iframe | state | { payload: <props> } | | iframe→parent | error | { code, message } |

All messages have envelope { source: 'reeve-preview', v: 1, type: ... }.

The protocol primitives (isReevePreviewMessage, makeStateMessage, etc.) live in @meetreeve/embed as of 2.0.0 — this package re-exports them from its root for convenience.

Browser support

Modern evergreen browsers. The UMD bundle requires Promise, fetch, URL, MessageEvent — IE11 not supported.

Authoring forms

Beyond rendering a preview, the SDK provides a headless form hook plus lifted editor templates so consumers can build authoring UIs without rebuilding from scratch.

Headless hook

import { useReevePresetForm, PreviewFrame } from '@meetreeve/preview-embed/react';

function MyAuthoringPage() {
  const form = useReevePresetForm('imessage-conversation');

  return (
    <div className="grid grid-cols-2 gap-4">
      {/* Build your own UI from form.values + form.setValues / form.set */}
      <input
        value={form.values.contactName ?? ''}
        onChange={(e) => form.set('contactName', e.target.value)}
      />

      <PreviewFrame presetId="imessage-conversation" props={form.values} />
    </div>
  );
}

The hook returns:

  • values — typed, schema-defaulted, current form state
  • setValues(next) — replace the whole object
  • set(path, value) — dot-path setter ('messages.0.text' works)
  • errorsRecord<dotPath, message> from Zod, empty when valid
  • isValid — boolean
  • reset() — back to defaults
  • getFieldProps(path){ value, onChange, error, name } for spreading onto inputs
  • getArrayHelpers(path){ items, append, remove, move, replace } for arrays

Authoring with your own UI (all 28 presets)

useReevePresetForm works for any preset ID. Pair it with getFieldProps and getArrayHelpers to wire your design system's inputs in a few lines:

import { PreviewFrame, useReevePresetForm } from '@meetreeve/preview-embed/react';
import { Input, Button } from 'your-design-system';

function ImessageEditor() {
  const form = useReevePresetForm('imessage-conversation');
  const messages = form.getArrayHelpers('messages');

  return (
    <div>
      <Input {...form.getFieldProps('contactName')} placeholder="Contact name" />
      {messages.items.map((_, i) => (
        <div key={i}>
          <select {...form.getFieldProps(`messages.${i}.sender`)}>
            <option value="me">Me</option>
            <option value="them">Them</option>
          </select>
          <Input {...form.getFieldProps(`messages.${i}.text`)} />
          <Button onClick={() => messages.remove(i)}>Remove</Button>
        </div>
      ))}
      <Button onClick={() => messages.append()}>Add message</Button>
      <PreviewFrame presetId="imessage-conversation" props={form.values} />
    </div>
  );
}

messages.append() with no argument inserts a schema-derived blank ({ sender: 'me', text: '' } for iMessage). Pass messages.append({ sender: 'them' }) to merge a partial onto the blank.

Sender flips and sibling fields

Switching sender from 'them' to 'me' does not auto-scrub sibling fields like emoji or readReceipt. If the new branch rejects them, you'll see entries in form.errors at the relevant dot-path. Scrub them yourself if you want — the SDK leaves data preservation as a consumer choice.

Schemas, defaults, and blankFromSchema

The full Zod schemas and registry-derived defaults are exported as plain values:

import { schemas, defaults, blankFromSchema, type PresetId } from '@meetreeve/preview-embed/react';

// All 28 preset IDs:
const ids = Object.keys(schemas) as PresetId[];

// Defaults seeded from src/presets/registry.ts defaultProps:
const initial = defaults['ad-product-showcase'];

// Walk a schema to derive a blank value:
const blankSlackMessage = blankFromSchema(schemas['slack-conversation'].shape.messages.element);

Drop-in editor

import { ReevePreviewEditor, createReeveAIGenerator } from '@meetreeve/preview-embed/react';
import '@meetreeve/preview-embed/react/styles.css';

const aiGenerate = createReeveAIGenerator({
  baseUrl: 'https://api.meetreeve.com',
  getToken: async () => myAuth.getAccessToken(),
});

export default function MyEditor() {
  return (
    <ReevePreviewEditor
      presetId="imessage-conversation"
      aiGenerateHandler={aiGenerate}
      imageUploadHandler={async (file) => (await myUpload(file)).url}
    />
  );
}

For fields-only (no preview iframe), use <ReeveEditor> with the same prop signature minus host/variant/layout/toolbar/footer.

For per-field customization:

<ReeveEditor
  presetId="imessage-conversation"
  overrides={{
    contactAvatar: ({ value, onChange }) => <MyAvatarPicker value={value} onChange={onChange} />,
    'messages.*.reaction': ({ value, onChange, descriptor }) => (
      <MyReactionPicker
        value={value}
        onChange={onChange}
        options={descriptor.enumOptions ?? []}
      />
    ),
  }}
/>

To theme, override CSS variables on .reeve-editor:

.my-app .reeve-editor {
  --reeve-bg:        var(--background);
  --reeve-fg:        var(--foreground);
  --reeve-border:    var(--border);
  --reeve-accent:    var(--primary);
  --reeve-accent-fg: var(--primary-foreground);
  --reeve-radius:    var(--radius);
}

Direct schema access

import { schemas, defaults } from '@meetreeve/preview-embed/react';

schemas['imessage-conversation'].safeParse(myValues);
console.log(defaults['imessage-conversation']);

Substrate: auth, brand, surfaces

These moved to @meetreeve/embed in 2.0.0 (see top of file). See MindFortressInc/reeve-embed for the full docs. Quick pointers:

  • mintEmbedToken / verifyEmbedToken — authed HMAC JWTs for cross-host surfaces. @meetreeve/embed/auth
  • mintAnonEmbedToken / verifyAnonEmbedToken — anon-visitor tokens for chat.meetreeve.com etc. @meetreeve/embed/auth
  • createOriginAllowlist — postMessage origin allowlist helper. @meetreeve/embed/auth
  • <ReeveSurface> / <ReeveCommsAdmin> — generic iframe surface + Comms admin wrapper. @meetreeve/embed/react
  • fetchHostAppBrand / brandToCssVarshost_app_brands registry client. @meetreeve/embed/brand
  • BrandPack → CSS vars (older Studio-derived). @meetreeve/embed/theme

License

UNLICENSED. Internal use within MindFortress + authorized white-label partners.