Skip to content

feat(serve): preview templates with sample data from previewProps - #1906

Open
ImDarkTom wants to merge 1 commit into
maizzle:masterfrom
ImDarkTom:feat/preview-props
Open

ImDarkTom wants to merge 1 commit into
maizzle:masterfrom
ImDarkTom:feat/preview-props

Conversation

@ImDarkTom

@ImDarkTom ImDarkTom commented Sep 29, 2026 •

Copy link
Copy Markdown

Implements request in discussion #1802, which was converted from an issue in #1799.

On the dev server, templates that take props are currently given undefined as serve never passes props, causing previews to show up incorrectly or with blank values as well as warnings being spammed to the log whenever an email with props is previewed.

As the discussion mentions, withDefaults() is not a good solution, as it means that any sample props could potentially leak into production emails if they're accidentally left missing.

This PR introduces a way of showing sample prop data on the dev server via exporting it from a plain <script> block:

<script lang="ts">
interface Props {
    name: string;
    plan: 'Free' | 'Pro';
    redirectUrl?: string;
}

export const previewProps: Props = { name: 'John Doe', plan: 'Pro' }
</script>

<script setup lang="ts">
defineProps<Props>();
</script>

Only the dev server ever uses the exported previewProps. render() ignore them, as proven by the new test in serve.test.ts.

I attempted to run the formatter as given in the contributing guidelines, but no script seemed to exist. I know CONTRIBUTING says to ask before working on significant features, but a discussion for this already exists albeit with no replies. I'm happy to rework this if needed.

Screenshots:
Code Example
Example Result

Summary by CodeRabbit

  • New Features
    • Development previews can now display templates using values exported as previewProps. Values passed directly to a render take precedence.
    • Programmatic rendering supports passing props to populate template properties.
  • Documentation
    • Updated guidance for configuring preview values in templates and converting React Email examples. Clarified that preview values aren’t applied to regular renders or builds.

@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: b787f7c1-aa8c-4150-bc45-137147f267cb

📥 Commits

Reviewing files that changed from the base of the PR and between 1c9fa8f and df7b0ea.

📒 Files selected for processing (5)
  • skills/maizzle/SKILL.md
  • skills/maizzle/references/CONVERT-REACT-EMAIL.md
  • src/render/createRenderer.ts
  • src/serve.ts
  • src/tests/serve.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

Dev-server renders can use a template’s exported previewProps when caller-provided props are nullish. Regular render() calls do not use those preview values. The documentation now describes this behavior and updates its React Email conversion example.

Changes

Preview Props

Layer / File(s) Summary
Preview rendering and usage
src/render/createRenderer.ts, src/serve.ts, src/tests/serve.test.ts, skills/maizzle/SKILL.md, skills/maizzle/references/CONVERT-REACT-EMAIL.md
Renderer.render accepts a preview option and uses the template’s exported previewProps when caller props are nullish. The dev server enables this option. The test checks that preview values appear in a dev-server render but not a regular render() call. The guides describe the export and update the password-reset example.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant DevServer
  participant getRendered
  participant Renderer.render
  participant TemplateModule
  participant createSSRApp
  DevServer->>getRendered: Request template render
  getRendered->>Renderer.render: Pass source and preview=true
  Renderer.render->>TemplateModule: Load component and previewProps
  TemplateModule-->>Renderer.render: Return default component and previewProps
  Renderer.render->>createSSRApp: Pass component and selected props
Loading

Suggested reviewers: cossssmin

Merge Risk: ⚪ Minimal · up to df7b0

Development previews can use template sample props without changing regular rendering. No actionable merge-blocking issue is identified; merge after normal checks pass.

Security Architecture Review

Security architecture risk: 🔵 Low · up to df7b0

Normal rendering and builds do not automatically use sample values, even when sharing resources with development previews. Development test emails do use those values. Remaining uncertainty concerns development-server exposure and reuse of mutable sample objects.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — The traced exposure is configured templates rendered through existing development endpoints, including test-email sending. Sample content can leave through a configured SMTP transport; without one, sending uses an Ethereal test account. Regular render and build callers do not enable preview.

Trust Boundaries and Controls

  • observed — Render and email request slugs must match files enumerated from configured content patterns before invocation. Requests do not supply preview props. Recipient selection and transport authority predate this PR; the new data source is the selected template's export.
  • observed — Regular render passes only caller props, including when reusing the development renderer. The added regression test checks that preview data appears in the development response but not in a subsequent regular render.

Resilience and Maintainability Implications

  • inferred — Per-call selection prevents the preview flag from persisting into later production calls, but it does not give nested sample values independent ownership. Mutating module-exported values during SSR could affect later previews using the cached module. No concrete mutation path was established, so this is not retained as a security finding.

Hardening Proposals

  • proposed — Document that development test emails inherit previewProps and may use a real configured transport. Recommend synthetic, non-sensitive sample values rather than production credentials or personal data.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 3 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: using previewProps to provide sample data when serving template previews.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 3 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant