## Summary Closes #7. Raise public marketing page Lighthouse scores (Performance / Accessibility / Best Practices / SEO) on `/`, `/about/`, and `/contact/`. ### Baseline (preview, mobile) | Page | Perf | A11y | BP | SEO | |------|------|------|----|-----| | `/` | 70 | 80 | 82 | 100 | | `/about/` | 71 | 81 | 82 | 100 | | `/contact/` | 74 | 90 | 82 | 100 | ### Changes - **Accessibility:** contrast overrides, nav `aria-label`s, footer/contact heading order (no skipped levels). - **Best practices:** replace theme `unload` listeners with `pagehide` (also helps bfcache); `WHITENOISE_MAX_AGE` for hashed static. - **Performance:** WebP heroes/headshot/breadcrumbs + preload; Google Fonts `display=swap` + fewer weights; async icon `fonts.css`; bundled/minified vendor CSS; lazy second swiper slide; remove above-fold WOW delay on home hero. - **SEO:** already 100; kept structured data / meta. ### Local verify (dev server — no gzip, so Perf is not representative) A11y / Best Practices / SEO all **100** on the three pages after fixes. Perf will look better on beta/preview (WhiteNoise compression + CDN/proxy) than on `runserver`. Remaining Perf headroom is mostly the theme’s large `core.min.js` / unused CSS and infra HTTP/2. ## Test plan - [ ] Deploy/preview branch and re-run Lighthouse on `/`, `/about/`, `/contact/` - [ ] Spot-check home hero, about headshot, contact form + mobile nav toggles - [ ] Confirm icons still appear after async `fonts.css` load - [ ] Confirm swiper slide 2 background appears when navigating slides Reviewed-on: #8
monica_site
Django 6 marketing platform for Monica Dhillon / MKDRealtor.com — public site, realtor portal, multi-channel outreach (email + SMS via SMTP2GO, postcards via PCM Integrations), and social scheduling (Facebook / Instagram / LinkedIn) with Ollama-assisted drafting.
Stack
- Django 6 +
uv - Postgres (prod/beta); SQLite locally when
DATABASE_URLunset - dj-queue (Django Tasks backend, Postgres queue, no Redis/Celery)
- Docker; deploy via
server-infraAnsible pipeline
Environments
| Env | Domain | Port (host) | Gate |
|---|---|---|---|
| prod | mkdrealtor.com |
8004 | SITE_UNDER_CONSTRUCTION=true (holding page) |
| beta | monica-preview.aimloperations.com |
8014 | full app (SITE_UNDER_CONSTRUCTION=false) |
Local development
uv sync
cd site
uv run python manage.py migrate
uv run python manage.py runserver
# optional: docker compose up # web + postgres + worker (hot reload)
Docker compose mounts ./site into the container and runs Django runserver when
DJANGO_ENV=dev (the default). The worker service polls dispatch_due every 15s so
scheduled campaigns and social posts fire without a manual command. Edit Python/templates
→ auto-reload; no image rebuild.
Rebuild only when Dockerfile, entrypoint scripts, or deps (pyproject.toml, uv.lock) change:
docker compose up --build
Local secrets (SMTP2GO, etc.)
Copy .env.example → .env (gitignored). Compose reads .env for email vars.
cp .env.example .env
# fill EMAIL_HOST_USER / EMAIL_HOST_PASSWORD
# for real delivery (not console logs):
# EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
docker compose up
Without EMAIL_BACKEND=…smtp…, mail prints to the web container logs (console backend).
SMTP2GO delivery webhooks
See site/messaging/README.md for SMTP2GO email/SMS webhooks
and PCM Integrations postcard designer + webhook setup (Bearer auth, events).
Prod compose (docker-compose.prod.yml) still uses gunicorn with baked-in image code.
Secret env files (control node)
Create on the deploy host:
~/Documents/secrets/monica_site/monica_site_prod.env
~/Documents/secrets/monica_site/monica_site_beta.env
Templates: .env.prod.example (full var list). Validate with:
./scripts/validate-env.sh ~/Documents/secrets/monica_site/monica_site_prod.env
Deploy
CI on merge to main → tests → server-infra/scripts/deploy.sh --app monica_site --env prod --ref <sha>.
Start the dj-queue worker on exactly one host:
docker compose -f docker-compose.prod.yml --profile worker up -d
Apps
public · accounts · dashboard · leads · contacts · analytics · messaging · social
Social AI drafts: POST /portal/social/api/generate/ → Ollama at OLLAMA_BASE_URL (default http://10.0.0.128:11434).
See docs/monica-site-design.md for architecture.