diff --git a/README.md b/README.md index a3e3620..58f31f5 100644 --- a/README.md +++ b/README.md @@ -1,320 +1,93 @@ -# TufteCMS +# kennethreitz.org -A Flask-based content management system designed for thoughtful writing, inspired by Edward Tufte's design principles. Built for digital gardens, essay collections, and content-rich websites that prioritize readability and deep engagement. +Kenneth Reitz's personal website and digital garden. A living exploration of how technology can serve human consciousness rather than exploit it. -> **Note**: This repository is a hybrid containing both the TufteCMS framework (in `tuftecms/`) and Kenneth Reitz's personal website content (in `data/`). The CMS powers kennethreitz.org and serves as a living example of the system in production. +Built with [Responder](https://github.com/kennethreitz/responder), powered by markdown content, deployed on [Fly.io](https://fly.io). ## Quick Start -### Option 1: Docker Compose (Recommended) - -The easiest way to get started with all dependencies included: - ```bash -# Clone the repository -git clone https://github.com/kennethreitz/tuftecms.git -cd tuftecms - -# Start with Docker Compose -docker compose up -``` - -The site will be available at `http://localhost:8000` with hot-reloading enabled. All dependencies, including PDF generation, are pre-configured. - -### Option 2: Local Development with uv - -For local development without Docker: - -```bash -# Clone the repository -git clone https://github.com/kennethreitz/tuftecms.git -cd tuftecms - -# Install dependencies with uv (recommended) +# Install dependencies uv sync # Run development server uv run python engine.py ``` -The site will be available at `http://localhost:8000` - -**Note**: PDF generation requires additional system libraries (see below). The site works fully without them - PDFs just won't be available. - -### Installing uv - -If you don't have `uv` installed: - -```bash -# macOS/Linux -curl -LsSf https://astral.sh/uv/install.sh | sh - -# Windows -powershell -c "irm https://astral.sh/uv/install.ps1 | iex" - -# Or via pip -pip install uv -``` - -## Philosophy - -TufteCMS embraces **human-first design** - content presentation that serves readers' mental models rather than forcing adaptation to machine logic. It provides powerful features like sidenotes, content indexing, and cross-referencing while maintaining simplicity and elegance. - -## Features - -### Content & Typography -- **Tufte-style sidenotes** - Margin commentary without disrupting reading flow -- **Responsive typography** - Optimized for reading across all devices -- **Markdown rendering** - Custom Mistune renderer with philosophical code blocks -- **File-based content** - Simple directory structure mirrors URL routing - -### Discovery & Navigation -- **Full-text search** - Relevance-scored search with contextual snippets -- **Content indexes** - Automatic extraction of sidenotes, quotes, outlines, connections, terms -- **Cross-referencing** - Track incoming/outgoing links between content -- **Theme detection** - Automatic categorization by content patterns -- **HTML & XML sitemaps** - Both human and machine-readable navigation - -### Visual Identity -- **Generated SVG icons** - Unique algorithmic icons for every piece of content -- **Deterministic design** - Same title always produces the same icon -- **Dynamic folder icons** - Color variations based on content titles -- **Reading progress** - Visual indicator for longer essays - -### Performance -- **Intelligent caching** - LRU caches for blog posts, indexes, and metadata -- **Background cache warming** - Async startup loading for instant response -- **Lazy loading** - Images load via IntersectionObserver -- **HTTP caching headers** - Aggressive caching for static assets -- **Cache debugging** - API endpoint to monitor cache performance - -### Developer Experience -- **Flask blueprints** - Modular architecture with clear separation -- **API endpoints** - JSON APIs for search, icons, and debugging -- **RSS/Atom feeds** - Standard feed formats for syndication -- **Template system** - Jinja2 templates with extensible blocks - -## PDF Generation Setup (Optional) - -TufteCMS includes server-side PDF generation using WeasyPrint. This requires system libraries: - -**macOS (via Homebrew):** -```bash -brew install cairo pango gdk-pixbuf libffi -``` - -**Ubuntu/Debian:** -```bash -sudo apt-get install libcairo2 libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info -``` - -**Docker:** -The provided Dockerfile includes these dependencies automatically. - -**Note:** If you skip this step, the site will work fine but `.pdf` URLs will not function. All other features work without these libraries. - -## Project Structure - -``` -tuftecms/ -├── tuftecms/ -│ ├── app.py # Application factory -│ ├── config.py # Configuration management -│ ├── blueprints/ # Route handlers -│ │ ├── main.py # Homepage and core routes -│ │ ├── content.py # Content rendering -│ │ ├── api.py # JSON API endpoints -│ │ └── feeds.py # RSS/sitemap generation -│ ├── core/ # Core functionality -│ │ ├── cache.py # Caching system -│ │ ├── content.py # Content processing -│ │ └── markdown.py # Markdown rendering -│ ├── utils/ # Utilities -│ │ ├── content.py # Content helpers -│ │ └── svg_icons.py # Icon generation -│ ├── templates/ # Jinja2 templates -│ └── static/ # CSS, images, fonts -├── data/ # Content directory -│ └── essays/ # Your content here -├── engine.py # Development server -└── pyproject.toml # Dependencies -``` - -## Content Organization - -### Directory Structure - -Content is organized in a simple directory structure under `data/`: - -``` -data/ -├── essays/ -│ ├── 2025-01-15-example-essay.md -│ └── 2025-02-20-another-essay.md -├── notes/ -└── index.md -``` - -URL paths mirror the file system: `/essays/2025-01-15-example-essay` - -### Writing with Sidenotes - -Sidenotes provide commentary without disrupting reading flow: - -```markdown -This is the main text.This is a sidenote that adds depth without breaking the narrative. The text continues naturally. -``` - -**Critical formatting rules:** -- Sidenotes must be inline (attached to sentence end with NO line breaks) -- Use descriptive IDs like `sn-consciousness`, `sn-recursion` -- Keep away from code blocks to prevent layout issues - -### Markdown Features - -```markdown -# Essay Title - -*Published: January 2025* - -Standard markdown with [links](/other-essay) and **emphasis**. - -Code blocks with philosophy: - -\`\`\`python -def consciousness(): - # TODO: Model the unmappable - pass -\`\`\` - -> Blockquotes for memorable passages -``` - -## Configuration - -Edit `tuftecms/config.py`: - -```python -class Config: - DISABLE_ANALYTICS = True # Privacy-first by default - SEARCH_CACHE_TIMEOUT = 60 - DATA_DIR = "data" - MIN_SEARCH_QUERY_LENGTH = 2 - MAX_SEARCH_RESULTS = 50 -``` - -## API Endpoints - -### Search -``` -GET /api/search?q=query -``` - -Returns JSON with relevance-scored results, snippets, and match locations. - -### Cache Debugging -``` -GET /api/debug-cache -``` - -Returns cache statistics and LRU cache performance metrics. - -### Icon Generation -``` -GET /api/icon/ -``` - -Returns generated SVG icon data for any content path. - -## Content Indexes - -TufteCMS automatically builds indexes: - -- **Sidenotes** - All margin notes with context -- **Outlines** - Heading structure across content -- **Quotes** - Blockquoted passages -- **Connections** - Internal link graph -- **Terms** - Key terms appearing across multiple articles -- **Themes** - Pattern-based content categorization - -Access via routes: `/sidenotes`, `/outlines`, `/quotes`, `/connections`, `/terms` - -## Deployment +The site will be available at `http://localhost:8000`. ### Docker ```bash -docker build -t tuftecms . -docker run -p 8000:8000 tuftecms +docker compose up ``` -### Production with Gunicorn +## Architecture + +This is a single-file Responder application (`engine.py`) serving markdown content from `data/`. + +``` +kennethreitz.org/ +├── engine.py # The whole application +├── data/ # All content (markdown) +│ ├── essays/ # 250+ essays (2008-2026) +│ ├── software/ # Project pages +│ ├── themes/ # Thematic collections +│ ├── artificial-intelligence/ +│ ├── poetry/ +│ ├── photography/ +│ ├── music/ +│ └── *.md # Standalone pages +├── tuftecms/ +│ ├── templates/ # Jinja2 templates +│ ├── static/ # CSS, fonts, images +│ ├── core/ # Cache, markdown rendering +│ └── utils/ # Content helpers, SVG icons +├── Dockerfile +├── fly.toml # Fly.io deployment config +└── pyproject.toml +``` + +URL paths mirror the filesystem: `data/essays/2025-08-26-example.md` → `/essays/2025-08-26-example` + +## Features + +- **Tufte-style sidenotes** — margin commentary without disrupting flow. +- **Full-site search** — cached index built at startup, server-side autocomplete. +- **Content indexes** — automatic extraction of sidenotes, quotes, outlines, connections, terms, themes. +- **Legacy URL redirects** — intelligent matching for old URL patterns (301 permanent). +- **Bot detection** — logs scraper activity with User-Agent identification. +- **Structured logging** — request-scoped context (ID, method, path, client IP) on every log line. +- **PDF generation** — server-side via WeasyPrint. +- **Generated SVG icons** — unique algorithmic icons for every piece of content. +- **RSS feed** — at `/feed.xml`. +- **Knowledge graph** — interactive D3 visualization of content connections. +- **Dark mode** — system-preference and manual toggle. + +## API Endpoints + +``` +GET /api/search?q=query # Full-site search with scoring +GET /api/search/autocomplete?q=q # Title-based autocomplete (8 results) +GET /api/blog # Essay listing +GET /api/themes # Theme listing with icons +GET /api/directory-tree # Site directory structure +GET /api/icon/ # Generated SVG icon +GET /api/cache-stats # Cache performance metrics +``` + +## Deployment + +Deployed on Fly.io with 2 shared CPUs, 2GB RAM, 2 uvicorn workers. ```bash -uv run gunicorn -w 4 -b 0.0.0.0:8000 'tuftecms.app:create_app()' +fly deploy ``` -### Environment Variables +## Content -```bash -DISABLE_ANALYTICS=true # Disable analytics -DEBUG=1 # Enable debug mode -``` - -## Development - -### Debug Mode - -```bash -DEBUG=1 uv run python engine.py -``` - -Enables verbose logging and development features. - -### Cache Management - -Clear all caches: - -```python -from tuftecms.core.cache import clear_all_caches -clear_all_caches() -``` - -### Adding New Features - -1. Create new blueprint in `tuftecms/blueprints/` -2. Register in `app.py` -3. Add templates to `tuftecms/templates/` -4. Update cache logic if needed in `core/cache.py` - -## Philosophy & Design - -TufteCMS is built on principles of **contemplative pragmatism**: - -- **Human-first design** - Optimize for people having difficult days -- **Simple over clever** - Tools should feel natural to use -- **Content-focused** - Design serves the writing, not the ego -- **Respectful reading** - No dark patterns, no engagement manipulation -- **Open and inspectable** - Clean code, clear architecture - -The name honors Edward Tufte's work on information design - presenting complex information with clarity and respect for the reader's intelligence. - -## Use Cases - -- **Digital gardens** - Personal knowledge bases that grow organically -- **Essay collections** - Long-form writing with depth and cross-references -- **Academic writing** - Papers with extensive sidenotes and citations -- **Documentation sites** - Technical docs with commentary -- **Philosophy blogs** - Contemplative writing with layered meaning +The `data/` directory contains 15+ years of writing — essays, software documentation, poetry, photography, AI explorations, and personal pages. Content is plain markdown with optional YAML frontmatter and Tufte-style HTML sidenotes. ## License -MIT License - see LICENSE file for details. - -## Credits - -Created by Kenneth Reitz as part of kennethreitz.org. Built with Flask, Mistune, and care for human consciousness. - ---- - -*"Technology should serve human mental models, not force humans to adapt to machine logic."* \ No newline at end of file +MIT