feat: MJML email template system with jersey reminder template #1

Closed
opened 2026-03-21 16:52:25 +00:00 by forgejo_admin · 0 comments

Type

Feature

Lineage

plan-wkq -> Phase 11 (Girls Tryout) -> discovered scope -> new capability. Parent issue: basketball-api#134.

Repo

forgejo_admin/westside-emails

User Story

As an admin
I want branded email templates decoupled from API code
So that copy changes don't require code changes, PRs, or deploys

Context

Current email system embeds 825 lines of inline-CSS HTML inside Python f-strings in basketball-api's services/email.py. Every copy change requires a code change, PR, and deploy. MJML enables semantic markup that compiles to battle-tested inline-CSS HTML for Gmail, Outlook, and Apple Mail. Templates are decoupled from API code -- basketball-api loads compiled HTML and does simple string replacement at send time.

File Targets

Files to create:

  • package.json -- mjml dependency and build/preview scripts
  • scripts/build.js -- node script to compile src/.mjml to dist/.html
  • src/base-layout.mjml -- shared Westside brand wrapper (header with logo, footer, brand colors)
  • src/jersey-reminder.mjml -- girls jersey ordering reminder template
  • sample-data/jersey-reminder.json -- sample data for preview
  • preview/index.html -- loads compiled HTML with sample data for visual check
  • .gitignore -- ignore node_modules and dist

Acceptance Criteria

  • npm run build compiles MJML to HTML in dist/
  • dist/jersey-reminder.html renders branded email with placeholder markers in browser
  • Brand colors match Westside design system (black #1a1a1a, red #c41230, white #ffffff)
  • Jersey images from MinIO CDN are included and accessible
  • Template uses {{variable}} literal markers for simple string replacement

Test Expectations

  • MJML compilation: npm run build exits 0 with valid HTML output
  • dist/jersey-reminder.html contains expected placeholder markers
  • Run command: npm run build && open preview/index.html

Constraints

  • MJML for compilation, NOT Jinja2 or server-side template engine
  • {{variable}} markers are literal strings in compiled HTML
  • Brand colors: black #1a1a1a, red #c41230, white #ffffff, light gray #e8e8e8
  • Gentle tone for jersey reminder -- no pressure, opt-out friendly
  • Jersey images from https://minio-api.tail5b443a.ts.net/assets/westside/jerseys/

Checklist

  • package.json with mjml dependency
  • base-layout.mjml with Westside brand
  • jersey-reminder.mjml template
  • Build script compiles successfully
  • Preview works in browser
  • No unrelated changes
  • project-westside-basketball -- project this affects
  • basketball-api#134 -- parent issue for MJML email service integration
### Type Feature ### Lineage `plan-wkq` -> Phase 11 (Girls Tryout) -> discovered scope -> new capability. Parent issue: basketball-api#134. ### Repo `forgejo_admin/westside-emails` ### User Story As an admin I want branded email templates decoupled from API code So that copy changes don't require code changes, PRs, or deploys ### Context Current email system embeds 825 lines of inline-CSS HTML inside Python f-strings in basketball-api's services/email.py. Every copy change requires a code change, PR, and deploy. MJML enables semantic markup that compiles to battle-tested inline-CSS HTML for Gmail, Outlook, and Apple Mail. Templates are decoupled from API code -- basketball-api loads compiled HTML and does simple string replacement at send time. ### File Targets Files to create: - `package.json` -- mjml dependency and build/preview scripts - `scripts/build.js` -- node script to compile src/*.mjml to dist/*.html - `src/base-layout.mjml` -- shared Westside brand wrapper (header with logo, footer, brand colors) - `src/jersey-reminder.mjml` -- girls jersey ordering reminder template - `sample-data/jersey-reminder.json` -- sample data for preview - `preview/index.html` -- loads compiled HTML with sample data for visual check - `.gitignore` -- ignore node_modules and dist ### Acceptance Criteria - [ ] `npm run build` compiles MJML to HTML in `dist/` - [ ] `dist/jersey-reminder.html` renders branded email with placeholder markers in browser - [ ] Brand colors match Westside design system (black #1a1a1a, red #c41230, white #ffffff) - [ ] Jersey images from MinIO CDN are included and accessible - [ ] Template uses `{{variable}}` literal markers for simple string replacement ### Test Expectations - [ ] MJML compilation: `npm run build` exits 0 with valid HTML output - [ ] `dist/jersey-reminder.html` contains expected placeholder markers - [ ] Run command: `npm run build && open preview/index.html` ### Constraints - MJML for compilation, NOT Jinja2 or server-side template engine - `{{variable}}` markers are literal strings in compiled HTML - Brand colors: black #1a1a1a, red #c41230, white #ffffff, light gray #e8e8e8 - Gentle tone for jersey reminder -- no pressure, opt-out friendly - Jersey images from https://minio-api.tail5b443a.ts.net/assets/westside/jerseys/ ### Checklist - [ ] package.json with mjml dependency - [ ] base-layout.mjml with Westside brand - [ ] jersey-reminder.mjml template - [ ] Build script compiles successfully - [ ] Preview works in browser - [ ] No unrelated changes ### Related - `project-westside-basketball` -- project this affects - basketball-api#134 -- parent issue for MJML email service integration
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/westside-emails#1
No description provided.