refactor(email): externalize styles to email.css, inject via expandLinkTag
Some checks failed
Build and Push Backend Image / build (push) Failing after 22s

- Move @import "@maizzle/tailwindcss" + @theme tokens to packages/email/email.css
- Layout uses <link rel="stylesheet" href="{{ cssPath }}" inline> — Maizzle's
  expandLinkTag reads the absolute path and expands it to a <style> tag, which
  the second compileCss pass then processes with @tailwindcss/postcss + LightningCSS
- render.ts passes cssPath as a local so the expression resolves inside the layout
- Layout head is now clean HTML with no inline style logic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 10:56:30 +01:00
parent a30692b1ac
commit d0f0d865b6
3 changed files with 27 additions and 25 deletions

18
packages/email/email.css Normal file
View File

@@ -0,0 +1,18 @@
@import "@maizzle/tailwindcss";
@theme {
/* ── Design tokens — exact mirror of frontend app.css :root ── */
--color-background: oklch(0.98 0.01 320);
--color-foreground: oklch(0.08 0.02 280);
--color-card: oklch(0.99 0.005 320);
--color-card-foreground: oklch(0.08 0.02 280);
--color-muted: oklch(0.95 0.01 280);
--color-muted-foreground: oklch(0.4 0.02 280);
--color-border: oklch(0.85 0.02 280);
--color-primary: oklch(56.971% 0.27455 319.257);
--color-primary-foreground: oklch(0.98 0.01 320);
/* ── Font ── */
--font-sans: 'Noto Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
}

View File

@@ -1,10 +1,11 @@
import { readFile } from "node:fs/promises";
import path from "node:path";
// Templates live at packages/email/templates/
// At runtime (dist/render.js), __dirname is packages/email/dist/
const PKG_ROOT = path.join(__dirname, "..");
const TEMPLATES_ROOT = path.join(PKG_ROOT, "templates");
const CSS_PATH = path.join(PKG_ROOT, "email.css");
const BASE_URL = process.env.PUBLIC_URL ?? "https://sexy.pivoine.art";
export interface RenderOptions {
@@ -26,14 +27,15 @@ export async function renderTemplate(
root: TEMPLATES_ROOT,
folders: ["layouts"],
},
// Override PostCSS `from` so @tailwindcss/postcss resolves @import "@maizzle/tailwindcss"
// from this package's node_modules (defu gives our value priority over the cwd default).
// Override PostCSS `from` so @import "@maizzle/tailwindcss" resolves
// from this package's node_modules (defu gives our value priority).
postcss: {
options: {
from: path.join(PKG_ROOT, "email.css"),
from: CSS_PATH,
},
},
locals: {
cssPath: CSS_PATH, // layout uses {{ cssPath }} in <link href="{{ cssPath }}" inline>
baseUrl: BASE_URL,
...locals,
},

View File

@@ -10,31 +10,13 @@
<![endif]-->
<title>{{ page.title || 'sexy.pivoine.art' }}</title>
<!-- Noto Sans for clients that support web fonts (Gmail, Apple Mail) -->
<!-- Noto Sans — progressive enhancement for clients that support web fonts -->
<style plain>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;600;700&display=swap');
</style>
<style>
@import "@maizzle/tailwindcss";
@theme {
/* ── Design tokens — exact mirror of frontend app.css :root ── */
--color-background: oklch(0.98 0.01 320);
--color-foreground: oklch(0.08 0.02 280);
--color-card: oklch(0.99 0.005 320);
--color-card-foreground: oklch(0.08 0.02 280);
--color-muted: oklch(0.95 0.01 280);
--color-muted-foreground: oklch(0.4 0.02 280);
--color-border: oklch(0.85 0.02 280);
--color-primary: oklch(56.971% 0.27455 319.257);
--color-primary-foreground: oklch(0.98 0.01 320);
/* ── Font ── */
--font-sans: 'Noto Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
}
</style>
<!-- Design tokens + Tailwind preset — path resolved by render.ts -->
<link rel="stylesheet" href="{{ cssPath }}" inline>
</head>
<body class="bg-background m-0 p-0 font-sans">