
Research
/Security News
737 Chrome VPN Extensions Linked to Brand Impersonation and Browser Traffic Redirection
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.
@aoexl/sign
Advanced tools
@aoexl/signEmbed Aoexl's PDF signing experience directly inside your product.
npm install @aoexl/sign
Use pk_test_demo for local evaluation and move to your own pk_live_* key for
production. Production embeds are expected to use the managed Aoexl engine after
license validation.
Recommended production auth order:
licenseEndpoint="/api/aoexl-token" so the browser talks only to your backendgetEngineToken={async () => ...} for custom fetch logicengineToken="..." for a pre-minted short-lived tokenlicenseKey="pk_live_..." directly in the browserbase and engineUrl can be used for localhost development or for same-origin
app-hosted engine assets in production. Arbitrary cross-origin engine URLs stay
blocked by the SDK.
import { AoexlViewer } from "@aoexl/sign";
export default function EmbeddedSigner() {
return (
<AoexlViewer
licenseEndpoint="/api/aoexl-token"
pdfUrl="/Merchant.pdf"
mode="embedded-signing"
signerInfo={{ name: "Taylor Merchant", email: "taylor@example.com" }}
completionRedirectUrl="/done?session={{sessionId}}&completedAt={{completedAt}}"
onComplete={(result) => console.log(result)}
onError={(error) => console.error(error)}
/>
);
}
import AoexlSign from "@aoexl/sign";
const viewer = await AoexlSign.init({
licenseEndpoint: "/api/aoexl-token",
container: "#signer",
pdfUrl: "/Merchant.pdf",
mode: "embedded-signing",
});
// later
viewer.destroy();
All configuration for AoexlSign.init() or <AoexlViewer /> is passed via the config object:
| Prop | Type | Description |
|---|---|---|
licenseKey | string | Legacy browser-validation path (pk_test_* or pk_live_*). |
engineToken | string | Pre-minted short-lived engine token from your backend. |
getEngineToken | Function | Async function that returns a short-lived engine token. |
licenseEndpoint | string | Easiest production path. SDK POSTs { domain, timestamp } to your backend route and expects { engineToken, refreshAfterSeconds? }. |
pdfUrl | string | URL of the PDF to load. |
pdfData | Uint8Array | Blob | string | Raw bytes or data-URL (alternative to pdfUrl). |
mode | AoexlMode | 'prepare', 'sign', or 'view'. |
theme | Theme | Customise colors (primaryColor) and container layout. |
signers | Signer[] | Define signer roles and identities. |
fields | Field[] | Restore a previously saved field layout. |
completionRedirectUrl | string | Optional redirect after completion. Supports {{sessionId}}, {{fileName}}, {{completedAt}}, {{signerName}}, {{signerEmail}}. |
base | string | Asset base for localhost development or same-origin app-hosted engine assets. |
ui | UIConfig | Hide specific buttons or sidebars using hide: []. |
config | Config | Behavior flags such as first-load zoom, field order, auto-flattening, and flattened banner customization. |
onComplete | Function | Fired when signing is finished and document is ready. |
At least one auth prop is required: licenseKey, engineToken, getEngineToken, or licenseEndpoint.
For the full prop contract, responsive behavior notes, and embed recipes, see PROPS.md.
Use config.initialViewMode when an embedded PDF should open responsively instead of at a fixed zoom percentage.
<AoexlViewer
licenseEndpoint="/api/aoexl-token"
pdfUrl="/Merchant.pdf"
mode="sign"
initialScale={1}
config={{
initialViewMode: "fit-width",
flattenedBanner: {
text: "This document is locked for review.",
backgroundColor: "#0f172a",
textColor: "#ffffff",
actionLabel: "Edit again",
showUnlock: true
}
}}
/>
initialViewMode supports 'scale', 'fit-width', and 'fit-page'. Set flattenedBanner: false to hide the flattened-document banner entirely.
The SDK supports two common embedded experiences:
mode="view" for read-only disclosures or consent PDFsmode="sign" / mode="signing" for signer-facing flowsFor signing embeds, prefer:
<AoexlViewer
mode="sign"
ui={{ hide: ["toolbar"] }}
config={{
initialViewMode: "fit-width",
enableSignatureIndicator: true,
}}
/>
That combination is the supported way to:
960pxFor read-only embeds, keep mode="view" and use config.initialViewMode: "fit-width" so the PDF fills the container on first load.
The secure-but-easy production model is:
licenseEndpoint="/api/aoexl-token"pk_live_* keyExample backend route:
app.post('/api/aoexl-token', async (req, res) => {
const upstream = await fetch('https://aoexl.com/api/v1/license_verification', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
licenseKey: process.env.AOEXL_LICENSE_KEY,
domain: req.body.domain,
timestamp: req.body.timestamp,
}),
})
const data = await upstream.json()
if (!upstream.ok || !data?.engineToken) {
return res.status(400).json({ error: data?.error || 'Failed to mint engine token' })
}
res.json({
engineToken: data.engineToken,
refreshAfterSeconds: data.refreshAfterSeconds,
})
})
The SDK validates the license first and only then fetches the managed Aoexl engine for production use.
To avoid scroll stutter in short onboarding packets and consent forms, PDFs with 5 pages or fewer render every page up front at high canvas quality. Larger PDFs render on demand while showing an in-view preparing state instead of leaving a blank page.
When a user uploads or opens a different PDF inside the viewer, previously supplied fields are cleared for that new document. If you want fields on the replacement PDF, pass the saved field layout for that PDF when you initialize or reinitialize the viewer.
The init() method returns a viewer instance with the following methods:
destroy(): Unmount and cleanup.savePdf(options): Triggers a download/save of the current PDF state.getPdfBytes(options): Returns the signed PDF as a Uint8Array.flattenPdf(): Merges all annotations and signatures into the base PDF.setScale(value): Sets the zoom level (e.g. 1.5 for 150%).fitWidth() / fitPage(): Auto-scale to fill the viewport.FAQs
Embeddable PDF eSignature SDK by Aoexl
The npm package @aoexl/sign receives a total of 61 weekly downloads. As such, @aoexl/sign popularity was classified as not popular.
We found that @aoexl/sign demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
The campaign amassed more than 75,000 installs by targeting Russian-speaking users seeking access to blocked services.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.