# How to Add Smart Document Templates to Your App (Copy-Paste Prompts Included)

- Tool: App Features
- Last updated: July 2026

## TL;DR

Smart document templates need four pieces: a template gallery, a dynamic form that reads variable fields from the template definition, an AI Edge Function that polishes the prose and fills optional fields, and a PDF renderer (pdf-lib client-side or @react-pdf/renderer in Next.js). With Lovable or V0 you can ship a working contract or proposal generator in 6-12 hours for $0-5/mo at low volume, rising to $25-40/mo at 1,000 users when Supabase Pro and AI enhancement calls kick in.

## What Smart Document Templates Actually Are

Smart document templates let users fill in a structured form and receive a polished, complete document — a freelance contract, a project proposal, an invoice, a legal brief. The 'smart' part is AI: instead of producing a rigid mail-merge output, the template includes an AI polish step that rewrites placeholder prose into fluent copy tailored to the filled-in values. The document is then rendered to PDF for download, saving to cloud storage, or forwarding for signature. This is the highest-demand AI document automation pattern for SaaS products targeting service businesses. The key product decisions are: which formats to export (PDF, DOCX, or both), whether users can create their own templates or only use admin-defined ones, and whether the AI enhancement step is mandatory or optional per section.

## Anatomy of the Feature

Six components. The dynamic form generator and the PDF renderer are where most builds hit problems — they need explicit library names in your prompt.

- **Template gallery** (ui): React grid (web) or Flutter GridView (mobile) showing template cards with category badge, preview thumbnail, estimated completion time, and a 'Use template' CTA. Filters by category (Contracts, Proposals, Invoices, Reports). Queries Supabase templates table for is_public records.
- **Template definition store** (data): Supabase templates table: id, name, category, body text (with {{variable_name}} placeholders), variables jsonb schema (name, type, label, required, placeholder), is_public boolean. The variables jsonb drives the dynamic form renderer without any hardcoded field lists.
- **Dynamic form generator** (ui): Reads the variables jsonb from the selected template record and renders shadcn/ui form fields dynamically: TextInput for text, DatePicker for dates, Select for enums, Textarea for multi-line paragraphs. All fields managed via react-hook-form with zod schema generated from the variables definition. Flutter equivalent uses FlutterFlow's Dynamic Form widget.
- **AI content enhancement** (backend): Supabase Edge Function that accepts the template body with all {{variable}} tokens replaced by user-submitted values, plus an optional 'enhance this section' instruction per section. Calls Anthropic claude-haiku-4-5 to polish prose, improve sentence flow, and fill in AI-suggested optional fields. Returns the enhanced document text.
- **PDF renderer** (service): pdf-lib (MIT, browser-compatible, no server required) for web builds: generates PDF in the user's browser from the filled template. @react-pdf/renderer for Next.js: renders React components to PDF as a PDFDownloadLink. Avoid Puppeteer in Edge Functions — the headless Chrome binary exceeds the 50MB Edge Function size limit.
- **Document storage** (backend): Supabase Storage bucket named 'generated-documents'. Generated PDFs are uploaded via the Supabase Storage client and a signed URL (60-second expiry) is returned to the user for download. RLS policy: only the document owner can read or write their files.

## Data model

Three tables cover the full smart document templates data model. Run this in the Supabase SQL editor (Dashboard → SQL editor → New query):

```sql
create table public.templates (
  id uuid primary key default gen_random_uuid(),
  name text not null,
  category text not null,
  body text not null,
  variables jsonb not null default '[]'::jsonb,
  created_by uuid references auth.users(id),
  is_public boolean not null default true,
  created_at timestamptz not null default now()
);

alter table public.templates enable row level security;

create policy "Anyone can read public templates"
  on public.templates for select
  using (is_public = true);

create policy "Owners can manage own templates"
  on public.templates for all
  using (auth.uid() = created_by)
  with check (auth.uid() = created_by);

create index templates_category_idx
  on public.templates (category, is_public);

create table public.generated_documents (
  id uuid primary key default gen_random_uuid(),
  user_id uuid references auth.users(id) on delete cascade not null,
  template_id uuid references public.templates(id) not null,
  filled_variables jsonb not null default '{}'::jsonb,
  output_url text,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

alter table public.generated_documents enable row level security;

create policy "Users can manage own documents"
  on public.generated_documents for all
  using (auth.uid() = user_id)
  with check (auth.uid() = user_id);

create index generated_documents_user_idx
  on public.generated_documents (user_id, created_at desc);

create table public.document_drafts (
  id uuid primary key default gen_random_uuid(),
  user_id uuid references auth.users(id) on delete cascade not null,
  template_id uuid references public.templates(id) not null,
  filled_variables jsonb not null default '{}'::jsonb,
  updated_at timestamptz not null default now()
);

alter table public.document_drafts enable row level security;

create policy "Users can manage own drafts"
  on public.document_drafts for all
  using (auth.uid() = user_id)
  with check (auth.uid() = user_id);
```

document_drafts enables autosave without creating a full generated_documents record. The upsert pattern (insert on conflict update) on document_drafts lets the frontend save every 30 seconds without accumulating duplicate draft rows. output_url in generated_documents stores the Supabase Storage path, not a signed URL.

## Build paths

### Lovable — fit 4/10, 6-10 hours

Strong fit for web — generates the Supabase schema, Edge Function, and form UI in one shot. Supabase Storage is auto-configured. Use client-side pdf-lib rather than Puppeteer for PDF generation.

1. Create a new Lovable project with Lovable Cloud enabled so auth, database, and Storage are provisioned automatically
2. Add ANTHROPIC_API_KEY in Cloud tab → Secrets for the AI enhancement Edge Function
3. Paste the prompt below into Agent Mode; specify pdf-lib explicitly — do not let it choose Puppeteer
4. After the first build, open the template gallery and verify at least 3 starter templates were seeded into the templates table
5. Test draft autosave by partially filling a form and refreshing — the fields should repopulate from document_drafts
6. Publish the app and test PDF download on the live URL; signed URL generation for Supabase Storage only works reliably on the published domain

Starter prompt:

```
Build a smart document template feature. Include: 1) A Templates page showing a responsive grid of template cards (name, category badge, 'Use template' CTA) fetched from a Supabase 'templates' table. Seed 3 starter templates: 'Freelance Service Contract' (variables: client_name, service_description, start_date, end_date, payment_amount, payment_terms), 'Project Proposal' (variables: project_name, client_name, objectives, deliverables, timeline, budget), 'Invoice' (variables: invoice_number, client_name, client_email, line_items jsonb, due_date, total_amount). 2) A Template Editor page that: reads the selected template's variables jsonb and renders a shadcn/ui form with matching fields (text inputs, date pickers, textareas) using react-hook-form + zod validation; shows a live document preview panel that updates as the user types, replacing {{variable_name}} tokens with entered values; autosaves to a document_drafts table every 30 seconds using upsert on (user_id, template_id); has an 'AI Polish' toggle button per section that calls a Supabase Edge Function 'enhance-document' with the current section text and filled variables, replacing the section content with AI-polished prose. 3) The Edge Function 'enhance-document' that calls Anthropic claude-haiku-4-5 with system prompt: 'You are a professional document writer. Replace all {{variable}} tokens with the provided values. Polish the prose for clarity and professionalism. Return only the enhanced document text with NO remaining {{}} placeholders. Do not add content not implied by the template.' Validate the response contains no remaining {{ patterns before returning. 4) A Download PDF button using pdf-lib (NOT Puppeteer) to generate the PDF client-side from the filled document text, download it to the user's browser, and save the generated_documents record with a Supabase Storage upload of the PDF. Handle: form validation errors inline, AI enhancement loading state, PDF generation progress, Supabase Storage 403 errors.
```

Limitations:

- PDF generation with Puppeteer exceeds the Edge Function size limit — use client-side pdf-lib as specified in the prompt
- Live preview re-renders on every keystroke; debounce preview updates to 400ms after last keystroke to avoid performance issues on large templates
- FlutterFlow-style in-app document previews are not possible in Lovable (web only) — mobile users need a separate FlutterFlow build

### V0 — fit 4/10, 8-12 hours

@react-pdf/renderer integrates cleanly with Next.js App Router and produces high-quality PDF output with CSS-like styling. Requires manual Vercel Blob or Supabase Storage setup for saving outputs.

1. Prompt V0 with the spec below to generate the template gallery, editor, and PDF download components
2. In V0's Vars panel, add NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, and ANTHROPIC_API_KEY
3. Run the SQL schema from this page in the Supabase SQL editor and seed the 3 starter templates
4. Add @react-pdf/renderer to the project dependencies if V0 does not include it automatically
5. Publish to Vercel and test the full flow: select template → fill form → AI polish → download PDF

Starter prompt:

```
Build a smart document template feature in Next.js App Router. Create: 1) A TemplateGallery server component at /templates that fetches from Supabase 'templates' table (is_public = true), renders cards in a responsive grid (3-col desktop, 2-col tablet, 1-col mobile) with category badge and 'Use template' link to /templates/[id]. 2) A TemplateEditor client component at /templates/[id] that: fetches the template record and parses variables jsonb to render a react-hook-form with zod-validated fields (Input, DatePicker, Textarea, Select from shadcn/ui based on variable type); shows a split-pane layout — form left, live document preview right — updating the preview on each field change with 400ms debounce; autosaves to document_drafts every 30 seconds via Supabase upsert; has an 'AI Polish' button per section that calls POST /api/enhance-document with section text and filled variables. 3) A Route Handler at app/api/enhance-document/route.ts calling Anthropic claude-haiku-4-5; system prompt: 'Replace all {{variable}} tokens with provided values. Polish prose. Return only the enhanced text. Ensure zero remaining {{ patterns.'; validate output before returning. 4) A DownloadPDF client component using @react-pdf/renderer PDFDownloadLink that renders the filled template as a styled PDF document with company logo placeholder, section headings, and body paragraphs; after download, POSTs to /api/save-document to save the generated_documents Supabase record. Handle loading, error, and empty template states. Use TypeScript throughout.
```

Limitations:

- Supabase Storage must be configured manually — V0 does not provision storage buckets
- @react-pdf/renderer must be explicitly imported as a client-only module to avoid SSR errors ('window is not defined')
- Live preview in split-pane layout requires careful state management — shadcn/ui registry mismatches may require a follow-up fix prompt

### Flutterflow — fit 3/10, 10-16 hours

FlutterFlow builds the template gallery and form on mobile with Firebase backend. PDF export on mobile requires a custom Dart action or server-side API call. Best for apps where document creation is a secondary mobile feature.

1. Create a Firestore collection 'templates' with documents containing name, category, body, and variables (map array) fields; seed 3 starter templates manually
2. Build a template gallery page using FlutterFlow's ListView or GridView connected to the Firestore templates collection
3. Add a Template Editor page; use a Column of dynamic form fields built from the variables list — each variable map renders a matching FlutterFlow widget (TextField, DatePicker, DropDown)
4. Add a Custom Action 'enhanceSection' that calls your Firebase Cloud Function with the section text and filled variables and returns the polished text
5. For PDF export, add a Custom Action that calls a server-side PDF generation API (e.g. a Cloud Function using pdfkit) and triggers a file download via url_launcher

Limitations:

- PDF export on mobile requires a Cloud Function for PDF generation or a third-party API — there is no native Flutter PDF generation library comparable to pdf-lib in terms of simplicity
- In-app document preview is limited — rendering formatted document HTML requires a WebView widget which can be slow on lower-end Android devices
- FlutterFlow's Dynamic Form widget covers basic variable types; complex variable schemas (jsonb arrays, conditional fields) require custom Dart widget code

### Custom — fit 5/10, 2-3 weeks

Custom development is needed when document requirements exceed what pdf-lib or @react-pdf/renderer can produce: DOCX with track changes, e-signature integration, collaborative template editing, or a catalogue exceeding 200 templates.

1. Implement DOCX generation with tracked changes using docxtemplater + PizZip for Word-native output that legal teams can annotate
2. Integrate HelloSign or Docusign API to embed e-signature fields in generated documents and trigger signing workflows
3. Build multi-user collaborative template editing with Supabase Realtime for co-editing session state
4. Implement template versioning and diff-based preview so admins can see exactly what changed between template revisions

Limitations:

- Docxtemplater licencing costs $149/year for commercial use — budget this into project cost
- E-signature integrations (HelloSign, Docusign) add 3-5 days of work each and require webhook handling for signature completion events

## Gotchas

- **PDF downloads are blank or corrupted** — pdf-lib requires assets like fonts and images to be fetched during PDF generation. When these assets are served from Supabase Storage with signed URLs, the URLs are generated at page load time and expire before the user clicks Download. pdf-lib fetches a 403 error silently and produces a blank page. Fix: Generate signed URLs for all PDF assets (fonts, logos) immediately before calling pdf-lib's PDF generation function — not at page load. Use a 60-second expiry on signed URLs. Alternatively, host static assets (fonts, logo) in the public folder so they do not require signed URLs at all.
- **AI enhancement returns text with literal {{variable}} placeholders remaining** — When the Edge Function sends the template body to claude-haiku-4-5, the model sometimes returns partially-filled output where optional variables it does not have values for are left as {{placeholder}} strings literally in the output, which then appear in the downloaded PDF as broken template syntax. Fix: Add two safeguards: first, explicitly instruct the model in the system prompt to replace all {{}} tokens and return zero remaining placeholders; second, after receiving the LLM response, run a regex check (`/\{\{[^}]+\}\}/g`) and throw an error if any placeholders remain rather than returning corrupted output.
- **Template form loses data on browser back navigation** — AI tools generate template editor components where form state lives only in React state. When a user navigates away and returns (browser back button, link click), all filled data is lost. For document editors where filling in a contract takes 10-15 minutes, data loss destroys user trust immediately. Fix: Implement two layers of persistence: sessionStorage for instant recovery within the same browser session (write on every field change), and a Supabase document_drafts upsert every 30 seconds for cross-session recovery. Load defaultValues from sessionStorage first on mount; fall back to document_drafts if sessionStorage is empty.
- **FlutterFlow crashes on large document preview in WebView** — When displaying a rendered document preview using FlutterFlow's WebView widget, loading a multi-page document as HTML causes memory pressure on low-end Android devices, particularly those with 2GB RAM. The app hard-crashes with an out-of-memory error and no useful error message. Fix: Paginate the preview — show one section at a time rather than the full document. For PDF preview specifically, use the flutter_pdfview package rather than a HTML WebView; it uses native Android/iOS PDF rendering which is memory-efficient even on low-end devices.

## Best practices

- Always seed at least 3 working starter templates at launch — an empty template gallery causes immediate bounce and no amount of 'create your own template' prompting fixes it
- Validate that AI-enhanced output contains zero {{}} placeholders before returning to the user — corrupted PDFs with literal placeholder text destroy first impressions
- Generate signed URLs for Supabase Storage assets immediately before PDF generation, not at page load; 60-second expiry is sufficient and prevents blank-page downloads
- Autosave form state every 30 seconds to document_drafts using upsert — losing a half-completed contract is an unrecoverable UX failure
- Use pdf-lib for client-side PDF generation rather than Puppeteer; Puppeteer's headless Chrome binary exceeds Edge Function size limits and adds unnecessary server load
- Make the AI enhancement step optional per section with a visible toggle — mandatory AI rewrites that change legal wording erode user trust in contract templates
- Cache generated PDFs in Supabase Storage by content hash — if a user downloads the same unfilled template twice, serve the cached file rather than regenerating

## Frequently asked questions

### Can I generate a PDF from a template without a server?

Yes — pdf-lib runs entirely in the browser with no server required. The user's device generates the PDF from the filled template text using JavaScript. This avoids Edge Function size limits (no Puppeteer) and reduces server costs to zero for PDF generation. The tradeoff is less styling control compared to a server-rendered approach.

### What is the difference between a smart template and a regular form?

A regular form collects data and stores it. A smart template takes that same data, injects it into a pre-written document structure, polishes the prose with AI, and outputs a complete formatted document — a PDF the user can share or sign immediately. The form is the input; the document is the output.

### Can users create their own templates or only admins?

Both are possible. Admin-only templates (is_public = true in templates table, created by admin accounts) give you quality control over what users see. User-created templates require an additional template editor interface and a separate RLS policy allowing users to insert rows where created_by = auth.uid(). Start admin-only and add user creation as a premium feature.

### How do I add e-signature support to generated documents?

Build the document generation feature first, then integrate HelloSign or Docusign as a second phase. Both services provide APIs that accept a PDF, add signature fields, and send signing invitations via email. The integration requires a webhook handler in your API to receive signature-completed events and update the generated_documents record status. Custom development is recommended for e-signature integrations — the webhook handling complexity exceeds what AI tools generate reliably.

### Can I export to Word format instead of PDF?

Yes, with docxtemplater. It uses a Word file (.docx) as the template source — place {{variable}} tokens directly in the Word document using a Word editor — and fills them programmatically via Node.js. The output is a native .docx file clients can open and edit in Microsoft Word. docxtemplater requires a commercial licence ($149/year) and is best handled in a custom server-side build rather than an AI tool-generated app.

### How do I prevent AI from changing the legal wording in a contract template?

Mark sections as AI-off by wrapping them in a special delimiter (e.g. [LEGAL-FIXED]...content...[/LEGAL-FIXED]) and instruct the Edge Function's system prompt to pass through any text between those markers verbatim without modification. Only sections outside the markers receive AI polishing. This preserves boilerplate legal clauses exactly while allowing AI to personalise the custom sections.

### Does template generation work offline on mobile?

Partially. The form filling works offline if you implement local storage or SQLite draft persistence. The AI enhancement step requires internet — it calls a Cloud Function that calls the LLM. PDF generation on mobile requires a server-side API call unless you use a local Flutter PDF library (flutter_pdf). Design for graceful degradation: let users fill and save forms offline, then complete AI polish and PDF export when connectivity returns.

### How do I prevent users from downloading other users' documents?

RLS on the generated_documents table (policy: `USING (auth.uid() = user_id)`) prevents direct Supabase queries from returning other users' records. For Supabase Storage, the RLS policy on the bucket must also restrict access by user_id path prefix (e.g. `generated-documents/{user_id}/`). Never return a permanent public URL from Storage — always generate a short-lived signed URL per download request so even if the URL leaks, it expires quickly.

---

Source: https://www.rapidevelopers.com/app-features/smart-document-templates
© RapidDev — https://www.rapidevelopers.com/app-features/smart-document-templates
