Add Django site, Docker packaging, and beta/prod Gitea deploys.
Deploy Beta / unit-tests (push) Successful in 9s
Deploy Beta / docker (push) Successful in 17s
Deploy Beta / deploy-beta (push) Successful in 2m31s

Unignore site/ (was blocked by mkdocs /site rule), add compose/Docker/uv tooling, and split deploys so push to main goes to beta while prod stays manual.
This commit is contained in:
2026-08-08 07:32:55 -05:00
parent 7dca98bbf6
commit 1f7d78de64
204 changed files with 21662 additions and 70 deletions
@@ -0,0 +1,124 @@
{% extends "portal_base.html" %}
{% block title %}Analytics · Portal{% endblock %}
{% block topbar_title %}Analytics{% endblock %}
{% block portal_content %}
<div class="stat-row">
<div class="stat-card">
<div class="label">Views (last 30 days)</div>
<div class="value">{{ visits_last_30_days }}</div>
</div>
<div class="stat-card">
<div class="label">UTM landings</div>
<div class="value">{{ total_visits }}</div>
</div>
<div class="stat-card">
<div class="label">Attributed leads</div>
<div class="value">{{ total_attributed }}</div>
</div>
<div class="stat-card">
<div class="label">Top source</div>
<div class="value" style="font-size:18px">{{ top_source|default:"—" }}</div>
</div>
<div class="stat-card">
<div class="label">Top campaign</div>
<div class="value" style="font-size:18px">{{ top_campaign|default:"—" }}</div>
</div>
</div>
<div class="panel">
<div class="panel-h"><h2>Landing volume by source</h2></div>
<div class="panel-b">
<div class="chart-placeholder">
{% for row in visits_by_source|slice:":8" %}
<div class="bar" style="height:{{ row.bar_pct }}%" title="{{ row.utm_source|default:'(direct)' }}: {{ row.count }}"></div>
{% empty %}
<div class="bar" style="height:12%"></div>
{% endfor %}
</div>
</div>
</div>
<div class="panel">
<div class="panel-h"><h2>UTM landings</h2><span class="muted" style="font-size:12px">From ?utm_* hits</span></div>
<div class="panel-b" style="padding:0">
<table class="table">
<thead>
<tr>
<th>Source</th>
<th>Medium</th>
<th>Campaign</th>
<th>Landings</th>
</tr>
</thead>
<tbody>
{% for row in visits_by_combo %}
<tr>
<td>{{ row.utm_source|default:"(direct)" }}</td>
<td>{{ row.utm_medium|default:"—" }}</td>
<td>{{ row.utm_campaign|default:"—" }}</td>
<td>{{ row.count }}</td>
</tr>
{% empty %}
<tr><td colspan="4" class="empty-state">No UTM landings yet. Open a public URL with ?utm_source=…</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="panel">
<div class="panel-h"><h2>Recent landings</h2></div>
<div class="panel-b" style="padding:0">
<table class="table">
<thead>
<tr>
<th>When</th>
<th>Path</th>
<th>Source</th>
<th>Campaign</th>
</tr>
</thead>
<tbody>
{% for visit in recent_visits %}
<tr>
<td>{{ visit.created_at|date:"M j, g:i A" }}</td>
<td>{{ visit.path }}</td>
<td>{{ visit.utm_source|default:"—" }}</td>
<td>{{ visit.utm_campaign|default:"—" }}</td>
</tr>
{% empty %}
<tr><td colspan="4" class="empty-state">No visits recorded.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="panel">
<div class="panel-h"><h2>Lead attribution</h2><span class="muted" style="font-size:12px">After contact-form submit</span></div>
<div class="panel-b" style="padding:0">
<table class="table">
<thead>
<tr>
<th>Source</th>
<th>Medium</th>
<th>Campaign</th>
<th>Leads</th>
</tr>
</thead>
<tbody>
{% for row in leads_by_combo %}
<tr>
<td>{{ row.utm_source|default:"(direct)" }}</td>
<td>{{ row.utm_medium|default:"—" }}</td>
<td>{{ row.utm_campaign|default:"—" }}</td>
<td>{{ row.count }}</td>
</tr>
{% empty %}
<tr><td colspan="4" class="empty-state">No attributed leads yet — submit the contact form after a UTM landing.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}