Stop demoing with test123. Generate realistic, domain-aware form data in one click.
Every team has this story. A PM is demoing to a client, and right there on the screen: "Cheeseburger" in the company name field, "asdf" for the email, and "John Doe" — the same John Doe — on every single record. QA tests with garbage. Designers screenshot forms full of "test123". There's no easy way to fill forms with realistic, context-appropriate data without writing seed scripts or maintaining test fixtures.
Before GhostFill:
First Name: test
Last Name: test
Email: test@test.com
Company: asdfasdf
Job Title: fjdksl
Phone: 1234567890
Address: 123 test street
After GhostFill:
First Name: Sarah
Last Name: Mitchell
Email: s.mitchell@northwind.com
Company: Northwind Traders
Job Title: Senior Account Executive
Phone: +1 (312) 555-0187
Address: 401 N Michigan Ave, Chicago, IL 60611
One click. Any form. No seed scripts.
Developers install it — npm install ghostfill -D, one import, done. But the whole team benefits:
- QA Engineers — fill forms with realistic edge cases instead of copy-pasting the same test data
- Product Managers — demo to clients with professional-looking data, not "test123"
- Designers — screenshot real-looking forms for decks and specs
- Solution Architects — show realistic D365, Salesforce, or ERP data during workshops
faker.js fills your database. Browser autofill fills your data. GhostFill fills the form you're looking at — visually, with data that fits the context.
| GhostFill | faker.js | Browser Autofill | |
|---|---|---|---|
| Who uses it | Anyone on the team | Developers only | Individual user |
| How it works | Visual in-page UI | Code library | Browser feature |
| Data quality | Domain-aware, contextual | Random but typed | Your personal data |
| Form detection | Reads labels, selects, custom dropdowns | N/A — you call it in code | Standard inputs only |
| Domain presets | D365, Healthcare, E-commerce, etc. | Generic schemas | N/A |
| Setup | One import, zero config | Write generation scripts | Already there |
npm install ghostfill -Dimport { init } from "ghostfill";
init();// app.tsx or layout.tsx
import { useEffect } from "react";
function GhostFill() {
useEffect(() => {
import("ghostfill").then((m) =>
m.init({
ai: {
endpoint: "/api/ghostfill",
provider: "openai",
},
})
);
}, []);
return null;
}
// In your app:
{process.env.NODE_ENV === "development" && <GhostFill />}import { fill } from "ghostfill";
await fill({ container: document.querySelector("form") });- A ghost icon appears on the page (starts minimized)
- Click it to enter selection mode — hover and click a form area
- Click the sparkles button to fill all detected fields
- By default, generates random sample data locally (no API needed)
- Optionally enable AI mode in settings for context-aware data generation through your backend
Save prompt templates for domain-specific data:
- D365 CE — Accounts, Contacts, Opportunities with CRM-realistic values
- Healthcare — Patient intake, insurance, clinical forms
- E-commerce — Products, orders, customer profiles
- Automotive — Vehicle specs, service records, dealer info
- Custom — Write your own prompt template for any domain
Presets are stored locally in the browser and sent as context to the AI provider.
GhostFill no longer accepts provider API keys in the browser. To use OpenAI, xAI, or Moonshot safely, expose a backend route and keep provider credentials server-side.
Install a server-side SDK in your app:
npm install openaiExample Next.js route:
// app/api/ghostfill/route.ts
import OpenAI from "openai";
import {
buildFillMessages,
parseFillDataPayload,
type GhostFillAIRequest,
type Provider,
} from "ghostfill/server";
const clients: Record<Provider, OpenAI> = {
openai: new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
}),
xai: new OpenAI({
apiKey: process.env.XAI_API_KEY,
baseURL: "https://api.x.ai/v1",
}),
moonshot: new OpenAI({
apiKey: process.env.MOONSHOT_API_KEY,
baseURL: "https://api.moonshot.ai/v1",
}),
};
const models: Record<Provider, string> = {
openai: process.env.GHOSTFILL_OPENAI_MODEL || "gpt-4o-mini",
xai: process.env.GHOSTFILL_XAI_MODEL || "grok-4-fast",
moonshot: process.env.GHOSTFILL_MOONSHOT_MODEL || "kimi-k2",
};
function isProvider(value: unknown): value is Provider {
return value === "openai" || value === "xai" || value === "moonshot";
}
export async function POST(req: Request) {
const body = (await req.json()) as Partial<GhostFillAIRequest>;
if (!isProvider(body.provider) || !Array.isArray(body.fields)) {
return Response.json({ error: "Invalid GhostFill request" }, { status: 400 });
}
const completion = await clients[body.provider].chat.completions.create({
model: models[body.provider],
messages: buildFillMessages({
provider: body.provider,
prompt: typeof body.prompt === "string" ? body.prompt : "",
systemPrompt:
typeof body.systemPrompt === "string" ? body.systemPrompt : undefined,
fields: body.fields,
}),
});
const content = completion.choices[0]?.message?.content || "";
return Response.json(parseFillDataPayload(content));
}This route supports all three providers, keeps secrets server-side, and only sends non-secret field metadata to the model. If you expose it outside local development, add your app's auth, rate limits, and request-size validation.
Click the gear icon to configure:
- Highlight Colour — pick the selection overlay color
- Use AI — toggle AI-powered fills when a secure backend route is configured
- Provider — cycle between OpenAI, xAI, and Moonshot
- Backend — shows the secure route or handler being used for AI fills
- Presets — save prompt templates for domain-specific data (e.g. D365, healthcare); keep them non-secret because they are stored locally
- Dark/Light theme — toggle with the sun/moon icon
- Zero config — works out of the box with random sample data
- Secure by default — AI mode uses a backend route instead of browser-held provider keys
- Shadow DOM — styles don't leak into your app
- Framework-aware — uses native value setters so React/Vue/Angular pick up changes
- Smart detection — labels from
<label>,aria-label, placeholder, preceding siblings - Custom dropdowns — handles Headless UI Listbox, Radix Select, and other
role="listbox"components - Draggable — drag the toolbar or minimized icon anywhere
- Presets — save and reuse prompt templates
- Dark/Light mode — matches your preference
- Keyboard shortcut —
Alt+Gto toggle
Initialize GhostFill and add the UI to the page.
init({
ai?: {
endpoint?: string, // Same-origin backend route (default: "/api/ghostfill")
requestFillData?: (request: GhostFillAIRequest) => Promise<FieldFillData[]>,
provider?: "openai" | "xai" | "moonshot"
},
shortcut?: string, // Keyboard shortcut (default: "Alt+G")
systemPrompt?: string // Custom system prompt to prepend
})Returns { destroy: () => void } to remove the UI.
Programmatic fill without the UI.
await fill({
container: HTMLElement, // The element containing form fields
prompt?: string, // Optional prompt for AI mode
ai?: {
endpoint?: string,
requestFillData?: (request: GhostFillAIRequest) => Promise<FieldFillData[]>,
provider?: "openai" | "xai" | "moonshot"
},
provider?: "openai" | "xai" | "moonshot",
systemPrompt?: string
})Returns { filled: number, errors: string[] }.
GhostFill includes an MCP (Model Context Protocol) server so AI agents like Claude Code and Cursor can generate form data directly.
{
"mcpServers": {
"ghostfill": {
"command": "npx",
"args": ["ghostfill-mcp"]
}
}
}Tools:
ghostfill_generate— Generate realistic fake data locally. No API key required.ghostfill_generate_ai— Generate context-aware data via OpenAI, xAI, or Moonshot. Requires an API key.
Requires @modelcontextprotocol/sdk and zod as peer dependencies:
npm install @modelcontextprotocol/sdk zodPolyForm Shield 1.0.0 — free to use, but you can't use it to build a competing product.