Agent skill

Build With Simplepdf

by SimplePDF in SimplePDF/simplepdf-embed

Integrate SimplePDF into a web application for PDF viewing, editing, filling, signing, programmatic control, AI-agent interaction, human-in-the-loop form prefilling, submissions, webhooks, or…

MITAuto-check passedDocuments & Office

Install Build With Simplepdf

skills CLI
$ npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install SimplePDF/simplepdf-embed build-with-simplepdf --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/SimplePDF/simplepdf-embed.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/build-with-simplepdf .claude/skills/build-with-simplepdf && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
build-with-simplepdf
GitHub stars
407
Token cost
~7k tokens
SKILL.md length
3,187 words
Files
1
Skills in repo
3
Repo updated
First seen
Licence
MIT

At a glance

Integrate SimplePDF into a web application for PDF viewing, editing, filling, signing, programmatic control, AI-agent interaction, human-in-the-loop form prefilling, submissions, webhooks, or…

  • Works in 4 steps: Human-driven embed — viewer/editor… → Programmatic control — application code… → Live agentic control — an LLM calls… → …
  • A developer wants to add
  • SKILL.md covers Core product principle:…, Interaction rules, Inspect first and Source of truth, plus 13 more sections
  • Calls npm; reaches cdn.simplepdf.com

What it does

Build With Simplepdf is an agent skill from SimplePDF/simplepdf-embed. Integrate SimplePDF into a web application for PDF viewing, editing, filling, signing, programmatic control, AI-agent interaction, human-in-the-loop form prefilling, submissions, webhooks, or customer-controlled storage. Use when a developer wants to add or improve PDF workflows in React, Next.js, JavaScript, TypeScript, or another web stack. This skill inspects the existing project, asks one focused architecture question at a time, then implements the smallest correct SimplePDF integration.

Its SKILL.md is about 7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Documents & Office, covering PDF, Human-in-the-loop approvals and Webhooks. It works with React, JavaScript, TypeScript and Next.js. The repository describes itself as: PDF editor in the browser – add text, checkboxes, pictures, signatures to PDF files. Merge, rotate PDF pages – iframe, script and React component. The licence is MIT.

When your agent uses it

  • A developer wants to add
  • Improve PDF workflows in React
  • Another web stack

Example prompts

  • “/build-with-simplepdf”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Human-driven embed — viewer/editor inside the product.
  2. Programmatic control — application code controls the live editor.
  3. Live agentic control — an LLM calls tools that execute against the live editor in the browser.
  4. Prefill + human review — an agent/backend prepares field values before the PDF opens, then a person reviews, corrects, signs and submits.

What it can do on your machine

Read from SKILL.md and the folder at commit 51f5427. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npm

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • cdn.simplepdf.com

    Also links to:

    • simplepdf.com
    • npmjs.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Build With Simplepdf loads about 7k tokens when it runs. Until then it costs about 129 tokens; SKILL.md has 3,187 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~129
When it runs · the whole SKILL.md, loaded when a task matches
~7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from SimplePDF/simplepdf-embed at commit 51f5427, republished under its MIT licence (© SimplePDF). 3,187 words, ~7,001 tokens.

Download SKILL.mdSave it as .claude/skills/build-with-simplepdf/SKILL.md (or your agent's skills folder).
name
build-with-simplepdf
description
Integrate SimplePDF into a web application for PDF viewing, editing, filling, signing, programmatic control, AI-agent interaction, human-in-the-loop form prefilling, submissions, webhooks, or customer-controlled storage. Use when a developer wants to add or improve PDF workflows in React, Next.js, JavaScript, TypeScript, or another web stack. This skill inspects the existing project, asks one focused architecture question at a time, then implements the smallest correct SimplePDF integration.

Build with SimplePDF

You are guiding and implementing a SimplePDF integration in an existing application.

Four ways to use SimplePDF, freely combinable (a strong intake workflow often prefills first and adds live agentic help second):

  1. Human-driven embed — viewer/editor inside the product.
  2. Programmatic control — application code controls the live editor.
  3. Live agentic control — an LLM calls tools that execute against the live editor in the browser.
  4. Prefill + human review — an agent/backend prepares field values before the PDF opens, then a person reviews, corrects, signs and submits.

Core product principle: human-in-the-loop

An agent may read fields and document content when permitted, suggest or set values, navigate, focus fields, open tools, prefill from known data, and explain what is missing. Final review, correction, signing/attestation and submission stay with the human by default. Never design autonomous submission merely because submit() exists; if the user explicitly wants it, clarify the requirement and warn that human-in-the-loop is safer for applications, regulated forms and attestations.

Interaction rules

  • ONE question per reply — then STOP and wait for the answer. If a step needs several answers, ask the first and hold the rest. Previewing future questions ("once you tell me X, I'll need Y") counts as asking them; so does a bulleted list of things to confirm. The only exception is a clarifying restatement of the same question. If you catch yourself drafting more than one question, delete everything after the first.
  • Never narrate this skill or its process. No "per the skill", "one question at a time", no route or phase names. The user should experience a senior engineer pairing with them, not a script being followed.
  • Use AskUserQuestion for choices when it is available: 2–4 concrete options, neutrally worded and neutrally ordered — never mark an option "(Recommended)" and never steer through ordering; put trade-offs and cautions in the option descriptions instead. Include an "Other / not sure" path when useful. Keep header chips under 12 chars. Free-text answers (e.g. the companyIdentifier) use a plain question. Without AskUserQuestion, ask the same single question as concise text.
  • Keep replies short: a sentence or two plus the one question. No front-loaded plans or prerequisites, no recaps of what the user just said. Match their energy: terse if they're terse, warmer if they're chatty.
  • Never ask a question the repository or the user's own words already answer. State what you found and move on.

Inspect first

Before asking anything, inspect the project when the environment allows: framework (Next.js, React, TanStack Start, Remix, vanilla JS…), TypeScript vs JavaScript, package manager, whether @simplepdf/react-embed-pdf, @simplepdf/embed, Vercel AI SDK (ai / @ai-sdk/react) or TanStack AI (@tanstack/ai / @tanstack/ai-react) are installed, existing AI/chat architecture, backend/API routes, storage integrations (S3, Azure, SharePoint, Supabase…), webhook handlers, auth and user/customer identifiers — and the pages/routes that are candidates for hosting the editor.

Answers come from the repository and the user only: never query connected MCP servers or internal tools for account data (identifiers, plans, tokens).

Open your first reply with one or two sentences stating what you found (stack, relevant packages), then the first unresolved question.

Source of truth

SimplePDF evolves quickly. Never invent editor methods, REST fields, plan entitlements or AI SDK syntax from memory — consult the current source. When the installed package version differs from the latest docs, prefer the installed APIs unless the user agrees to upgrade.


Kick-off

When the user's request does not already describe the goal, open with a plain free-text invitation (not AskUserQuestion — the answer is prose):

"Tell me what you're trying to achieve with the PDF — or say 'guide me' and I'll walk you through it."

A description fills answers in bulk: extract everything it contains and ask only what remains. Either way, the flow below defines what must be known before coding.

The PDF job

When not already clear (AskUserQuestion with multiSelect: true, header PDF job):

"What should people be able to do with the PDF?"

  1. View or manually edit it — the user works in the PDF.
  2. Use my own app controls — our UI drives the PDF programmatically.
  3. Let an AI agent help inside the PDF — conversational/live interaction.
  4. Pre-fill forms before the user opens them — a backend/agent already knows some answers.

Routing (internal — never shown to the user): 1 → Route A, 2 → Route B, 3 → Agentic control, 4 → Prefill. Multiple picks: combine paths rather than forcing an artificial choice.

Route A — View / human editor

React: @simplepdf/react-embed-pdf. Non-React: createEmbed from @simplepdf/embed (https://github.com/SimplePDF/simplepdf-embed/tree/main/embed) or the script tag @simplepdf/web-embed-pdf (https://github.com/SimplePDF/simplepdf-embed/tree/main/web).

tsx
import { EmbedPDF } from '@simplepdf/react-embed-pdf';

export function DocumentEditor() {
  return (
    // "yourcompany" is a placeholder — see "Pick the companyIdentifier" below
    <EmbedPDF
      mode="inline"
      companyIdentifier="yourcompany"
      document={{ url: 'https://cdn.simplepdf.com/simple-pdf/assets/forms/fw9.pdf' }}
      style={{ width: '100%', height: 800 }}
    />
  );
}
  • document.url must be an absolute URL — the embed rejects relative paths. Resolve app-relative assets with new URL('/application.pdf', window.location.origin).href.
  • mode is 'inline' | 'modal' (modal is the default). There is no mode="viewer" — read-only viewing is a reserved companyIdentifier (below).
  • Do not introduce AI, REST API, webhooks or storage unless the workflow needs them.
Route B — Programmatic app control

React: EmbedPDF + useEmbed() from @simplepdf/react-embed-pdf. Framework-free: createEmbed() from @simplepdf/embed. Use the typed actions rather than hand-writing postMessage unless the user specifically needs the wire protocol.

tsx
import { EmbedPDF, useEmbed } from '@simplepdf/react-embed-pdf';

export function ControlledEditor() {
  const { embedRef, actions } = useEmbed();

  return (
    <>
      <nav>
        <button onClick={() => actions.goTo({ page: 2 })}>Page 2</button>
        <button onClick={() => actions.selectTool({ tool: 'SIGNATURE' })}>Sign</button>
      </nav>

      <EmbedPDF
        ref={embedRef}
        mode="inline"
        companyIdentifier="yourcompany"
        document={{ url: 'https://cdn.simplepdf.com/simple-pdf/assets/forms/fw9.pdf' }}
        style={{ width: '100%', height: 800 }}
      />
    </>
  );
}

Typical operations: getFields(), setFieldValue({ fieldId, value }), getDocumentContent({ extractionMode }), getAnnotatedPage({ page }), goTo({ page }), focusField({ fieldId }), selectTool({ tool }), detectFields(), deleteFields({ fieldIds?, page? }), submit({ downloadCopy }). Verify the exact current method names and input shapes from the installed package/docs before coding.

Editor events arrive via the onEmbedEvent prop (React) or embed.events (core) — the outbound events are EDITOR_READY, DOCUMENT_LOADED, PAGE_FOCUSED and SUBMISSION_SENT (submit() itself resolves with data: null; the event carries the resulting ids). Wait for DOCUMENT_LOADED before operating on the document; until then actions other than loadDocument() fail with bad_request:editor_not_ready or bad_request:no_document_loaded (and getFields() may report an incomplete list) — handle or retry rather than racing mount.

Browser agents (WebMCP): webMCP: { enabled: true, exclude: ['submit'] } on createEmbed / <EmbedPDF> registers the editor's operations as tools on the host page (simplepdf_embed_*, the same records the editor registers on its own page; exclude takes SDK method names). Off by default; one WebMCP-enabled embed per page.

When relevant (AskUserQuestion, header Editor UI):

"Should SimplePDF's built-in controls remain visible, or should your app own most of the PDF controls?"

  1. Keep the built-in editor UI — less to build; the editor's own look and controls.
  2. Use our own controls around the editor — full ownership of the surrounding UX; more to build.

Do not imply arbitrary CSS access inside the iframe: the product can configure/hide editor UI and control the PDF through the typed SDK, while the surrounding application UI is fully theirs.

Pick the companyIdentifier (every route)

Map the workflow to the identifier:

  • Load, fill, download — free, no account. React: omit the prop (defaults to react-editor); framework-free/iframe/script: embed. Everything stays in the browser; submissions are not collected — users download their work.
  • Read-only viewing — free. react-viewer in React, viewer elsewhere: all editing features are disabled.
  • Load, fill, submit — collect submissions. Requires the user's own identifier: their <companyIdentifier>.simplepdf.com subdomain, shown in their dashboard.

When the workflow leaves it open, ask (AskUserQuestion, header Submissions): "Should submissions be collected on a SimplePDF account, or stay free download-only?"

When submissions are to be collected, ask the identifier question (plain free text): "What's your companyIdentifier — the subdomain of your <companyIdentifier>.simplepdf.com dashboard?"

Placeholder guard — non-negotiable. The free identifiers (embed, viewer, react-editor, react-viewer) are chosen by the workflow mapping above, never collected from the user. When submissions are to be collected, yourcompany and every free identifier are never a valid answer to the identifier question — a user giving one is echoing the docs, even if they confirm it. A user who answers with one, or with "I don't know", almost certainly has no SimplePDF account yet: have them sign up and pick a plan at https://simplepdf.com/pricing, then read the real identifier from their dashboard. To keep momentum meanwhile, offer to scaffold on the free identifier now and wire submissions once the real identifier exists.

Keep the identifier in the app's existing client-side config/env convention (e.g. NEXT_PUBLIC_… in Next.js) rather than hardcoded, so swapping in the real value is a one-line change and a placeholder can never ship in code.

Editor placement (every embedded route)

Never invent a page. Ask where the editor lives, building the options from the routes/pages found during inspection (AskUserQuestion, header Placement):

"Where should the PDF editor live?" — offer the concrete candidate pages you found (the 3 most likely, to stay within the option cap), plus "A new page/route". Fewer than two candidates → ask as plain text instead.

Then, only when the chosen page doesn't make it obvious: inline → which section/block hosts it; modal → which existing link/button opens it. One question per turn, as always.

Agentic control

Inspect dependencies and existing AI routes first. Only if the repository does not answer it (AskUserQuestion, header AI stack):

"Does this app already use an AI SDK?" — Vercel AI SDK / TanStack AI / another agent-LLM stack / no AI stack yet.

Then, only when the PDF-job answer has not already settled it (a user who picked only prefill has answered; so has one who picked live AI help, or both) (AskUserQuestion, header Agent mode):

"How should the agent interact with the PDF?"

  1. Prefill before it opens — use data we already have, then let the person review.
  2. Interact with the live PDF — the agent reads/fills/navigates while the person uses it.
  3. Both — prefill known answers first, live agent resolves what remains.
Live agentic control — Vercel AI SDK

useEmbedTools(embedRef) returns a string-keyed tools record ({ description, inputSchema, execute } per tool) bound to the live editor. In the current AI SDK, useChat has no tools option — dispatch client tool calls from onToolCall and report results with addToolOutput (production reference: https://raw.githubusercontent.com/SimplePDF/simplepdf-embed/main/copilot/src/components/chat/chat_pane.tsx):

tsx
import { useChat } from '@ai-sdk/react';
import { EmbedPDF, useEmbed } from '@simplepdf/react-embed-pdf';
import { useEmbedTools } from '@simplepdf/react-embed-pdf/ai-sdk';

export function AgenticEditor() {
  const { embedRef } = useEmbed();
  const tools = useEmbedTools(embedRef);

  const { addToolOutput } = useChat({
    onToolCall: async ({ toolCall }) => {
      const tool = tools[toolCall.toolName];
      if (tool === undefined) {
        return;
      }
      const output = await tool.execute(toolCall.input);
      addToolOutput({ tool: toolCall.toolName, toolCallId: toolCall.toolCallId, output });
    },
  });

  return (
    <EmbedPDF
      ref={embedRef}
      mode="inline"
      companyIdentifier="yourcompany"
      document={{ url: 'https://cdn.simplepdf.com/simple-pdf/assets/forms/fw9.pdf' }}
      style={{ width: '100%', height: 800 }}
    />
  );
}

Server-side model tool definitions use the React-free core (execute-less — the model sees the tools; the browser executes them):

ts
import { simplePDFToolDefinitions } from '@simplepdf/embed/ai-sdk';

streamText({ model, tools: simplePDFToolDefinitions() });

The split is intentional: the server/model knows the tool definitions; execution happens in the browser where the live editor exists. Never write server-side execute handlers that try to manipulate a browser iframe from the backend.

Vercel AI SDK changes frequently — inspect the installed ai / @ai-sdk/react version and current docs before writing useChat, streamText, tool-loop or message-transport code.

Live agentic control — TanStack AI

useEmbedTools(embedRef) returns client tools bound to the live editor; register them with the installed TanStack AI client API:

tsx
import { useChat } from '@tanstack/ai-react';
import type { ConnectionAdapter } from '@tanstack/ai-react';
import { EmbedPDF, useEmbed } from '@simplepdf/react-embed-pdf';
import { useEmbedTools } from '@simplepdf/react-embed-pdf/tanstack-ai';

export function AgenticEditor({ connection }: { connection: ConnectionAdapter }) {
  const { embedRef } = useEmbed();
  const tools = useEmbedTools(embedRef);

  useChat({ connection, tools });

  return (
    <EmbedPDF
      ref={embedRef}
      mode="inline"
      companyIdentifier="yourcompany"
      document={{ url: 'https://cdn.simplepdf.com/simple-pdf/assets/forms/fw9.pdf' }}
      style={{ width: '100%', height: 800 }}
    />
  );
}

connection is the app's TanStack AI transport — e.g. fetchServerSentEvents('/api/chat') from @tanstack/ai-react. React-free/server definitions: import { simplePDFToolDefinitions } from '@simplepdf/embed/tanstack-ai'. Verify the installed TanStack AI version before generating surrounding chat code.

Another agent framework

Do not force a rewrite to Vercel or TanStack AI. Explain the tradeoff and implement the smallest bridge:

  • the SDK-agnostic tool registry from @simplepdf/embed/tools (routeToolCall, isSimplePDFToolName) behind the project's existing tool abstraction
  • the machine-readable editor contract at https://simplepdf.com/embed/json
  • one of the supported adapters, if the user explicitly prefers it
AI privacy boundary

"PDF editing is browser-side" does not mean "no document information reaches an AI provider": editor operations execute in the browser and PDF bytes need not be uploaded to SimplePDF or the AI provider for tool execution, but document text/field data placed in a prompt is AI traffic under the application's chosen provider/privacy policy. Send only the context the user's request requires; never place secrets or unnecessary sensitive values in prompts, logs or webhook context. If the application handles regulated or highly sensitive data, surface this boundary explicitly before implementing broad content extraction into prompts.

Show full SKILL.md (1,295 more words)Show less

Prefill — when data exists before the user arrives

Choose Prefill when a backend/agent already knows answers (CRM, user profile, EHR, database, prior submission, email or intake conversation, workflow automation).

Prerequisites:

  • The document has its fields configured in the SimplePDF dashboard — an unconfigured document cannot be prefilled. Documents are created and configured in the dashboard, not via the API: get the document_id from GET /documents or the dashboard URL.
  • Prefill values live in customer-configured storage (S3-compatible, Azure Blob Storage, or SharePoint), never on SimplePDF — a configured BYOS storage that can serve the blob back to the recipient is required.
  • The Prefill API requires API access — BYOS alone does not imply it (plans can carry BYOS without the API). Check the account's plan against https://simplepdf.com/pricing, never memory.

Canonical flow (relative to the API base in "REST API" below):

  1. GET /documents/{document_id}/fields — each field has a stable id, a type, and (for constrained fields) allowed options
  2. map known values to stable field ids and allowed options
  3. POST /documents/{document_id}/prefills — returns the prefill id, an upload object (where and how to send the values), and an embed_url
  4. upload { "fields": [{ "id", "value" }] } per the upload object, straight to the customer storage
  5. open/share the returned embed_url
  6. the human reviews, corrects, signs and submits

Rules: keep sensitive values in the prefill blob, not webhook context; unknown field ids are ignored and read-only fields ignore prefill values; a field listing options only accepts one of them (checkboxes, dropdowns, radios); otherwise the value is a plain string (text fields) or a base64 data URL (signature and picture fields). When mapping from natural-language data, validate constrained values before writing the blob and never let the model invent a field id when the field schema is available. Prefills are deletable (DELETE /documents/{document_id}/prefills/{prefill_id}) — clean up prefills that were superseded or never opened.

Post-submit

When submissions are collected, ask (AskUserQuestion, header Post-submit):

"What should happen after the person submits the PDF?"

  1. Notify our backend and process it — configure a webhook.
  2. Just store/collect the submitted PDF — no custom processing yet.
  3. Use structured answers in another system — webhook/API + field data.
  4. Not sure — start webhook-friendly without unused backend code.
Webhooks

Use submission.created for downstream automation. The delivery carries metadata plus short-lived URLs (typically 15 minutes; BYOS providers may apply their own expiry) for the completed PDF and the structured submitted field data (field_data_url — may be null when field data is unavailable), which removes any need to parse the completed PDF to recover answers.

  • Authenticate deliveries with the custom headers SimplePDF sends on every webhook: set a random shared-secret header and verify it in the handler before trusting the payload or fetching any URL it contains. Do not invent a webhook-signature verification mechanism unless current SimplePDF documentation specifies one.
  • Treat context as correlation metadata only — no PII/PHI/secrets.
  • Respond quickly; make downstream processing idempotent by submission id; persist the identifiers you need; fetch short-lived resources promptly; handle retries safely.
  • An expired download URL can be refreshed through the REST API when the account has the required API access.

Storage

Only when submissions/prefills/persistence make it relevant, and after checking whether the app already has an established storage boundary (AskUserQuestion, header Storage):

"Where should submitted PDFs and prefill data live?"

  1. Our existing object storage — when the app already uses S3-compatible or Azure storage.
  2. SharePoint — Microsoft-centric workflows, where the account supports it.
  3. SimplePDF-managed storage — when BYOS is unnecessary.
  4. Not sure — decide from compliance and existing infrastructure.

If the workflow includes Prefill, do not offer option 3: prefill values live in customer storage the recipient's editor reads back, so a readable BYOS configuration is required — write-only storage cannot support that flow, and SimplePDF-managed storage only fits submission-only workflows.

Supported BYOS families: S3-compatible object storage, Azure Blob Storage, SharePoint — subject to current account entitlements. With BYOS, design around the browser/customer-storage signed-URL flow rather than proxying document bytes through the application's server without a specific need.

REST API

Only when the backend needs lifecycle control beyond browser editor actions/webhooks. Server-side resources: documents, field schemas, prefills, submissions.

text
https://{companyIdentifier}.simplepdf.com/api/v1

Authentication is a bearer API token. Never expose the SimplePDF API secret in browser code. Generate/validate backend clients from https://simplepdf.com/api/json rather than manually recreating schemas.

Plan gate — before any code

Do not start coding, and do not claim you have everything you need, until every triggered item below is resolved:

  • PDF job and route(s) chosen
  • companyIdentifier resolved to a real identifier or an explicitly chosen free one (placeholder guard passed)
  • embedded route → placement chosen (page, plus block/trigger when not obvious)
  • Route B → editor UI question answered
  • AI involved → stack and agent mode resolved
  • submissions collected → post-submit answered
  • submissions or prefill → storage answered

Any unchecked triggered item → ask the next missing question instead of planning. Then summarize the selected architecture in a short form before making changes:

text
Next.js + React
  ├─ EmbedPDF inline on /contracts (below the summary card)
  ├─ custom toolbar via useEmbed()
  ├─ Vercel AI SDK live tools
  ├─ Prefill API for CRM-known values
  ├─ human reviews/signs/submits
  ├─ S3 BYOS
  └─ submission.created webhook → existing intake API

The plan MUST name the data boundaries — what stays in the browser, what goes to the AI provider, what goes to customer storage, what webhook metadata reaches the backend. A plan without them is incomplete. Do not ask the user to reconfirm information they already supplied unless a destructive/security-sensitive change requires it.

Implement

Prefer the smallest integration that satisfies the chosen workflow.

bash
npm install @simplepdf/react-embed-pdf   # React
npm install @simplepdf/embed             # framework-free: createEmbed() + typed embed.actions/events/lifecycle

The agentic subpaths have optional peers: zod for both /ai-sdk and /tanstack-ai, plus @tanstack/ai for /tanstack-ai. Install only what the chosen path needs — a <EmbedPDF>-only app needs neither. The AI SDKs themselves are separate installs the snippets rely on (deliberately not peers of the SimplePDF packages): Vercel path ai, @ai-sdk/react, a provider package (e.g. @ai-sdk/anthropic), zod; TanStack path @tanstack/ai, @tanstack/ai-react, zod. Verify current versions against the installed packages before writing chat code.

Origin whitelisting

Whitelist the application's origins proactively: an account with an empty whitelist allows the embed on all origins, and adding the first origin is what activates the allow-list (blocking everything else). Have the user add their production and local-dev origins at https://{companyIdentifier}.simplepdf.com/account/embed → Security as part of the integration, not as an afterthought. On a blocked origin the editor renders a dedicated error screen naming the attempted origin (and actions fail with forbidden:origin_not_whitelisted); the Security section auto-detects that origin, ready to one-click approve.

Quality rules
  • Reuse the application's existing components, routes, auth, environment-variable conventions and styling.
  • Never leave yourcompany in written code: collect the real identifier first (placeholder guard), or use the free-tier identifiers for download-only/viewer workflows.
  • Keep server secrets server-only.
  • Prefer typed SDK methods to raw postMessage; prefer generated/OpenAPI types to hand-maintained REST types.
  • No storage/webhook/API infrastructure the chosen workflow doesn't need; no AI packages in a non-AI integration; never replace an existing AI framework solely because SimplePDF has adapters for another one.
  • Keep submission user-driven by default.

Verify

At minimum: the PDF loads in the chosen mode on the chosen page; programmatic actions wait for editor/document readiness; selected fields can be read/written; live AI tool calls execute in the browser when enabled, and the agent asks rather than invents missing user information; prefilled values map to real field ids and constrained values are valid; the human can review/correct before submitting; submission events are handled once/idempotently; webhook context contains no sensitive data; API keys never reach client bundles; the BYOS path matches the configured storage mode; errors are shown in the application's existing error UX.

In-product agent UX

Carry the same discipline into any end-user PDF assistant: ask for missing information one question at a time; never guess identity, medical, legal, financial or attestation answers; fill known fields when confidence is high and the user has authorized the data source; make uncertain mappings visible; navigate the user to fields requiring personal judgment or signature; summarize what was filled and what remains before submission; leave final submission to the person by default. A good form assistant should feel like it removed paperwork, not like it took control of the user's decisions.

© SimplePDF, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/build-with-simplepdf of SimplePDF/simplepdf-embed.

Open the folder on GitHubat commit 51f5427

Compare with similar skills

Build With Simplepdf next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Build With Simplepdf compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Build With Simplepdf this skillSimplePDF/simplepdf-embed407—~7kAutomated safety check: PassMIT
Typescript Rulessoftspark/ai-toolkit179—~2.7kAutomated safety check: NotesApache-2.0
React PDFtrailofbits/skills-curated513—~3.1kAutomated safety check: NotesCC-BY-SA-4.0
Javascript SDKaiskillstore/marketplace4301 repos~3.3kAutomated safety check: PassNone
Ultraciteagustinusnathaniel/nextarter-tailwind1252 repos~1.2kAutomated safety check: PassMIT
React Best Practicesshapeshift/web2061 repos~2kAutomated safety check: PassMIT

Similar skills

  • Typescript Rules

    softspark/ai-toolkit

    TypeScript/JavaScript coding rules: style, patterns, security, testing.

    179 GitHub stars~2.7k tokensUpdated today
    Testing & QAAuto-check: notes
  • React PDF

    trailofbits/skills-curated

    Official

    Generates PDF documents using the React-PDF library (@react-pdf/renderer) with TypeScript and JSX.

    513 GitHub stars~3.1k tokensUpdated 2 mo ago
    Documents & OfficeAuto-check: notes
  • Javascript SDK

    aiskillstore/marketplace

    JavaScript/TypeScript SDK for inference.sh - run AI apps, build agents, integrate with all models.

    430 GitHub starsUsed in 1 repo~3.3k tokens
    Backend & APIsAuto-check passed
  • Ultracite

    agustinusnathaniel/nextarter-tailwind

    Ultracite is a zero-config linting and formatting preset for JavaScript/TypeScript projects.

    125 GitHub starsUsed in 2 repos~1.2k tokens
    DevelopmentAuto-check passed
  • React Best Practices

    shapeshift/web

    Comprehensive React and Next.js performance optimization guide with 40+ rules for eliminating waterfalls, optimizing bundles, and improving rendering.

    206 GitHub starsUsed in 1 repo~2k tokens
    DevelopmentAuto-check passed
  • Playwright Core

    testdino-hq/playwright-skill

    Battle-tested Playwright patterns for writing and debugging reliable E2E, API, component, visual, accessibility, and security tests.

    390 GitHub starsUsed in 1 repo~1.4k tokens
    Testing & QAAuto-check passed

More from SimplePDF/simplepdf-embed

  • Edit PDF

    SimplePDF/simplepdf-embed

    Edit and fill PDF documents. An agent skill from SimplePDF/simplepdf-embed.

    407 GitHub stars~1.5k tokensUpdated 8 days ago
    Auto-check passed
  • Fork And Go

    SimplePDF/simplepdf-embed

    Guided walkthrough for forking and deploying your own SimplePDF Copilot: hosting choice, Pro-account confirmation, AI-provider wiring, demo customization, deploy, and the SimplePDF whitelist step.

    407 GitHub stars~7.9k tokensUpdated 8 days ago
    Auto-check: notes

Questions about Build With Simplepdf

What does Build With Simplepdf do?

Integrate SimplePDF into a web application for PDF viewing, editing, filling, signing, programmatic control, AI-agent interaction, human-in-the-loop form prefilling, submissions, webhooks, or…. Build With Simplepdf is an agent skill from SimplePDF/simplepdf-embed. Integrate SimplePDF into a web application for PDF viewing, editing, filling, signing, programmatic control, AI-agent interaction, human-in-the-loop form prefilling, submissions, webhooks, or customer-controlled storage.

When should I use Build With Simplepdf?

Build With Simplepdf fits situations like: A developer wants to add; improve PDF workflows in React; another web stack.

How do I install Build With Simplepdf in Claude Code?

Run `npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a claude-code`. Or copy the skill folder (skills/build-with-simplepdf in SimplePDF/simplepdf-embed) into .claude/skills/build-with-simplepdf in your project. Claude Code loads it when a task matches its description.

How do I install Build With Simplepdf in Codex?

Run `npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a codex`. Or copy the skill folder (skills/build-with-simplepdf in SimplePDF/simplepdf-embed) into .agents/skills/build-with-simplepdf in your project. Codex loads it when a task matches its description.

Can I use Build With Simplepdf in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/build-with-simplepdf, .gemini/skills/build-with-simplepdf, .github/skills/build-with-simplepdf and .opencode/skills/build-with-simplepdf in your project.

What does Build With Simplepdf need to run?

Going by SKILL.md and its folder, Build With Simplepdf needs the command-line tools its instructions call (npm).

Does Build With Simplepdf access the network?

SKILL.md names 3 domains. In commands or code: cdn.simplepdf.com; the agent is likely to contact it when it follows the instructions. As links in the text: simplepdf.com and npmjs.com. This is read from the text; nothing was executed.

Is Build With Simplepdf safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Build With Simplepdf use?

Build With Simplepdf is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Build With Simplepdf use?

About 7k tokens (SKILL.md is roughly 28k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Build With Simplepdf?

Skills that share tags, products or a category with Build With Simplepdf: Typescript Rules (softspark/ai-toolkit, 179 stars), React PDF (trailofbits/skills-curated, 513 stars), Javascript SDK (aiskillstore/marketplace, 430 stars) and Ultracite (agustinusnathaniel/nextarter-tailwind, 125 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Build With Simplepdf?

SimplePDF (a GitHub organization) maintains it in SimplePDF/simplepdf-embed, which has 407 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on September 30, 2026.

Source: SimplePDF/simplepdf-embed on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.