Files
web_django_template/README.md
T
westfarn 97b8607bf2 Add campaign UTM links and piha.li shortener (#4)
## Summary
- Port Monica campaign UTM + piha.li minting into always-on `core` (`shortener.py`, `campaign_utm.py`) so `email_sms` and `directmail` stay optional and never import each other.
- `utm_source` is a slug of `SITE_NAME` (override with `UTM_SOURCE`). Email gets an HTML `data-campaign-utm` link; SMS gets a plain URL; postcard QR only — no body inject.
- Live composer mints through login+CSRF `POST /portal/campaigns/short-link/` (registered only when an outreach app is installed). Empty `SHORTENER_*` falls back to the long UTM URL.

Reference: [monica_site PR #10](ai_ml_operations/monica_site#10)

Closes #3

## Test plan
- [x] `cd site && uv run python manage.py test` (125 tests)
- [ ] Email composer: type a name, confirm HTML link + `utm_campaign` updates, save draft
- [ ] SMS composer: plain `piha.li` (or long UTM if shortener unset) in the body
- [ ] Postcard composer: QR copies the tracked URL; campaign body has no `utm_source`
- [ ] Campaign report pages show the same panel
- [ ] With `FEATURE_EMAIL_SMS` and `FEATURE_DIRECT_MAIL` off, no extra nav and no `/portal/campaigns/short-link/` route

Reviewed-on: #4
2026-09-01 13:36:01 -07:00

2.9 KiB

web_django_template

Gitea template for AI ML Operations client websites (Web Design & Hosting).

Clone this repo (or Use this template), run scripts/bootstrap-client.sh, set branding + FEATURE_* flags in the secret env file, deploy.

Always included: public site (landing, about, contact) and client portal (login, dashboard, leads, UTM analytics). Optional catalog add-ons are separate Django apps. A flag that is off keeps the app out of INSTALLED_APPS — no models, admin, URLs, or portal nav.

Catalog → flags

Catalog item Flag App
Public site (always on) public
Client portal + UTM (always on) accounts, dashboard, leads, analytics, contacts, core
Email & SMS FEATURE_EMAIL_SMS email_sms
Direct mail (PCM) FEATURE_DIRECT_MAIL directmail
Blog FEATURE_BLOG blog
Payments (Stripe) FEATURE_PAYMENTS payments (requires email/SMS)
Social consolidation FEATURE_SOCIAL social
AI social generator FEATURE_SOCIAL_AI social_ai (requires social)

New client

# 1. Create repo from this Gitea template, clone it.
# 2. Rename package + branding placeholders:
./scripts/bootstrap-client.sh acme_site "Acme HVAC" acmehvac.com

# 3. Brand public templates and static/brand/ (logo, colors, copy).

# 4. Secrets on the control node:
mkdir -p ~/Documents/secrets/acme_site
cp .env.prod.example ~/Documents/secrets/acme_site/acme_site_prod.env
# Flip only purchased FEATURE_* flags. Fill provider secrets.
./scripts/validate-env.sh ~/Documents/secrets/acme_site/acme_site_prod.env

# 5. Infra: Postgres on 10.0.0.230, server-infra app_catalog, NPM, CI.
# 6. Deploy. Create a portal user (createsuperuser).

Local:

cp .env.example .env
uv sync
cd site
uv run python manage.py migrate
uv run python manage.py runserver
# or: docker compose up

Stack

Django 6 + uv · Postgres (prod/beta); SQLite locally · dj-queue · Docker · server-infra Ansible deploy.

Ollama for social drafts lives on the LAN at http://10.0.0.128:11434. Do not call a public Ollama host.

When FEATURE_EMAIL_SMS or FEATURE_DIRECT_MAIL is on, composers auto-insert a homepage URL with utm_source (slug of SITE_NAME, or UTM_SOURCE), utm_medium = channel, and utm_campaign = campaign name. Configured SHORTENER_BASE_URL + SHORTENER_API_TOKEN mint that URL via url_shortening_service and put piha.li / beta.piha.li short links in SMS, email hrefs, and postcard QR codes.

Caller secrets (this repo's env file):

SHORTENER_BASE_URL=https://shortener.aimloperations.com
SHORTENER_API_TOKEN=<slug>:<secret>

Operator secrets (url_shortening_service_*): SHORTENER_API_TOKENS=<slug>:<same-secret> and SHORT_ALLOWED_HOSTS must include the client domain. Mint against the API host, never piha.li.