Let's Build: AI business card scanner with Transloadit
Business card scanners are a great example of productizing file workflows. You capture an image, clean it up, then extract contact details into structured fields. Transloadit’s primitives let you assemble that pipeline in a few steps.
What we’re building
- Accept PNG/JPEG or PDF cards
- Optimize images with 🤖 /image/optimize
- Extract contact fields with 🤖 /ai/chat
Schema first (zod)
import { z } from 'zod'
import { zodToJsonSchema } from 'zod-to-json-schema'
const businessCardSchema = z.object({
full_name: z.string().optional(),
title: z.string().optional(),
company: z.string().optional(),
email: z.string().optional(),
phones: z.array(z.string()).optional(),
address: z.string().optional(),
website: z.string().optional(),
socials: z.array(z.string()).optional(),
})
const toJsonSchema = (schema: z.ZodTypeAny): unknown =>
typeof (z as { toJSONSchema?: typeof zodToJsonSchema }).toJSONSchema === 'function'
? (z as { toJSONSchema: typeof zodToJsonSchema }).toJSONSchema(schema)
: zodToJsonSchema(schema)
const businessCardJsonSchema = toJsonSchema(businessCardSchema)
Pipeline overview
PDF cards ──▶ /ai/chat
Images ──▶ /image/optimize ──▶ /ai/chat
Assembly snippet
const assembly = await transloadit.createAssembly({
params: {
steps: {
pdf_verified: {
robot: '/file/filter',
use: ':original',
accepts: [['${file.mime}', '==', 'application/pdf']],
},
non_pdf: {
robot: '/file/filter',
use: ':original',
accepts: [['${file.mime}', '!=', 'application/pdf']],
},
card_image: {
robot: '/image/optimize',
use: 'non_pdf',
progressive: true,
},
extract_card: {
robot: '/ai/chat',
use: ['pdf_verified', 'card_image'],
model: 'anthropic/claude-4-sonnet-20250514',
format: 'json',
schema: JSON.stringify(businessCardJsonSchema),
messages: 'Extract business card fields. Omit keys if unknown.',
result: true,
},
},
},
files: {
card: filePath,
},
waitForCompletion: true,
})
Try the example app
The runnable version of this post lives at example_apps/business-card-scanner/run.ts.
node example_apps/business-card-scanner/run.ts
Suggested inputs for visuals
Use the bundled samples or swap in a real card scan:
_assets/demos/inputs/streetsign1.jpg_assets/demos/inputs/streetsign2.jpg_assets/demos/inputs/transloadit-padded.png
Next steps
- Add deduplication before inserting contacts into your CRM.
- Normalize phone numbers and addresses per locale.
- Add a manual review step for low-confidence extractions.
