Typescript Rules
softspark/ai-toolkit
TypeScript/JavaScript coding rules: style, patterns, security, testing.
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…
$ npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install SimplePDF/simplepdf-embed build-with-simplepdf --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ 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-srcUse ~/.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/
Install the "build-with-simplepdf" agent skill from https://github.com/SimplePDF/simplepdf-embed/tree/main/skills/build-with-simplepdf into .claude/skills/build-with-simplepdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "build-with-simplepdf", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/SimplePDF/simplepdf-embed/tree/main/skills/build-with-simplepdfType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install SimplePDF/simplepdf-embed build-with-simplepdf --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/SimplePDF/simplepdf-embed.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/build-with-simplepdf .agents/skills/build-with-simplepdf && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "build-with-simplepdf" agent skill from https://github.com/SimplePDF/simplepdf-embed/tree/main/skills/build-with-simplepdf into .agents/skills/build-with-simplepdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "build-with-simplepdf", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install SimplePDF/simplepdf-embed build-with-simplepdf --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/SimplePDF/simplepdf-embed.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/build-with-simplepdf .cursor/skills/build-with-simplepdf && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "build-with-simplepdf" agent skill from https://github.com/SimplePDF/simplepdf-embed/tree/main/skills/build-with-simplepdf into .cursor/skills/build-with-simplepdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "build-with-simplepdf", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/SimplePDF/simplepdf-embed.git --path skills/build-with-simplepdf--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install SimplePDF/simplepdf-embed build-with-simplepdf --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/SimplePDF/simplepdf-embed.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/build-with-simplepdf .gemini/skills/build-with-simplepdf && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "build-with-simplepdf" agent skill from https://github.com/SimplePDF/simplepdf-embed/tree/main/skills/build-with-simplepdf into .gemini/skills/build-with-simplepdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "build-with-simplepdf", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install SimplePDF/simplepdf-embed build-with-simplepdfInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/SimplePDF/simplepdf-embed.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/build-with-simplepdf .github/skills/build-with-simplepdf && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "build-with-simplepdf" agent skill from https://github.com/SimplePDF/simplepdf-embed/tree/main/skills/build-with-simplepdf into .github/skills/build-with-simplepdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "build-with-simplepdf", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add SimplePDF/simplepdf-embed --skill build-with-simplepdf -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install SimplePDF/simplepdf-embed build-with-simplepdf --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/SimplePDF/simplepdf-embed.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/build-with-simplepdf .opencode/skills/build-with-simplepdf && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "build-with-simplepdf" agent skill from https://github.com/SimplePDF/simplepdf-embed/tree/main/skills/build-with-simplepdf into .opencode/skills/build-with-simplepdf/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "build-with-simplepdf", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
build-with-simplepdfIntegrate 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. 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.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 51f5427. It shows what the files ask for, not the result of running them.
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.
Shell commands in SKILL.md call:
npmFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
cdn.simplepdf.comAlso links to:
simplepdf.comnpmjs.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
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.
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.
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.
The full file from SimplePDF/simplepdf-embed at commit 51f5427, republished under its MIT licence (© SimplePDF). 3,187 words, ~7,001 tokens.
.claude/skills/build-with-simplepdf/SKILL.md (or your agent's skills folder).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):
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.
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.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.
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.
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.
When not already clear (AskUserQuestion with multiSelect: true, header PDF job):
"What should people be able to do with the PDF?"
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.
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).
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).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.
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?"
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.
companyIdentifier (every route)Map the workflow to the identifier:
react-editor); framework-free/iframe/script: embed. Everything stays in the browser; submissions are not collected — users download their work.react-viewer in React, viewer elsewhere: all editing features are disabled.<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.
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.
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?"
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):
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):
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.
useEmbedTools(embedRef) returns client tools bound to the live editor; register them with the installed TanStack AI client API:
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.
Do not force a rewrite to Vercel or TanStack AI. Explain the tradeoff and implement the smallest bridge:
@simplepdf/embed/tools (routeToolCall, isSimplePDFToolName) behind the project's existing tool abstraction"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.
Choose Prefill when a backend/agent already knows answers (CRM, user profile, EHR, database, prior submission, email or intake conversation, workflow automation).
Prerequisites:
document_id from GET /documents or the dashboard URL.Canonical flow (relative to the API base in "REST API" below):
GET /documents/{document_id}/fields — each field has a stable id, a type, and (for constrained fields) allowed optionsPOST /documents/{document_id}/prefills — returns the prefill id, an upload object (where and how to send the values), and an embed_url{ "fields": [{ "id", "value" }] } per the upload object, straight to the customer storageembed_urlRules: 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.
When submissions are collected, ask (AskUserQuestion, header Post-submit):
"What should happen after the person submits the PDF?"
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.
context as correlation metadata only — no PII/PHI/secrets.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?"
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.
Only when the backend needs lifecycle control beyond browser editor actions/webhooks. Server-side resources: documents, field schemas, prefills, submissions.
https://{companyIdentifier}.simplepdf.com/api/v1Authentication 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.
Do not start coding, and do not claim you have everything you need, until every triggered item below is resolved:
companyIdentifier resolved to a real identifier or an explicitly chosen free one (placeholder guard passed)Any unchecked triggered item → ask the next missing question instead of planning. Then summarize the selected architecture in a short form before making changes:
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 APIThe 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.
Prefer the smallest integration that satisfies the chosen workflow.
npm install @simplepdf/react-embed-pdf # React
npm install @simplepdf/embed # framework-free: createEmbed() + typed embed.actions/events/lifecycleThe 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.
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.
yourcompany in written code: collect the real identifier first (placeholder guard), or use the free-tier identifiers for download-only/viewer workflows.postMessage; prefer generated/OpenAPI types to hand-maintained REST types.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.
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
Just SKILL.md in skills/build-with-simplepdf of SimplePDF/simplepdf-embed.
Open the folder on GitHubat commit 51f5427
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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Build With Simplepdf this skillSimplePDF/simplepdf-embed | 407 | — | ~7k | Automated safety check: Pass | MIT | |
| Typescript Rulessoftspark/ai-toolkit | 179 | — | ~2.7k | Automated safety check: Notes | Apache-2.0 | |
| React PDFtrailofbits/skills-curated | 513 | — | ~3.1k | Automated safety check: Notes | CC-BY-SA-4.0 | |
| Javascript SDKaiskillstore/marketplace | 430 | 1 repos | ~3.3k | Automated safety check: Pass | None | |
| Ultraciteagustinusnathaniel/nextarter-tailwind | 125 | 2 repos | ~1.2k | Automated safety check: Pass | MIT | |
| React Best Practicesshapeshift/web | 206 | 1 repos | ~2k | Automated safety check: Pass | MIT |
softspark/ai-toolkit
TypeScript/JavaScript coding rules: style, patterns, security, testing.
trailofbits/skills-curated
Generates PDF documents using the React-PDF library (@react-pdf/renderer) with TypeScript and JSX.
aiskillstore/marketplace
JavaScript/TypeScript SDK for inference.sh - run AI apps, build agents, integrate with all models.
agustinusnathaniel/nextarter-tailwind
Ultracite is a zero-config linting and formatting preset for JavaScript/TypeScript projects.
shapeshift/web
Comprehensive React and Next.js performance optimization guide with 40+ rules for eliminating waterfalls, optimizing bundles, and improving rendering.
testdino-hq/playwright-skill
Battle-tested Playwright patterns for writing and debugging reliable E2E, API, component, visual, accessibility, and security tests.
SimplePDF/simplepdf-embed
Edit and fill PDF documents. An agent skill from SimplePDF/simplepdf-embed.
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.
Works with
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.
Build With Simplepdf fits situations like: A developer wants to add; improve PDF workflows in React; another web stack.
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.
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.
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.
Going by SKILL.md and its folder, Build With Simplepdf needs the command-line tools its instructions call (npm).
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.
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.
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.
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.
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.
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.