8.8 KiB
8.8 KiB
ADR-003: Front-end Technology Stack
Status
Accepted
Context
StarPunk requires a front-end for:
- Public interface (homepage, note permalinks) - Server-side rendered
- Admin interface (note creation/editing) - Requires some interactivity
- 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)
: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
/* Base: Mobile styles */
body { padding: 1rem; }
/* Tablet and up */
@media (min-width: 768px) {
body { padding: 2rem; }
}
JavaScript Architecture
Markdown Preview Implementation
// 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
{# templates/base.html #}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{{ site.title }}{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<link rel="alternate" type="application/rss+xml" href="{{ url_for('feed') }}">
{% block head %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
Microformats Integration
Server-side rendering makes microformats implementation straightforward:
{# Macro for h-entry note rendering #}
{% macro render_note(note) %}
<article class="h-entry">
<div class="e-content">
{{ note.content_html | safe }}
</div>
<footer>
<a class="u-url" href="{{ url_for('note', slug=note.slug) }}">
<time class="dt-published" datetime="{{ note.created_at.isoformat() }}">
{{ note.created_at.strftime('%B %d, %Y') }}
</time>
</a>
</footer>
</article>
{% endmacro %}
Build and Development Workflow
Development
- Run Flask development server:
flask run - Edit templates/CSS/JS directly
- Browser auto-refresh on template changes
- No build step required
Production
- Copy static files to production
- Templates are rendered on-demand
- Optionally enable Flask caching for rendered HTML
- 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