How to Use unpkg.ai to Generate and Import AI-Powered ESM Modules
Updated
unpkg.ai generates an ES module on demand from a URL-encoded prompt, and you import it like any other ESM dependency. The pattern is https://unpkg.ai/esm/{url-encoded-prompt}.js, where the prompt is a function signature such as formatCurrency(amount:number,currency?:string):string. It is a good fit when you want a small, typed helper or plugin without writing it first; it is a poor fit when you need audited, stable code in production, because the generated module is produced by an LLM at request time and its correctness is not guaranteed.
What you need before starting
- A JavaScript environment that supports ESM
import— a browser module script, Node with"type": "module", or a bundler. - Network access to
unpkg.ai. - A clear function signature: name, parameter types, and return type. The signature is the prompt, so vague types produce vague modules.
The service page states no signup, no API keys, and no authentication are required. It does not publish pricing or rate-limit details, so treat availability and cost as unconfirmed until you check the site yourself.
Step 1: Write the prompt as a type signature
The prompt is a TypeScript-style signature. Everything after /esm/ and before .js is the prompt, URL-encoded.
| Part | Example | Notes |
|---|---|---|
| Function name | formatCurrency |
Becomes the named export |
| Parameters | (amount:number,currency?:string) |
? marks optional |
| Return type | :string |
Object returns use {tip:number,total:number} |
| Encoding | ? → %3F, : stays, spaces avoided |
Encode reserved characters |
From the site's examples:
formatCurrency(amount:number,currency?:string):string
calculateTip(amount:number,percentage:number,people?:number):{tip:number,total:number,perPerson:number}
generatePassword(options?:{length?:number,symbols?:boolean,numbers?:boolean,uppercase?:boolean,lowercase?:boolean}):{password:string,strength:number,feedback:string[]}
Step 2: Build the URL and import it
Take the signature, URL-encode it, and append it to the base path. Then import the named export.
import { formatCurrency } from 'https://unpkg.ai/esm/formatCurrency(amount:number,currency%3F:string):string.js';
console.log(formatCurrency(1234.56, 'EUR')); // "€1,234.56"
Expected result: the module resolves, exports formatCurrency, and the call returns a formatted string. If the import fails, check that ? is encoded as %3F and that no unencoded spaces or # characters remain in the path.
Step 3: Add optional parameters
The page lists two optional query parameters:
model— choose the LLM, e.g.gpt-4orclaude-3.seed— a number for deterministic output.
Use seed when you want the same prompt to return the same module across requests, which matters if you cache or snapshot generated code. Use model when output quality or style differs between models. The page does not document how these combine with the path, so verify the exact URL form on the site before relying on it.
Step 4: Walk through a fuller example
The password generator shows a structured return type:
import { generatePassword } from 'https://unpkg.ai/esm/generatePassword(options%3F:{length%3F:number,symbols%3F:boolean,numbers%3F:boolean,uppercase%3F:boolean,lowercase%3F:boolean}):{password:string,strength:number,feedback:string[]}.js';
const result = generatePassword({ length: 16, symbols: true });
// { password: 'K#9m$L2pQ!7vX8nR', strength: 95, feedback: ['Very strong'] }
The site also shows a Minesweeper module returning {start, reset, getStats}, which illustrates that generated modules can export stateful APIs, not just pure functions.
Where this breaks down
- Malformed prompts. A missing return type or unbalanced braces produces a module that may not parse. Keep signatures simple and test the URL before wiring it into code.
- Unreliable generated code. The module is LLM output. It can be subtly wrong — off-by-one logic, wrong currency rounding, weak randomness. Review the generated source before trusting it.
- No version pinning. There is no documented version or hash in the URL, so the same prompt can yield different code later. Use
seedand cache the result if stability matters. - Runtime dependency. Every import is a network fetch to a third party; offline builds and strict CSP setups will fail.
For dynamic plugin systems and top-down prototyping, the trade-off is usually worth it. For anything handling money, secrets, or security boundaries, generate the module, read it, and vendor it into your repo.