Pogodoc
Templates

JavaScript Framework Templates

Create dynamic and complex document templates using React, Vue, Angular, Svelte, or any JavaScript framework

JavaScript Framework Templates

Pogodoc allows you to leverage the power and flexibility of React, Vue, Angular, Svelte, or any JavaScript framework to create dynamic and complex document templates. This guide will walk you through the process of setting up a JavaScript framework project to be used as a Pogodoc template.

Any JavaScript framework that builds to static HTML works! This guide uses React as an example, but the same principles apply to Vue, Angular, Svelte, and others.

Overview

Unlike simple template strings (like EJS or HTML), JavaScript framework templates require:

  1. A build process to compile your components
  2. Packaging the build output as a ZIP file
  3. Uploading the ZIP to Pogodoc

Project Setup

While you can use any React setup (like Create React App, Next.js in static export mode, or a custom webpack configuration), we recommend using Vite for a fast and straightforward setup.

Create a new React project with TypeScript using Vite:

npm create vite@latest my-react-template -- --template react-ts
cd my-react-template
npm install
npm create vite@latest my-vue-template -- --template vue-ts
cd my-vue-template
npm install
npm create vite@latest my-svelte-template -- --template svelte-ts
cd my-svelte-template
npm install

This creates a new directory with a basic project structure.

Accessing Template Data

When Pogodoc renders your template, it injects the JSON data you provide into the window object under the __POGODOC_DATA__ property. To access this data in a type-safe way, create a helper file.

Create src/config.ts:

src/config.ts
declare global {
  interface Window {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    __POGODOC_DATA__: any;
  }
}

export const pogodocData = window.__POGODOC_DATA__;

This declares a global __POGODOC_DATA__ property on the window object and exports the data for easy use throughout your application.

You can also create a proper TypeScript interface for your data instead of using any for better type safety.

Create Your Template

Now you can import and use the data in any of your components.

src/App.tsx
import { pogodocData } from './config';

function App() {
  return (
    <div style={{ fontFamily: 'Arial', padding: '40px' }}>
      <h1>Invoice for {pogodocData.customer.name}</h1>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead>
          <tr>
            <th style={{ textAlign: 'left', borderBottom: '2px solid #333' }}>Item</th>
            <th style={{ textAlign: 'right', borderBottom: '2px solid #333' }}>Price</th>
          </tr>
        </thead>
        <tbody>
          {pogodocData.items.map((item: any, i: number) => (
            <tr key={i}>
              <td style={{ padding: '8px 0' }}>{item.name}</td>
              <td style={{ textAlign: 'right' }}>\${item.price.toFixed(2)}</td>
            </tr>
          ))}
        </tbody>
      </table>
      <h2 style={{ textAlign: 'right', marginTop: '20px' }}>
        Total: \${pogodocData.total.toFixed(2)}
      </h2>
    </div>
  );
}

export default App;
src/App.vue
<script setup lang="ts">
import { pogodocData } from './config';
</script>

<template>
  <div style="font-family: Arial; padding: 40px">
    <h1>Invoice for {{ pogodocData.customer.name }}</h1>
    <table style="width: 100%; border-collapse: collapse">
      <thead>
        <tr>
          <th style="text-align: left; border-bottom: 2px solid #333">Item</th>
          <th style="text-align: right; border-bottom: 2px solid #333">Price</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(item, i) in pogodocData.items" :key="i">
          <td style="padding: 8px 0">{{ item.name }}</td>
          <td style="text-align: right">\${{ item.price.toFixed(2) }}</td>
        </tr>
      </tbody>
    </table>
    <h2 style="text-align: right; margin-top: 20px">
      Total: \${{ pogodocData.total.toFixed(2) }}
    </h2>
  </div>
</template>
src/App.svelte
<script lang="ts">
  import { pogodocData } from './config';
</script>

<div style="font-family: Arial; padding: 40px">
  <h1>Invoice for {pogodocData.customer.name}</h1>
  <table style="width: 100%; border-collapse: collapse">
    <thead>
      <tr>
        <th style="text-align: left; border-bottom: 2px solid #333">Item</th>
        <th style="text-align: right; border-bottom: 2px solid #333">Price</th>
      </tr>
    </thead>
    <tbody>
      {#each pogodocData.items as item, i}
        <tr>
          <td style="padding: 8px 0">{item.name}</td>
          <td style="text-align: right">\${item.price.toFixed(2)}</td>
        </tr>
      {/each}
    </tbody>
  </table>
  <h2 style="text-align: right; margin-top: 20px">
    Total: \${pogodocData.total.toFixed(2)}
  </h2>
</div>

Build Your Template

After creating your template, build it to generate the static HTML, CSS, and JavaScript files.

Run the build command:

npm run build

This creates a dist directory containing your bundled application.

Package as ZIP

Zip the contents of the dist folder (not the dist folder itself).

cd dist
zip -r ../my-template.zip .
cd ..

Important: Only the contents of the dist folder should be zipped, not the dist folder itself. The root of your ZIP should contain index.html, not a dist/ folder.

Upload to Pogodoc

Save your template to your Pogodoc account.

Follow "Creating Templates". Or, save templates through the SDKs or our API.

Generate Documents

Now you can generate documents using the templateId of your saved template.

Best Practices

1. Inline Styles

For documents (especially PDFs), use inline styles instead of CSS classes:

// ✅ Good - inline styles
<div style={{ color: '#333', fontSize: '14px' }}>Content</div>

// ❌ Bad - CSS classes might not work
<div className="text-gray-700 text-sm">Content</div>

2. Absolute Units

Use absolute units (px, pt, cm) instead of relative units (rem, em, %) for consistent sizing:

// ✅ Good - absolute units
<div style={{ padding: '20px', fontSize: '14px' }}>Content</div>

// ❌ Bad - relative units
<div style={{ padding: '2rem', fontSize: '1em' }}>Content</div>

3. Avoid External Resources

Include all assets (images, fonts) in your ZIP or use data URLs:

// ✅ Good - base64 image
<img src="data:image/png;base64,iVBORw0KGgo..." alt="Logo" />

// ❌ Bad - external URL might not load
<img src="https://example.com/logo.png" alt="Logo" />

4. Test Locally

Before uploading, test your template locally:

npm run build
npm run develop

Make sure it renders correctly in the browser before uploading to Pogodoc.

Pro Tip: To preview how Pogodoc will render a PDF document you can use Ctrl/Cmd + P in your browser and preview how it would look like.

Framework-Specific Tips

React

  • Use create-react-app or vite for setup
  • Avoid hooks that depend on browser APIs (like useEffect with timers)
  • Use React 18+ for best compatibility

Vue

  • Use create-vue or vite for setup
  • Avoid lifecycle hooks that depend on browser timing
  • Use Vue 3+ for best compatibility

Angular

  • Use Angular CLI for setup
  • Configure for production build with ng build --prod
  • Disable animations that might not work in PDF rendering

Svelte

  • Use vite with Svelte template
  • Avoid stores that depend on browser APIs
  • Use Svelte 3+ for best compatibility

Troubleshooting

Template Not Rendering

  • Check that index.html is at the root of your ZIP
  • Verify window.__POGODOC_DATA__ is being accessed correctly
  • Check browser console for errors in preview

Styling Issues

  • Ensure all styles are inline or in <style> tags
  • Use absolute units (px, pt) instead of relative (rem, em)
  • Test with different page sizes (A4, Letter, etc.)

Build Size Too Large

  • Minimize dependencies
  • Use code splitting
  • Remove unused code with tree shaking
  • Compress images before including

Examples

Next Steps