SendOps lets you preview templates with real data, manage test data profiles, and send test emails — all from the template detail page. Test data profiles can be synced from your repository or created directly in SendOps.

## Template preview

Every template has a side-by-side preview on the **Overview** tab of the template detail page. The left panel shows the raw Handlebars source code, and the right panel shows the rendered HTML output.

The preview updates automatically when you select a different test data profile, so you can see how the template looks with different data without leaving the page.



## Test data profiles

Test data profiles provide the variable values used to render template previews and send test emails. Each template can have multiple profiles to test different scenarios (e.g. a profile for a premium user, one for a free user, one with a long list of items).

### Profile types

There are two types of test data profiles:

**Git-synced profiles** — defined in your repository's [`sendops.json` manifest file](/templates/manifest-file). These profiles are read-only in SendOps and update automatically when you push changes to your repository. Use these for canonical test data that the whole team shares.

**User-managed profiles** — created directly in SendOps by any team member. These can be edited, duplicated, and deleted freely. Use these for personal testing scenarios or quick experiments.



### Managing profiles

From the **Test Data** tab on the template detail page:

- **Create** — click **New Profile** to create a user-managed profile. Give it a name and provide JSON data.
- **Edit** — open any user-managed profile to modify its data. Git-synced profiles are read-only.
- **Duplicate** — copy an existing profile (either type) as a starting point for a new user-managed profile.
- **Delete** — remove a user-managed profile. Git-synced profiles cannot be deleted from SendOps.
- **Set as default** — mark a profile as the default. The default profile is automatically selected when previewing or sending a test email.

### Test data editor

When creating or editing a profile, the editor has two tabs:

**JSON tab** — edit the raw JSON directly. This gives you full control over the data structure, including nested objects and arrays.

```json
{
  "name": "Jane Smith",
  "premium_member": true,
  "items": [
    { "name": "Widget", "price": "$9.99" },
    { "name": "Gadget", "price": "$24.99" }
  ],
  "shipping_address": {
    "street": "123 Main St",
    "city": "Springfield",
    "state": "IL",
    "zip": "62701"
  }
}
```

**Form tab** — a form-based editor with type-aware inputs. Strings show text fields, booleans show toggles, and arrays let you add or remove items. This is convenient for quick edits without writing JSON.

### Stub data generation

When you create a new profile, SendOps can **auto-generate stub data** from the template's extracted variables. The generated data uses type-appropriate defaults: strings are empty (`""`), numbers are `0`, booleans default to `false`, and objects get their nested fields populated. Arrays are left empty unless the template iterates over fields inside them (for example `{{#each items}}…{{this.name}}`), in which case you get one sample element with those fields stubbed.

This gives you a working starting point that you can customize, rather than having to build the JSON from scratch.

### Variable warnings

The test data editor shows warnings when your data doesn't match the template's variables:

- **Missing variables** — variables used in the template that aren't present in your test data. The preview will show blank values for these.
- **Extra variables** — data fields that don't correspond to any template variable. These are ignored during rendering but may indicate a typo or outdated data.
- **Type mismatches** — when a variable is used as one type in the template (e.g. in an `{{#each}}` block, implying an array) but the test data provides a different type (e.g. a string).

## Sending test emails

From the template detail page, click **Send Test** to deliver a rendered version of the template to a real inbox.


  <Step title="Enter a recipient">
    Type the email address where the test should be delivered.
  </Step>

  <Step title="Select a test data profile">
    Choose a profile to use for rendering. The preview updates in real-time as you switch profiles.
  </Step>

  <Step title="Review the preview">
    Verify that the rendered template looks correct with the selected data.
  </Step>

  <Step title="Send">
    Click **Send**. SendOps renders the template with the selected profile data and sends the email.
  </Step>


On success, SendOps shows details including the **message ID**, **subject line**, and **sending method** used.


  If your SES account is still in the sandbox, test emails can only be sent to verified email addresses. See [SES Sandbox & Production](/sending-email/ses-sandbox) for details on moving to production.


## Versioning

SendOps tracks template versions through Git — there is no separate version history UI. Each time a sync processes a template, SendOps records the **content hash** and **commit SHA**. This lets SendOps detect whether a template actually changed between syncs.

To view the history of a template's changes, use `git log` on the template file in your repository. To revert a template, revert the commit in Git and push to the default branch — SendOps syncs the restored content automatically.


  You don't need to configure anything for versioning. SendOps compares content hashes on each sync and only re-deploys templates that have actually changed.


## What's next?

- [Template Management](/templates/template-management) — connecting GitHub, sync, validation, and template structure.
- [Pull Requests & Compare](/templates/github-integration) — review template changes through PRs and compare branches.
- [How Email Flows](/sending-email/email-flow) — understand how templates fit into the sending pipeline.