HTML + Tailwind Code Studio

    Write HTML with TailwindCSS, bind dynamic data with Jinja2 directives, and generate pixel-perfect PDFs. Full control, zero config.

    How it works

    01

    Write HTML + Tailwind

    Design your document layout exactly as you want it. Use any Tailwind utility class.

    02

    Bind Data with Jinja2

    Use input(), mini(), or raw variables to declare where dynamic content goes.

    03

    Generate PDF

    Hit Build — Docmiral renders your template with user data and exports a pixel-perfect PDF.

    Template Capabilities

    Everything you can use in your template

    Input Fields

    input() directive

    Declare typed fields directly in your HTML — text, number, price, textarea, rich editor, or smart editor with variable substitution.

    {{ input(name="title", title="Job Title", type="string") }}
    {{ input(name="bio", title="Bio", type="smarteditor") }}

    Image Fields

    input() with type image

    Add image upload fields with custom dimensions. Users pick from their gallery or upload directly — renders as an img tag.

    {{ input(name="logo", title="Logo",
      type="image",
      settings={"width": "80px"}) }}

    MiniApp Data

    mini() directive

    Bind to structured data schemas — resumes, invoices, cover letters — with single values or loopable arrays.

    {{ mini(name="resumes/personal", key="name") }}
    
    {% for job in mini(name="resumes/experiences",
        items=["title", "company", "key_points"]) %}
      <h3>{{ job.title }} @ {{ job.company }}</h3>
    {% endfor %}

    Generic Variables

    Raw Jinja2

    Use any Jinja2 variable or loop directly. Define a schema for custom fields and reference them anywhere in the template.

    <h1>{{ client_name }}</h1>
    {% for item in order_items %}
      <p>{{ item.title }} — {{ item.price | priceformat }}</p>
    {% endfor %}

    Built-in Filters

    Transforms & formatting

    Format values on the fly with built-in Jinja2 filters — uppercase, lowercase, price formatting, and unit stripping.

    {{ name | uppercase }}
    {{ price | priceformat }}      {# → 1,234.50 #}
    {{ "180 cm" | strip_units | int }}  {# → 180 #}

    Loop Helpers

    loop.index, loop.first...

    Full Jinja2 loop variables available — index, first, last, length — great for alternating styles or conditional separators.

    {% for skill in skills %}
      <span class="{% if loop.first %}ml-0{% else %}ml-2{% endif %}">
        {{ loop.index }}. {{ skill }}
      </span>
    {% endfor %}

    Page Types

    Choose your page structure

    Fixed Page.page

    Defined A4 dimensions. Best for resumes, cards, certificates.

    <div class="page"><div class="content">
      <!-- your content -->
    </div></div>
    Flexible Page.flexpage

    Auto-height based on content. Best for contracts, letters.

    <div class="flexpage"><div class="content">
      <!-- your content -->
    </div></div>

    Mix both types in a single template — use fixed pages for structured layouts and flexible pages for variable-length sections.

    Document Settings

    Configure without touching the HTML

    Page Size

    A3, A4, A5, Letter, Legal, or custom mm dimensions

    Orientation

    Portrait or Landscape with one click

    Margins & Padding

    0–30mm controls per side

    Page Numbering

    6 positions, custom format, font, and color

    Header & Footer

    Optional custom HTML header and footer areas

    Background & Textures

    Solid colors, paper arts, and texture overlays

    Tars AI

    Stuck? Just describe what you want.

    Tars AI is embedded in the studio. Chat to generate template sections, restyle elements, add new fields, or restructure layouts — all from natural language. Upload a reference PDF and Tars will replicate it.

    Add a two-column layoutMake the header blue with white textAdd a skills section with tagsUpload PDF to cloneAdd experience loop with dates

    Ready to build your first template?

    Open the studio, write some HTML, add a directive, and watch it render.