# ADR-003: Front-end Technology Stack ## Status Accepted ## Context StarPunk requires a front-end for: 1. Public interface (homepage, note permalinks) - Server-side rendered 2. Admin interface (note creation/editing) - Requires some interactivity 3. Progressive enhancement principle - Core functionality must work without JavaScript The front-end must be minimal, elegant, and align with the "no client-side complexity" principle stated in CLAUDE.MD. ## Decision ### Public Interface: Server-Side Rendered HTML - **Template Engine**: Jinja2 (included with Flask) - **CSS**: Custom CSS (no framework) - **JavaScript**: None required for V1 - **Build Tools**: None required ### Admin Interface: Enhanced Server-Side Rendering - **Template Engine**: Jinja2 (included with Flask) - **CSS**: Custom CSS (shared with public interface) - **JavaScript**: Minimal vanilla JavaScript for markdown preview only - **Build Tools**: None required ### Asset Management - **CSS**: Single stylesheet served statically - **JavaScript**: Single optional file for markdown preview - **No bundler**: Direct file serving - **No transpilation**: Modern browsers only (ES6+) ## Rationale ### Server-Side Rendering (SSR) **Simplicity Score: 10/10** - Zero build process - No JavaScript framework complexity - Direct Flask template rendering - Familiar Jinja2 syntax **Fitness Score: 10/10** - Perfect for content-first site - Faster initial page load - Better SEO (though not critical for single-user) - Works without JavaScript - Easier to implement microformats **Maintenance Score: 10/10** - Jinja2 is stable and mature - No framework version updates - No npm dependency hell - Templates are simple HTML ### No CSS Framework **Simplicity Score: 10/10** - Custom CSS is ~200 lines for entire site - No unused classes or styles - Full control over appearance - No framework learning curve **Fitness Score: 9/10** - StarPunk needs minimal, elegant design - Single theme, no customization needed - Mobile-responsive can be achieved with simple media queries - No complex components needed ### Minimal JavaScript Approach **Simplicity Score: 9/10** - Vanilla JavaScript only (no React/Vue/Svelte) - Single purpose: markdown preview in admin - Optional progressive enhancement - No build step required **Fitness Score: 10/10** - Markdown preview improves UX but isn't required - All functionality works without JavaScript - Can use fetch API for preview without library - Modern browser features are sufficient ## Consequences ### Positive - Zero build time - No node_modules directory - Instant development setup - Fast page loads - Works with JavaScript disabled - Easy to understand and modify - Microformats implementation is straightforward - Complete control over HTML output ### Negative - No TypeScript type checking - No hot module replacement (but Flask auto-reload works) - Manual CSS organization required - Must write responsive CSS manually ### Mitigation - Keep JavaScript minimal and well-commented - Organize CSS with clear sections - Use CSS custom properties for theming - Test manually in multiple browsers - Validate HTML with W3C validator ## Frontend File Structure ``` static/ ├── css/ │ └── style.css # Single stylesheet for entire site └── js/ └── preview.js # Optional markdown preview (admin only) templates/ ├── base.html # Base template with HTML structure ├── index.html # Homepage (note list) ├── note.html # Single note permalink └── admin/ ├── base.html # Admin base template ├── dashboard.html # Admin dashboard ├── new.html # Create new note └── edit.html # Edit existing note ``` ## CSS Architecture ### Custom CSS Properties (Variables) ```css :root { --color-text: #333; --color-bg: #fff; --color-link: #0066cc; --color-border: #ddd; --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --font-mono: 'SF Mono', Monaco, monospace; --spacing-unit: 1rem; --max-width: 42rem; } ``` ### Mobile-First Responsive Design ```css /* Base: Mobile styles */ body { padding: 1rem; } /* Tablet and up */ @media (min-width: 768px) { body { padding: 2rem; } } ``` ## JavaScript Architecture ### Markdown Preview Implementation ```javascript // static/js/preview.js // Simple markdown preview using marked.js CDN (no build step) // Progressive enhancement - form works without this ``` **Decision**: Use marked.js from CDN for client-side preview - **Justification**: Same library as server-side (consistency) - **Simplicity**: No bundling required - **Reliability**: CDN delivers cached version - **Alternative**: No preview (acceptable fallback) ## Template Organization ### Jinja2 Template Strategy - **Inheritance**: Use base templates for common structure - **Blocks**: Define clear content blocks for overriding - **Macros**: Create reusable microformat snippets - **Filters**: Use Jinja2 filters for date formatting ### Example Base Template Structure ```jinja2 {# templates/base.html #} {% block title %}{{ site.title }}{% endblock %} {% block head %}{% endblock %} {% block content %}{% endblock %} ``` ## Microformats Integration Server-side rendering makes microformats implementation straightforward: ```jinja2 {# Macro for h-entry note rendering #} {% macro render_note(note) %}
{{ note.content_html | safe }}
{% endmacro %} ``` ## Build and Development Workflow ### Development 1. Run Flask development server: `flask run` 2. Edit templates/CSS/JS directly 3. Browser auto-refresh on template changes 4. No build step required ### Production 1. Copy static files to production 2. Templates are rendered on-demand 3. Optionally enable Flask caching for rendered HTML 4. Serve static assets with nginx/Apache (optional) ## Browser Support - Modern browsers (Chrome 90+, Firefox 88+, Safari 14+, Edge 90+) - Mobile browsers (iOS Safari 14+, Chrome Android 90+) - Progressive enhancement ensures basic functionality on older browsers ## Alternatives Considered ### React/Vue/Svelte (Rejected) - **Simplicity**: 2/10 - Requires build tools, npm, bundlers - **Fitness**: 3/10 - Massive overkill for content site - **Maintenance**: 5/10 - Constant framework updates - **Verdict**: Violates "no client-side complexity" principle ### htmx (Considered) - **Simplicity**: 8/10 - Single JavaScript file, declarative - **Fitness**: 6/10 - Useful for dynamic updates, but not needed in V1 - **Maintenance**: 8/10 - Stable, minimal dependencies - **Verdict**: Interesting for V2, but V1 doesn't need dynamic updates ### Alpine.js (Considered) - **Simplicity**: 8/10 - Lightweight, declarative - **Fitness**: 5/10 - Good for small interactions, but we barely need any - **Maintenance**: 8/10 - Well maintained - **Verdict**: Too much for the minimal JS we need ### Tailwind CSS (Rejected) - **Simplicity**: 4/10 - Requires build process, large configuration - **Fitness**: 3/10 - Utility-first doesn't fit minimal design needs - **Maintenance**: 7/10 - Well maintained but heavy - **Verdict**: Build process violates simplicity; custom CSS is sufficient ### Bootstrap/Bulma (Rejected) - **Simplicity**: 5/10 - Large framework with many unused features - **Fitness**: 3/10 - Component-heavy, we need minimal custom design - **Maintenance**: 9/10 - Very stable - **Verdict**: Too much CSS for what we need ### PicoCSS/Water.css (Considered) - **Simplicity**: 9/10 - Classless CSS, just include and go - **Fitness**: 7/10 - Good starting point but may not match design vision - **Maintenance**: 8/10 - Maintained, simple - **Verdict**: Close consideration, but custom CSS gives full control ## Standards Compliance - Semantic HTML5 elements - Valid HTML (W3C validator) - Accessible forms and navigation - Proper heading hierarchy - ARIA labels where needed - Mobile-responsive (viewport meta tag) - Progressive enhancement (works without JS) ## References - Jinja2 Documentation: https://jinja.palletsprojects.com/ - MDN Web Docs: https://developer.mozilla.org/ - Microformats2: http://microformats.org/wiki/h-entry - Progressive Enhancement: https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement - Semantic HTML: https://developer.mozilla.org/en-US/docs/Glossary/Semantics