8.0 KB
raw
{% extends 'base.html' %}
{% block extra_head %}
{% include "includes/social.html" %}
{% endblock %}
{% block extra_css %}
<link href="{{ vite_asset('static_src/pages/index.js', 'css') }}" rel="stylesheet">
{% endblock %}
{% block breadcrumbs %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="/">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">{{ page.title }}</li>
</ol>
</nav>
{% endblock %}
{% block main %}
<div class="container my-5">
<div class="row">
<div class="col-lg-8 offset-lg-2">
<div class="section-label mb-2">release log</div>
<h1 class="fw-bolder text-white" style="letter-spacing: -0.01em;">{{ page.title }}</h1>
<p class="text-muted">Shipped changes, schema tweaks, and the occasional tease for something coming.</p>
</div>
</div>
<div class="row mt-4">
<div class="col-lg-8 offset-lg-2">
<div class="changelog-entry">
<div class="changelog-date">2026-05-09</div>
<ul>
<li>Replace the dashboard PDF pipeline with the embedded Typst compiler (<code>typst</code> + <code>typst-pdf</code> + <code>typst-kit</code>). No chromium subprocess, no temp files; fonts are searched once at startup and shared across renders</li>
<li>Restructure the axum server into per-feature route modules under <code>src/routes/</code>, with <code>AppState</code>/router assembly split into <code>src/app.rs</code> and the standard render context centralized in <code>src/render.rs</code></li>
<li>Fix several dashboard issues exposed by the restructure (404 handling, breadcrumb edge cases)</li>
<li>Expand <code>make clean</code> to wipe <code>target/</code>, frontend deps, runtime data, and the cached topojson</li>
<li>Fix the mobile nav menu being clipped by the fixed navbar height</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2026-05-07</div>
<ul>
<li>Rewrite the entire backend from Django to a single statically-linked axum binary in Rust. sqlx + SQLite directly, minijinja for templates, no more Gunicorn or Uvicorn or separate scheduler process. The collector endpoint and embed snippet are unchanged, so existing tracked sites keep reporting without edits</li>
<li>Drop the multi-user accounts model. Auth is now a single operator password from <code>.env</code> with signed-cookie sessions and <code>SameSite=Strict</code> instead of CSRF tokens</li>
<li>Route bot traffic into a dedicated <code>bot_events</code> table at write time so human dashboard queries never have to filter it</li>
<li>Auto-download the GeoIP database and ua-parser regexes on boot when missing or stale. The server still boots and serves dashboards if either download fails</li>
<li>Add an <code>analytics migrate</code> subcommand that imports an existing Django SQLite into the new schema while preserving property UUIDs, so embedded snippets keep working after the cutover</li>
<li>Add an in-memory dashboard cache (5-minute TTL, keyed by property + date range + filter), bypassed for PDF and markdown exports so they always reflect the live data</li>
<li>Add a stable <code>/static/collector.js</code> route so embed snippets don't break when Vite re-hashes the collector bundle</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2026-04-29</div>
<ul>
<li>Replace the dashboard PDF report with a toner-friendly print template</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2026-04-26</div>
<ul>
<li>Swap the US-only datamap for a Natural Earth world map with admin-1 drill-down on click</li>
<li>Switch IP geolocation from MaxMind to DB-IP City Lite (CC-BY-4.0, no signup, monthly auto-refresh)</li>
<li>Drop SQLite <code>mmap_size</code> to avoid a multi-process corruption hazard</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2026-04-18</div>
<ul>
<li>Replace the Playwright PDF pipeline with a headless Chromium subprocess wrapper and move the Docker base image to Alpine: smaller image, faster cold starts</li>
<li>Centralize SQLite settings and expand PRAGMA tuning (WAL, synchronous, cache, mmap, temp_store)</li>
<li>Speed up the property dashboard, split the property view, and surface bot traffic separately</li>
<li>Swap the Exim relay for a Python direct-to-MX email backend</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2026-04-17</div>
<ul>
<li>Redesign the whole dashboard with a warm-earth palette: mossy forest green and amber on deep charcoal, Monaspace Argon throughout, aligned to the <a href="https://status.bythewood.me/">status</a> app</li>
<li>Rework the property dashboard with metric tiles, period-over-period deltas, chart panels, and compact ranked top-lists instead of Bootstrap list groups</li>
<li>Rework the properties listing page with search, live-signal tiles, and a dense row layout</li>
<li>Swap the bar-chart emoji favicon for a themed SVG mark matching the in-app logo</li>
<li>Add a <code>/documentation</code> link into the main nav so the collector snippet docs are easier to find</li>
<li>Restyle the collector-tag modal and accordion docs as terminal-style code blocks</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2025-10-04</div>
<ul>
<li>Swap browser automation to Playwright with the bundled Chromium runtime</li>
<li>Switch Docker base image to Ubuntu 24.04 LTS</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2025-10-03</div>
<ul>
<li>Migrate Python package management from Pipenv/pyenv to <code>uv</code></li>
<li>Switch frontend build from Yarn + Webpack to Bun + Vite</li>
<li>Fix d3/datamaps strict-mode crash under ESM so the US-state map renders again</li>
<li>Fix logout 405 by switching to a POST form + CSRF (Django 5 <code>LogoutView</code> is POST-only)</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2022-07-26</div>
<ul>
<li>Add URL property filtering: click any top-page row to scope the whole dashboard</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2022-07-06</div>
<ul>
<li>Change IPInfo to local MaxMind DB for IP → geo lookup (no more third-party API)</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2022-06-18</div>
<ul>
<li>Rename all "tracking" terminology to "collecting" (we're not spyware)</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2022-06-05</div>
<ul>
<li>Add PDF report generator: hit <code>?report</code> on any property page to export</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2022-05-28</div>
<ul>
<li>Add headless Chromium screenshot utility</li>
<li>Add Open Graph / Twitter card metadata</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-date">2022-05-22</div>
<ul>
<li>Add previous-period comparisons on every metric card</li>
<li>Add a shareable public-link toggle for property pages</li>
<li>Add UTM query-param collection (source, medium, campaign)</li>
<li>Add platform doughnut graph</li>
<li>Add date-range selection with presets and a custom picker</li>
<li>Add custom event cards: pin any custom event as a headline metric</li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}