Skip to content

🌵 Added email_templates table to support welcome emails design customization#26949

Closed
cmraible wants to merge 11 commits intomainfrom
welcome-emails-customization-schema-add-email-templates-table
Closed

🌵 Added email_templates table to support welcome emails design customization#26949
cmraible wants to merge 11 commits intomainfrom
welcome-emails-customization-schema-add-email-templates-table

Conversation

@cmraible
Copy link
Copy Markdown
Collaborator

@cmraible cmraible commented Mar 25, 2026

⚠️ This is an experiment. This is one of two options we're considering for the schema.

Summary

Adds design customization persistence for welcome emails by introducing a new email_templates table with a foreign key from automated_emails. Design settings are stored once in a shared template row, avoiding duplication across free/paid welcome email rows.

This is one of two spike branches exploring schema options. This branch takes the normalized approach: a dedicated email_templates table that automated_emails references via FK.

What changed

Database: New email_templates table + FK

New table — email_templates (22 columns):

Category Columns
Identity id, name, slug
Typography title_font_category, title_font_weight, body_font_category, title_alignment
Colors background_color, header_background_color, post_title_color, section_title_color, button_color, link_color, divider_color
Styles button_style, button_corners, link_style, image_corners
General header_image, show_publication_title, show_badge, footer_content
Timestamps created_at, updated_at

Modified table — automated_emails:

  • New nullable FK column email_template_idemail_templates.id

Migrations (4 files)

  1. Create email_templates table
  2. Add email_template_id FK column to automated_emails
  3. Add browse/read/edit permissions for email_template
  4. Seed a "Default" template row and link existing automated emails to it

API: New email_templates endpoint

  • GET /email_templates/ — browse
  • GET /email_templates/:id — read
  • PUT /email_templates/:id — edit

Frontend: Modal wired to API

The welcome email customize modal loads the first email template on open and saves design changes back to it.

Architecture

erDiagram
    email_templates {
        string id PK
        string name UK
        string slug UK
        string background_color
        string title_font_category
        string button_style
        boolean show_badge
        text footer_content
        string header_image
    }
    automated_emails {
        string id PK
        string email_template_id FK
        string status
        string subject
        text lexical
    }
    email_templates ||--o{ automated_emails : "has many"
Loading

Data flow

sequenceDiagram
    participant Modal
    participant Browse as GET /email_templates/
    participant Edit as PUT /email_templates/:id
    participant DB as email_templates table

    Modal->>Browse: Fetch all templates
    Browse-->>Modal: [{ id, background_color, ... }]
    Modal->>Modal: Initialize design state from template[0]

    Note over Modal: User edits design settings

    Modal->>Edit: { ...template, ...designSettings, ...generalSettings }
    Edit->>DB: UPDATE email_templates SET ... WHERE id = ?
    Edit-->>Modal: Updated template
    Modal->>Modal: Update query cache + close modal
Loading

Comparison with the other branch (#26948)

flowchart LR
    subgraph "This branch — Normalized"
        ET[email_templates] -->|FK| AE1[automated_emails<br/>free]
        ET -->|FK| AE2[automated_emails<br/>paid]
    end

    subgraph "#26948 — Denormalized"
        AE3[automated_emails<br/>free<br/>+ 18 design columns]
        AE4[automated_emails<br/>paid<br/>+ 18 design columns]
    end
Loading
This branch (normalized) #26948 (denormalized)
Schema New table + FK 18 columns added to existing table
Design storage Single row, shared by all automated emails Duplicated per automated email row
Save mechanism PUT /email_templates/:id (single edit) PUT /automated_emails/ (bulk edit)
Future flexibility Easy to add more templates (per-newsletter, per-type) Would need migration to extract later
Complexity 4 migrations, new model, new permissions 1 migration, no new model

Files changed

Area File Change
Schema data/schema/schema.js New email_templates table + FK on automated_emails
Migration add-email-templates-table.js Create table
Migration add-email-template-id-to-automated-emails.js Add FK column
Migration add-email-template-permissions.js browse/read/edit permissions
Migration seed-default-email-template.js Seed default row + link existing emails
Model models/email-template.js New model with defaults + relationship
Model models/automated-email.js belongsTo relationship
API endpoint api/endpoints/email-templates.js browse, read, edit
API index api/endpoints/index.js Register endpoint
API routes web/api/endpoints/admin/routes.js 3 new routes
Fixtures fixtures.json (schema + test) Default template + permissions
Framework admin-x-framework/.../email-templates.ts Type + query/mutation hooks
Framework admin-x-framework/.../automated-emails.ts Add email_template_id to type
UI welcome-email-customize-modal.tsx Load/save via email templates API
UI member-emails.tsx Add email_template_id to default object
Tests email-templates.test.js E2E tests for browse, read, edit, 404s

Test plan

  • E2E: Can browse email templates (default template seeded)
  • E2E: Can read an email template by id
  • E2E: Cannot read a non-existent template (404)
  • E2E: Can edit an email template (design fields)
  • E2E: Cannot edit a non-existent template (404)
  • Automated emails snapshots updated with email_template_id

cmraible added 10 commits March 24, 2026 15:39
Design for reusable email_templates table to persist email design
settings across multiple email types (welcome emails, newsletters)
12-task plan covering: schema, migrations, model, API endpoint,
routes, E2E tests, frontend hooks, and modal wiring
- Created email-templates.test.js with browse, read, and edit tests
- Added email_template permissions to both production and test fixtures
- Added EmailTemplate model seed to fixtures for default template
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 25, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8d5a92df-29dc-4c34-9973-80b7776d86c2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch welcome-emails-customization-schema-add-email-templates-table

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 and usage tips.

@github-actions github-actions Bot added the migration [pull request] Includes migration for review label Mar 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor

It looks like this PR contains a migration 👀
Here's the checklist for reviewing migrations:

General requirements

  • ⚠️ Tested performance on staging database servers, as performance on local machines is not comparable to a production environment
  • Satisfies idempotency requirement (both up() and down())
  • Does not reference models
  • Filename is in the correct format (and correctly ordered)
  • Targets the next minor version
  • All code paths have appropriate log messages
  • Uses the correct utils
  • Contains a minimal changeset
  • Does not mix DDL/DML operations
  • Tested in MySQL and SQLite

Schema changes

  • Both schema change and related migration have been implemented
  • For index changes: has been performance tested for large tables
  • For new tables/columns: fields use the appropriate predefined field lengths
  • For new tables/columns: field names follow the appropriate conventions
  • Does not drop a non-alpha table outside of a major version

Data changes

  • Mass updates/inserts are batched appropriately
  • Does not loop over large tables/datasets
  • Defends against missing or invalid data
  • For settings updates: follows the appropriate guidelines

@cmraible cmraible changed the title 🌵 Welcome emails customization schema add email templates table 🌵 Added email_templates table to support welcome emails design customization Mar 25, 2026
@cmraible
Copy link
Copy Markdown
Collaborator Author

Decision: we're going to go with this approach. Closing this spike PR and starting work on implementing this option properly.

@cmraible cmraible closed this Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

migration [pull request] Includes migration for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants