One template. Every scenario.

Catch wrong totals, invitation roles and reset expiry text across your rendered variations. Start with a business workflow below, edit its requirements, and compare the repaired version under the same rules.

Start with a React Email or MJML template

A complete synthetic signing email with document details, expiry text, help links and three English variations: standard, long-name and reminder. These files were produced by the real open-source renderers; they are example fixtures.

The ZIP includes original template source, synthetic fixtures, a pinned npm lockfile, setup instructions and passing/broken rendered samples. npm ci installs both renderers. Extract it into a new folder and review it before running.

Template source + matching GitHub workflow in one ZIP

Start a new renderer with synthetic fixtures, pinned dependencies, a local setup check and matching script/folder paths. Render and preview locally for free. Saved CI checks require Pro or Enterprise and a configured project.

Extract into a new folder and read README.md first. Review and merge files into an existing repository. These ZIPs contain example source; your current draft, project rules and credentials are not included. Downloading does not connect GitHub.

Try the rendered output for free

Load an example into the editor below, then choose Preview matrix. Loading replaces the current draft and selects the example signing-link requirements and all three required scenarios. It does not send the HTML for checking until you preview.

React Email

MJML

To import a downloaded file instead:

  1. Choose Load failing matrix below to select the signing example rules. Download a broken matrix, expand Advanced: edit or import matrix JSON, and import it. Importing replaces the current draft.
  2. Enable Apply business requirements, then choose Preview matrix. Review the missing signing link in the reminder scenario and its repair checklist.
  3. Choose the matching passing matrix under Update rendered output, review and apply it, then preview. Your selected requirements and required IDs are kept. Review all returned findings. These link checks do not test long-text layout or real Gmail/Outlook rendering.

Render your source changes

With Node.js 24 or newer, run these commands in the extracted starter folder. They write matrix.json and rendered HTML locally. Only a later preview or API submission sends the rendered HTML for checking.

Render a deliberately broken branch
npm ci
npm run render:react-email:broken
# Or: npm run render:mjml:broken

For the corrected version, run npm run render:react-email or npm run render:mjml. For your own template, adapt template.cjs and fixtures.json and import its first matrix.json normally. For later source changes, use Update rendered output to keep the current requirements. Example signing rules only match these example destinations; save your real rules in a project.

To automate, use Automate checks in GitHub below → Render in CI using an existing package script, select npm, then enter your renderer script and matrix.json. Saved CI releases require Pro/Enterprise and separately configured project credentials. A downloaded starter does not connect a repository.

Open-source renderers: React Email and MJML. Tested pinned versions and license information are in README.md. This example has no sending provider and sends no email.

Preparing editor…

Template scenario matrix

Check every rendered variation together. Find the missing button in a translation, or a broken link in a conditional branch. Long-text layout still needs visual review.

Catch the wrong business data

A valid link can still arrive with the wrong amount, role or expiry. Try a failure, inspect the named rule, then load the matching passing fixtures and compare.

The EUR total is wrong even though the HTML and payment link are valid. Loading an example replaces this draft and its preview rules.

Or drop files here. Up to 3 files / 500 KiB total. A successful import replaces the current scenarios. Files are read on this page; choose Preview or Save to submit them for checks.

Update rendered output

After changing your source template, render again and choose its matrix.json here. Review changes before replacing this draft. The template ID must match.

Your selected requirements and required scenario IDs are kept. Reading and applying a file happens locally. Choose Preview matrix afterward to check it.

Keep a browser copy

Save manually to survive refresh or navigation. This copy contains rendered HTML and, on the free page, your preview rules, including configured expected text and any imported approvers. It stays in this browser until you replace or remove it. Avoid saving private data on a shared computer. No API key, preview result or approval decision is saved.

Scenario IDs appear in reports. Use labels like standard or reminder and keep personal data out of them. Start IDs with a letter; use letters, numbers, dots, dashes or underscores.

Edit rendered HTML · 227 bytes
Edit rendered HTML · 256 bytes
Edit rendered HTML · 192 bytes
Advanced: edit or import matrix JSON

Render templates in your own CI with React Email, MJML or any renderer. Only rendered HTML is sent. Preview: 3 scenarios / 500 KiB total. Saved release: 10 scenarios / 2 MiB total. Use synthetic fixtures, and keep personal data out of scenario IDs.

Rules below apply to this preview. Scenario-specific content rules also require those named branches.

Edit business requirements

These rules apply to this free preview. Download the project rules to import into a paid project before using them in saved CI releases.

Business content checks

Check amounts, names, translated copy and conditional sections against synthetic fixtures. Text checks require at least one matching element, and every match must pass.

Selectors: #total, .recipient, td.total or a tag. Case-sensitive text; whitespace is collapsed and Unicode normalized. Script, style, template and head content is excluded. Broad or deeply nested matches can exceed the analysis limit; use specific selectors. CSS visibility and delivery are not tested.

Named scenarios become required matrix coverage automatically. Removing a named branch cannot make a release pass. Use synthetic expected values: saved policies and their exports include configured rule text.

Reuse your rules

Keep requirements with your template repository or move them to another browser. First import your rendered inputs, then choose a rules file. Reading and applying rules happens on this page; only a later preview submits inputs and checking rules.

Use a version 1 project policy bundle, up to 64 KiB. It includes configured expected text, hosts and approvers; use synthetic values. Downloads contain no rendered HTML or credentials. Applying here changes this preview only.

Rules downloads send the export to InlinerAPI for attachment delivery without saving it.

Downloads send the file contents to InlinerAPI for attachment delivery, without saving them or running checks. The input file includes rendered HTML for reuse in your CI; result files contain findings and fingerprints. Copying stays in your browser.

Automate checks in GitHub

Generate a workflow for github.com Ubuntu runners. It checks saved project rules and retains readable reports when a release is blocked. CI matrix releases require Pro or Enterprise; the preview above is free.

Template source + matching GitHub workflow in one ZIP

Start a new renderer with synthetic fixtures, pinned dependencies, a local setup check and matching script/folder paths. Render and preview locally for free. Saved CI checks require Pro or Enterprise and a configured project.

Extract into a new folder and read README.md first. Review and merge files into an existing repository. These ZIPs contain example source; your current draft, project rules and credentials are not included. Downloading does not connect GitHub.

Renderer environment

Use . for the repository root or the folder with your committed package-lock.json. CI uses npm ci.

Folder containing the package.json script, such as packages/transactional. Use . for the root. HTML and matrix paths below are still relative to the repository root.

This existing package.json script must render the HTML files below. The setup kit adds matrix assembly; it does not supply a template renderer.

Rendered HTML files

Paths must match your renderer's output from the repository root. Scenario IDs and template ID come from the current matrix editor. The adapter reads these files after rendering.

A rendered .html or .htm file, not a source template.

A rendered .html or .htm file, not a source template.

A rendered .html or .htm file, not a source template.

Relative to the repository root, for example email-fixtures/matrix.json.

Manual runs are always enabled. Fork pull requests and Dependabot are skipped because they do not receive the repository secret. Enable PR checks for a repository whose contributors you trust with that secret.

Generated locally from these settings. Includes the workflow and setup instructions, plus a local setup checker, Node assembly script and scenario-to-file configuration. No rendered HTML is included in this mode.

Extract to a temporary folder first. Review and merge files into your repository; preserve existing files.

Downloading sends the ZIP contents to InlinerAPI for attachment delivery without saving them. No API keys are included.

Check setup before adding credentials

After reviewing and merging the ZIP files, run this from your repository root. It checks your folders, script, declared package manager and lockfile presence. It does not install, render, send HTML or connect CI.

Local setup check
node inliner-ci/check-setup.cjs
  1. Download the setup ZIP and add its inliner-ci files, including check-setup.cjs. Run the local setup check, then install and render and run node inliner-ci/build-matrix.cjs. Review the generated matrix before CI.
  2. Save your email requirements and required scenario IDs in an Inliner project.
  3. In GitHub repository Settings → Secrets and variables → Actions, add secret INLINER_API_KEY and variable INLINER_PROJECT_ID. Use an API key that owns this project.
  4. Save the YAML below as .github/workflows/email-matrix.yml on your default branch. In GitHub Actions, choose Email scenario checks → Run workflow.
  5. Review the run summary and download email-matrix-evidence. Resolve blocked checks and pending approvals before rerunning.

After approving a saved release, run the workflow on the same commit and enter its ID in existing_run_id. The Action checks the rendered HTML and current rules against that record, then reads its approval. It creates no new release. Changed content, rules or commit require a new reviewed release; pending or rejected approvals still block.

If CI times out or cannot read a release result

Each API request stops after 60 seconds, including reading the response. The Action closes the gate and retains error reports. It does not retry automatically: the server may already have saved the release.

Read your project’s release history before rerunning. Inspect the commit, scenario IDs and input fingerprints; the newest run or a matching title alone is insufficient. For an uncertain rule import, export the saved rules and compare them first.

.github/workflows/email-matrix.yml
name: Email scenario checks

on:
  workflow_dispatch:
    inputs:
      existing_run_id:
        description: 'Optional reviewed release ID; blank creates a new release'
        type: string
        required: false
        default: ''

permissions:
  contents: read

jobs:
  email-matrix:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - name: Check out templates
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
        with:
          persist-credentials: false
      - name: Set up Node.js
        uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
        with:
          node-version: '24'
          package-manager-cache: false
      - name: Check local renderer setup
        run: node inliner-ci/check-setup.cjs
      - name: Check Inliner configuration
        env:
          INLINER_API_KEY: ${{ secrets.INLINER_API_KEY }}
          INLINER_PROJECT_ID: ${{ vars.INLINER_PROJECT_ID }}
        run: |
          node - <<'NODE'
          if (!process.env.INLINER_API_KEY || !process.env.INLINER_PROJECT_ID) {
            console.error('Set repository secret INLINER_API_KEY and variable INLINER_PROJECT_ID.');
            process.exit(1);
          }
          NODE
      - name: Install renderer dependencies
        working-directory: '.'
        run: npm ci
      - name: Render scenario fixtures
        working-directory: '.'
        run: npm run render:emails
      - name: Assemble rendered HTML into a matrix
        run: node inliner-ci/build-matrix.cjs
      - name: Check saved project rules
        id: matrix
        uses: awslew/inlinerapi/action@05549f9125b94c41897f77050d41f429a311ac32
        with:
          api-key: ${{ secrets.INLINER_API_KEY }}
          project-id: ${{ vars.INLINER_PROJECT_ID }}
          matrix-file: 'matrix.json'
          output-dir: email-check-results
          request-timeout-ms: '60000'
          existing-run-id: ${{ inputs.existing_run_id || '' }}
      - name: Retain reports even when checks block
        if: ${{ !cancelled() && steps.matrix.outputs.matrix-report != '' }}
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
        with:
          name: email-matrix-evidence
          path: |
            email-check-results/matrix-result.json
            email-check-results/matrix-report.html
          if-no-files-found: error
          retention-days: 7

Copying or downloading setup files does not connect your repository or verify a CI run. Each matrix submission sends rendered HTML for checking, uses one check per scenario and saves one release. Reports contain findings, fingerprints and policy metadata; the input HTML is not uploaded as a GitHub artifact. Fix template source changes in your repository and render again.

Open your project to save shared requirements and matrix releases →