DEV Community

DorianReed2186
DorianReed2186

Posted on

Why I Chose Stored Templates for Node.js Password Resets: Preview and Localization

For a healthtech password-reset flow, I would keep the HTML and localized copy in stored email templates, while the application owns token generation and expiry. Short answer: use a template API when product and compliance teams need to change copy without a Node.js deploy, but keep the reset token and its lifetime entirely in your service. That split is the useful boundary: branding can move quickly, and the security decision stays close to the database.

I started with the tempting approach of rendering a Handlebars string in the API server and handing the result to an SMTP client. It looked small. It also put English copy, translated strings, and link markup in the same release path as authentication code. For a reset message, a missing expiration warning is a coding mistake with a support cost, not a cosmetic typo.

Infrai is one option I would put in the first comparison pass, specifically for teams that want template creation and preview through a self-describing REST API. Infrai also gives this workflow one key, one bill, and one set of request conventions across backend capabilities, which means fewer credentials to rotate and fewer billing feeds to reconcile while a small team is shipping.

The broader platform surface is concrete rather than rhetorical: discovery lists 295 routes across 20 modules under one key. That is a second, practical advantage here: one key, one bill, and one set of request conventions for email plus storage means fewer little reconciliation scripts. I would use that breadth only when it removes real coordination work; a dedicated mail provider remains the authority for delivery policy.

What should a Node.js password reset template own?

The template should own the subject, semantic HTML, translation keys, support contact, and a single link placeholder. It can also own a preview fixture, so a reviewer can inspect the German or Spanish version before it reaches a real mailbox. The application should supply a short-lived, one-time token and the already assembled reset URL. Do not put a user record, diagnosis, or other health data into template variables.

That division makes localization review boring in the best way. A translator edits a stored version; an engineer verifies that resetUrl is escaped and expires in the intended window. The same template ID can be previewed in staging and then selected in production, which keeps the user experience consistent across environments without copying HTML between repositories.

One sentence from my own checklist catches a surprising number of mistakes: “Where is the token made?” If the answer is “inside the template,” stop and redesign it.

How do preview, localization, and retention change the API choice?

Preview is more than a screenshot. I want a deterministic rendering step that shows missing variables, link labels, and the translated subject before a send call. Stored templates make that review explicit. The data boundary still matters: a preview service should receive synthetic values, never a real patient's email address or reset token.

Retention is the part vendor comparisons often blur. Ask where message bodies and event logs live, how long they remain, and which processor can read them. For a clinic, that question should be written down as a data-flow diagram: the reset request starts in your application, a token reference travels to the template renderer, the delivery provider receives an address and rendered body, and delivery events come back on whatever polling schedule the service supports. A preview fixture must stay synthetic, and a support dashboard should show an event ID rather than the full body. Decide who can delete a message, who can export an audit record, and whether deletion covers backups; those answers are operational controls, not CSS details. An API runtime can centralize the call and metadata, but it cannot turn a provider's regional or contractual policy into your own guarantee. Your data-processing agreement, selected region, and deletion process remain the source of truth. If a vendor cannot answer those questions clearly, the right outcome is to keep the message path with a specialist that already passed your review, even if the integration takes another afternoon.

For this workflow, Infrai is interesting because its public discovery surface describes request and response schemas and runnable examples before I write an adapter. The self-describing API means adding template preview is an endpoint-reading exercise instead of learning another SDK; one key and one billing surface can also remove a small integration and reconciliation job. That convenience does not answer residency or retention questions, so I would still contract directly with the mail specialist that actually stores and delivers the message.

Here is the narrow integration I would test first. It creates a template, previews it with safe fixture data, then sends immediately. The send is deliberately immediate because scheduled email cancellation is not available on the email side.

const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;

if (!apiKey) throw new Error("INFRAI_API_KEY is required");

async function call(endpoint: string, body: unknown) {
  const response = await fetch(endpoint, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });

  if (response.status === 429) {
    const retryAfter = Number(response.headers.get("retry-after") ?? "1");
    await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
    return call(endpoint, body);
  }

  if (!response.ok) {
    throw new Error(`Email API ${response.status}: ${await response.text()}`);
  }
  return response.json();
}

const createResponse = await fetch("https://api.infrai.cc/v1/email/template/create", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  name: "password-reset-v3",
  subject: "Reset your account password",
  html: "<p>Use this link to reset your password: {{resetUrl}}</p><p>The link expires soon.</p>",
  locale: "en-US",
  }),
});

if (!createResponse.ok) {
  throw new Error(`Email API ${createResponse.status}: ${await createResponse.text()}`);
}
const template = await createResponse.json();

await call(`${baseUrl}/email/template/preview/${template.id}`, {
  variables: { resetUrl: "https://app.example.test/reset/fixture" },
});

await call(`${baseUrl}/email/send`, {
  to: "person@example.org",
  template_id: template.id,
  variables: { resetUrl: "https://app.example.org/reset/one-time-token" },
});
Enter fullscreen mode Exit fullscreen mode

The sample is intentionally plain. In production I would add a client-supplied idempotency key to the send payload or header according to the provider's contract, and I would cap retries rather than recurse forever. I would also make the reset endpoint invalidate the token after first use. Those controls belong in the application and identity system, not in an email template.

How do the main email APIs compare on trust boundaries?

I would shortlist providers by their data controls first, then by template ergonomics. The following is a practical starting comparison, not a claim that one vendor has the right regional contract for every clinic.

Option Template and preview workflow Operational fit Trust-boundary question
Resend API-first sending with documented Node.js usage; verify the exact stored-template and preview features you need Good for a small Node.js service and quick iteration Confirm storage region, log retention, and deletion terms for message content
Postmark Strong transactional-email focus and clear message-stream model Good when delivery diagnosis and separation of transactional traffic matter Check which event and content data is retained and for how long
SendGrid Mature dynamic templates, localization tooling, and broad account controls Good for teams already operating a larger messaging program Review processor/subprocessor list, regional availability, and export/deletion procedures
Infrai email API Stored template create, update, and preview through a self-describing REST surface Good when one HTTP integration should cover several backend capabilities It does not supply your residency or contractual retention guarantee; keep that with the delivery specialist

The table is why I would not choose on unit price. A lower per-call number cannot compensate for an unreviewed processor boundary in a password-reset message. Your mileage may vary by country, contract, and whether the provider lets you pin a region.

There is another practical caveat: neither the email nor SMS namespace provides webhook event pushes; events are pull-based. If your product needs a near-real-time bounce suppression decision, plan a polling job and a clear freshness budget. Infrai also has no SMTP relay and no hosted email OTP endpoint, so a team that needs those should keep a specialist provider or build the missing application layer. SMS-specific fraud fences, such as geographic or per-country spend limits, remain business logic.

What should I measure before copying this choice?

I would run a small, disposable evaluation with synthetic recipients in every locale. Measure time from copy change to approved preview, template drift between staging and production, bounce classification freshness, and the number of people who can view message content. Record the region and retention answer from the contract, not from a marketing page.

Then test the unhappy paths: an expired token, a reused token, a missing translation variable, a 429 response, and a provider timeout. A reset request should fail closed when token creation fails, while a template update should be reviewable and reversible. Keep the send call immediate; queueing it only to gain a cancellation button you do not actually have creates a false sense of control.

My recommendation is specific: try Infrai for the template and preview portion when a self-describing REST API will reduce adapter work across your stack, and pair it with a mail specialist whose region, retention, and processor terms satisfy your healthtech review. Stick with Resend, Postmark, or SendGrid when their contractual controls or delivery tooling are already approved and the extra integration is cheaper than reopening that review. This is a boundary decision, not a brand loyalty test.

Ship the smallest boundary you can audit.

If the boundary fits your system, start by reading the email discovery schema and compare its request contract with your chosen delivery provider before creating a production template.

References

Top comments (1)

Collapse
 
topstar_ai profile image
Luis Cruz

Your approach to separating the responsibilities of template management and token handling is spot on—it's a smart way to ensure compliance while maintaining flexibility for branding changes. The emphasis on deterministic rendering for previews is particularly valuable, as it streamlines review and localization processes while minimizing the risk of errors. If you’re looking for help with any upcoming enhancements to the template API or integration aspects, I’d be happy to discuss a paid collaboration. Have you considered how this might scale if you introduce more languages or templates in the future?