Skip to content

Architecture

Runtime boundaries

  • Laravel 13: auth, workspace membership, template metadata, generation records, API, billing, storage, and queues.
  • React 19 + Inertia 3 + shadcn/ui: authenticated workspace and document forms. Page navigation uses standard server requests where possible; JavaScript is reserved for forms, drag-and-drop, menus, and live queue completion signals.
  • Node.js worker: parses placeholders, extracts visible text, rewrites exact smart-field candidates across Word text runs, and renders DOCX with docxtemplater; invokes LibreOffice for PDF and LibreOffice plus Poppler for first-page PNG previews.
  • Private storage: DOCUMENTS_DISK selects local development storage or production S3.
  • Redis: production cache, sessions, and queues.
  • Stripe: Cashier uses the workspace (Team internally) as its customer.
  • OpenAI: optional Responses API integration returns strict structured candidates for smart template parsing; request storage is disabled.
  • Admin: an is_admin gate protects aggregate operational metrics and database-backed operational failure notifications.

Document flow

  1. A member uploads a DOCX to the current workspace.
  2. Laravel checks quota, writes to the private disk, and creates a template record.
  3. ParseDocumentTemplate calls Node and stores unique placeholders such as [first name] before dispatching GenerateTemplatePreview to write a private first-page PNG. Preview errors are non-fatal and tracked separately from parsing errors.
  4. Optional smart parsing extracts text, receives schema-constrained candidates, and asks Node to replace only exact source spans with stable placeholders.
  5. Field definitions select a resolver (provided input or an internal variable) before rendering.
  6. A submitted form or XLSX mapping creates standard generation records. Single fills dispatch GenerateDocument; bulk fills run through a tracked GenerationBatch with a plan row cap and optional ZIP archive.
  7. Node renders DOCX, optionally converts to PDF, and Laravel stores the result privately.
  8. Grid cards, list rows, and the template detail page request previews through an authorized workspace route; storage paths are never sent to the client.
  9. While work is processing, the browser holds one authenticated server-sent event connection. Laravel signals completion and the browser performs a full page refresh; there is no client polling loop.
  10. An authorized member downloads through Laravel, or a recipient uses a temporary signed email-share URL. Object paths are never public.

Internal naming

Laravel's starter kit calls collaborative workspaces “teams”. Stable internal names (Team, team_members) remain while the product and public documentation use “workspace”.

Extension seams

WorkspaceStorage owns quotas and disk selection. DocumentWorker owns the PHP/Node contract. FieldValueResolverRegistry is the plugin seam for input, internal variables, and future intelligence providers. PlanCapabilities centralizes smart-parse and bulk-run entitlements. Queue jobs isolate heavy work. Enum-backed formats/statuses allow expansion. Cashier is workspace-scoped for two later paid plans.