# TailwindCSS Migration Implementation Plan > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Replace the ~1000 lines of custom CSS with TailwindCSS utility classes, while preserving the existing design and dark mode support. **Architecture:** 1. Install TailwindCSS as a dev dependency with PostCSS 2. Create a minimal `tailwind.config.js` that extends the default theme with the existing color palette 3. Keep a small `base.css` for critical custom styles that can't be replaced (e.g., CodeMirror overrides, Milkdown-specific styles) 4. Replace HTML class names with Tailwind utility classes in templates 5. Use `@apply` for complex patterns that appear multiple times **Tech Stack:** TailwindCSS 4.x, PostCSS, existing esbuild for CSS bundling --- ## Current CSS Inventory | File | Lines | Purpose | |------|-------|---------| | `static/css/style.css` | 427 | Base styles, navbar, cards, buttons, forms, alerts | | `static/css/editor.css` | 419 | Editor layout, toolbar, modals, split pane | | `static/css/markdown.css` | 84 | Markdown preview rendering | | `static/css/diff.css` | 60 | Diff view styling | | **Total** | **990** | | --- ## Chunk 1: Setup TailwindCSS **Files:** - Modify: `/Users/johnluther/projects/diffdown/package.json` - Create: `/Users/johnluther/projects/diffdown/tailwind.config.js` - Create: `/Users/johnluther/projects/diffdown/postcss.config.js` - Create: `/Users/johnluther/projects/diffdown/src/styles/input.css` - [ ] **Step 1: Install TailwindCSS and dependencies** Run: `npm install -D tailwindcss postcss autoprefixer` - [ ] **Step 2: Initialize Tailwind config** ```javascript /** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./templates/**/*.html", "./static/**/*.js", ], darkMode: 'class', // Use data-theme attribute for dark mode theme: { extend: { colors: { bg: 'var(--bg)', 'bg-card': 'var(--bg-card)', text: 'var(--text)', 'text-muted': 'var(--text-muted)', border: 'var(--border)', primary: 'var(--primary)', 'primary-hover': 'var(--primary-hover)', danger: 'var(--danger)', success: 'var(--success)', 'code-bg': 'var(--code-bg)', 'alert-error-bg': 'var(--alert-error-bg)', 'alert-error-border': 'var(--alert-error-border)', }, fontFamily: { sans: ['"Barlow"', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', 'sans-serif'], heading: ['"Lexend"', '-apple-system', 'BlinkMacSystemFont', '"Segoe UI"', 'Roboto', 'sans-serif'], mono: ['"JetBrains Mono"', '"Fira Code"', '"Cascadia Code"', 'monospace'], }, borderRadius: { DEFAULT: '6px', }, }, }, plugins: [], } ``` - [ ] **Step 3: Create PostCSS config** ```javascript module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, } ``` - [ ] **Step 4: Create input.css for Tailwind directives** ```css @tailwind base; @tailwind components; @tailwind utilities; /* Keep custom font import */ @import url(https://fonts.bunny.net/css?family=barlow:100,200,300,400,500,600|lexend:100,200,300,400,500,600,700,800,900); /* CSS variables - kept for backward compatibility */ :root { --bg: #fafafa; --bg-card: #fff; --text: #1a1a2e; --text-muted: #6b7280; --border: #e5e7eb; --primary: #2563eb; --primary-hover: #1d4ed8; --danger: #dc2626; --success: #16a34a; --code-bg: #f3f4f6; --alert-error-bg: #fef2f2; --alert-error-border: #fecaca; } [data-theme="dark"] { --bg: #0d1117; --bg-card: #161b22; --text: #e6edf3; --text-muted: #ededed; --text-secondary: #d4d4d4; --border: #30363d; --code-bg: #1f2428; --primary: #388bfd; --primary-hover: #58a6ff; --danger: #f85149; --success: #3fb950; --alert-error-bg: #1c0608; --alert-error-border: #6e1c20; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --bg: #0d1117; --bg-card: #161b22; --text: #e6edf3; --text-muted: #ededed; --text-secondary: #d4d4d4; --border: #30363d; --code-bg: #1f2428; --primary: #388bfd; --primary-hover: #58a6ff; --danger: #f85149; --success: #3fb950; --alert-error-bg: #1c0608; --alert-error-border: #6e1c20; } } ``` - [ ] **Step 5: Add build script to package.json** ```json "scripts": { "build:css": "npx tailwindcss -i ./src/styles/input.css -o ./static/css/tailwind.css", "build:collab": "npx esbuild node_modules/prosemirror-collab/dist/index.js --bundle --format=esm --outfile=static/vendor/collab.js", "build": "npm run build:css && npm run build:collab" } ``` - [ ] **Step 6: Build TailwindCSS** Run: `npm run build:css` Expected: Creates `static/css/tailwind.css` with Tailwind utilities - [ ] **Step 7: Commit** ```bash git add package.json tailwind.config.js postcss.config.js src/styles/input.css static/css/tailwind.css git commit -m "feat: add TailwindCSS setup" ``` --- ## Chunk 2: Replace CSS in base.html **Files:** - Modify: `/Users/johnluther/projects/diffdown/templates/base.html` - [ ] **Step 1: Replace navbar styles with Tailwind classes** Old: ```html ``` New: ```html ``` - [ ] **Step 2: Replace main and alert styles** Old: ```html
{{if .Error}}
{{.Error}}
{{end}} {{block "content" .}}{{end}}
``` New: ```html
{{if .Error}}
{{.Error}}
{{end}} {{block "content" .}}{{end}}
``` - [ ] **Step 3: Update base.html to link tailwind.css instead of style.css** Old: ```html ``` New (keep style.css for now, we'll remove later): ```html ``` - [ ] **Step 4: Test locally** Run: `make run` Open: `http://127.0.0.1:8080` Verify: Navbar, main content, and dark mode still work - [ ] **Step 5: Commit** ```bash git add templates/base.html git commit -m "refactor: convert base.html to TailwindCSS classes" ``` --- ## Chunk 3: Replace style.css (base styles) **Files:** - Modify: `/Users/johnluther/projects/diffdown/templates/landing.html` - Modify: `/Users/johnluther/projects/diffdown/templates/documents.html` - Modify: `/Users/johnluther/projects/diffdown/templates/register.html` - Modify: `/Users/johnluther/projects/diffdown/templates/login.html` - [ ] **Step 1: Review style.css for reusable patterns** Run: `cat static/css/style.css` Identify patterns to convert: - `.btn`, `.btn-sm`, `.btn-outline` → Tailwind utility classes - `.alert`, `.alert-error` → Already handled in base.html - `.card` → Tailwind card styles - `.form-group`, `.form-label`, `.form-input` → Tailwind form styles - [ ] **Step 2: Convert landing.html** Read and convert elements to use Tailwind classes inline instead of custom CSS classes. - [ ] **Step 3: Convert documents.html** Same approach for the documents dashboard page. - [ ] **Step 4: Convert auth pages (register, login)** Convert form elements to use Tailwind classes. - [ ] **Step 5: Test all pages** Run: `make run` Verify: Landing, documents, login, register pages render correctly with dark mode - [ ] **Step 6: Commit** ```bash git add templates/ git commit -m "refactor: convert auth and dashboard pages to TailwindCSS" ``` --- ## Chunk 4: Replace editor.css (complex layout) **Files:** - Modify: `/Users/johnluther/projects/diffdown/templates/document_edit.html` - Modify: `/Users/johnluther/projects/diffdown/templates/document_view.html` - [ ] **Step 1: Review editor.css** Key patterns: - `.editor-page` → Full height flex container - `.editor-toolbar` → Sticky top toolbar with flex layout - `.editor-rich` → Rich text editor container - `.editor-split` → Split pane layout (editor + preview) - `.invite-modal` → Modal overlay and box - [ ] **Step 2: Convert document_edit.html toolbar** ```html
...
...
...
``` - [ ] **Step 3: Convert editor containers** - [ ] **Step 4: Convert modal components** - [ ] **Step 5: Test editor functionality** Run: `make run` Create/edit a document Verify: Rich mode, source mode, preview, toolbar all work - [ ] **Step 6: Commit** ```bash git add templates/document_edit.html templates/document_view.html git commit -m "refactor: convert editor pages to TailwindCSS classes" ``` --- ## Chunk 5: Replace markdown.css and diff.css **Files:** - Modify: `/Users/johnluther/projects/diffdown/templates/document_view.html` - Modify: `/Users/johnluther/projects/diffdown/templates/landing.html` - Create: Keep minimal overrides in a new file if needed - [ ] **Step 1: Review markdown.css** Mostly Markdown rendering styles - can keep as-is for now with minimal overrides. - [ ] **Step 2: Review diff.css** Diff view styles - can keep as-is. - [ ] **Step 3: Link tailwind.css in view templates** Add `` to templates that don't have it. - [ ] **Step 4: Test view pages** Run: `make run` View a document Verify: Markdown renders correctly with dark mode - [ ] **Step 5: Commit** ```bash git add templates/ git commit -m "refactor: add TailwindCSS to view pages" ``` --- ## Chunk 6: Cleanup and final integration **Files:** - Delete: `/Users/johnluther/projects/diffdown/static/css/style.css` (after verifying no missing styles) - Delete: `/Users/johnluther/projects/diffdown/static/css/editor.css` (after verifying no missing styles) - Modify: `/Users/johnluther/projects/diffdown/templates/base.html` - Modify: `/Users/johnluther/projects/diffdown/package.json` - [ ] **Step 1: Check for any remaining custom CSS references** Run: `grep -r 'class="' templates/ | grep -E '\.(btn|alert|card|form)' | head -20` - [ ] **Step 2: Remove unused CSS files one by one** Start with style.css - comment out the link in base.html, test thoroughly, then delete. - [ ] **Step 3: Keep minimal base.css for CodeMirror/Milkdown overrides** Create `static/css/base.css` for: - CodeMirror theme overrides - Milkdown-specific styles - Any other third-party library styles - [ ] **Step 4: Update base.html to remove old CSS links** ```html ``` - [ ] **Step 5: Add CSS build to existing build command** ```json "scripts": { "build": "npm run build:css && npm run build:collab", "build:css": "npx tailwindcss -i ./src/styles/input.css -o ./static/css/tailwind.css --minify", "build:collab": "npx esbuild node_modules/prosemirror-collab/dist/index.js --bundle --format=esm --outfile=static/vendor/collab.js" } ``` - [ ] **Step 6: Final testing** Run: `make build && make run` Test all pages: - Landing page - Login/register - Documents list - Document edit (rich + source mode) - Document view - About page - Dark mode toggle - [ ] **Step 7: Commit final cleanup** ```bash git add -A git commit -m "refactor: complete TailwindCSS migration, remove legacy CSS" ``` --- ## Testing Checklist - [ ] Landing page displays correctly (logged out) - [ ] Login page renders with proper styling - [ ] Register page renders with proper styling - [ ] Dashboard shows document list with cards - [ ] Dark mode toggle works on all pages - [ ] Document editor loads in rich mode - [ ] Document editor toggles to source mode - [ ] Preview pane renders Markdown - [ ] Invite modal opens/closes properly - [ ] Document view renders Markdown - [ ] About page displays correctly - [ ] Navbar shows correct links for logged in/out users --- ## Rollback Plan If issues arise: 1. Keep old CSS files in a `static/css/legacy/` folder 2. Restore old link in base.html: `` 3. Test before committing deletions --- ## Notes - TailwindCSS 4.x uses a different configuration approach - verify which version is installed - The `data-theme` attribute approach is already implemented, Tailwind's `darkMode: 'class'` should work with it - CodeMirror and Milkdown may need specific overrides in a separate CSS file - Consider using `@layer components` in input.css for complex custom patterns