# Legal Templates — Live Deployment Playbook

**Generated:** 2026-06-02 21:39 UTC
**Goal:** Ship the v2 legal templates to live sites without breaking design.
**Status:** Plan only. No production deployments until Ola reviews and merges PRs.

---

## 0. Why this is non-trivial

The 7 live sites have **radically different** design systems, routing, and footer patterns. A blanket "copy template here" approach would either:
- Render a generic page that looks bolted on (breaks visual trust)
- Override the site's existing design tokens (breaks layout)
- Conflict with the site's existing routing (404s / wildcards)

So: every site gets an **adapted** version of the template, not a copy.

The audit (2026-06-02 21:30 UTC) confirms:

| Site | Stack | Footer | Colors | Existing legal | Risk |
|---|---|---|---|---|---|
| agenticinfluencer.agency | React/Vite + CF Pages | Inline (not in `<footer>` tag) | dark, no clear brand color | NONE | high — first legal page |
| catchup.help | Next.js | Pixel retro, dense | `#670f02` rust, orange/red | NONE | low — already has /docs, /blog, /pricing structure |
| lovkode.no | Worker (Hono-like) | JS-rendered, no `<footer>` tag in raw HTML | dark editorial `#0f0e0d` + cream `#faf9f6` | NONE | medium — JS-rendered footer makes it hard to add a link without rebuilding |
| samsvarlig.no | Cloudflare Worker (D1+R2+Queues) | App-rendered | unknown (worker page is app shell) | NONE | medium — worker app has its own legal page slot already, see /api/health |
| styr.ing | Astro | No `<footer>` in raw HTML | emerald `#065f46` + cream `#f6f2ea` + gold `#fbbf24` | mentions DPA in body | low — clean Astro project, design tokens obvious |
| turmo.dev | Static HTML (CF Pages) | Custom dark editorial | `#070707` near-black | NONE | low — static site, easy to add page |

**kurs.ing is EXCLUDED from this rollout** per Ola's note 2026-06-02 21:32 UTC.

**AgentOnboard.ing is EXCLUDED** because the canonical .ing TLD isn't registered. The marketing site is at `agentonboard-ing.pages.dev` and could be deployed there, but the legal-pack templates are also marketing-facing — defer until canonical domain is bound.

---

## 1. Core principles

**P1 — Never auto-deploy to production.** Every change goes via a draft PR. Ola reviews, Ola merges.
**P2 — Match the site's design tokens, don't override them.** Use the same fonts, colors, spacing rhythm.
**P3 — Use the site's existing routing convention.** If the site uses `/personvern`, use `/personvern` — don't force `/privacy`. Match trailing slashes.
**P4 — Keep the legal-pack on legal-pack.pages.dev as the source of truth.** Live sites get a thin reference link, not a copy.
**P5 — Footer link is the only required integration point.** Everything else is a separate page.
**P6 — Mobile-first.** A surprising number of legal pages are read on phones.
**P7 — Don't break the design system.** If the site uses a CSS framework (Tailwind, vanilla CSS, inline styles), use the same.

---

## 2. Per-site adaptation rules

### agenticinfluencer.agency
- **Stack:** React + Vite + Cloudflare Pages (per repo layout)
- **Source path:** likely `index.html` at root + components in `src/` or root
- **Color scheme:** dark luxury (no clear brand color in audit — need to inspect further)
- **Routing:** SPA — use `src/pages/Privacy.tsx` or `src/pages/privacy.astro` (whichever matches)
- **Footer:** inline, not in `<footer>` tag — need to find the actual footer element
- **Language:** English
- **Path:** `/privacy` (matches marketing-style "agency" feel; no `/personvern`)
- **Integration steps:**
  1. Clone `Ola-Turmo/AgenticInfluencer.agency` to a fresh dir
  2. Locate the footer component and the existing `<a>` patterns
  3. Add `<a href="/privacy">Privacy</a> · <a href="/terms">Terms</a>` matching the footer style
  4. Add the page files (use the legal-pack template as the source, replace colors with site tokens)
  5. Open a PR with title "Add /privacy, /terms, /dpa, /cookies pages (legal v2.0)"
  6. Wait for Ola to review

### catchup.help
- **Stack:** Next.js
- **Source path:** `app/privacy/page.tsx` (or `pages/privacy.tsx` if older Next.js)
- **Color scheme:** pixel retro, `#670f02` rust base
- **Routing:** Next.js file-based — files in `app/` (App Router) or `pages/` (Pages Router)
- **Footer:** proper `<footer>` tag, dense list
- **Language:** English
- **Path:** `/privacy`, `/terms` (matches the existing `/docs`, `/blog`, `/pricing` pattern)
- **Integration steps:**
  1. Clone `Ola-Turmo/CatchUp.help`, check `package.json` for Next.js version + router type
  2. Add `app/privacy/page.tsx` etc. using the legal template, wrapped in the site's layout (`<Layout>` import)
  3. Match typography: pixel font, monospace headers, `#670f02` accent
  4. Add footer links: `Privacy · Terms · DPA · Cookies`
  5. PR with same title convention

### lovkode.no
- **Stack:** Cloudflare Worker (Hono or similar — needs to check)
- **Color scheme:** editorial dark `#0f0e0d` + cream `#faf9f6` + grey `#afaeac`
- **Routing:** Worker has its own router — need to add routes like `/personvern`, `/vilkar`
- **Footer:** JS-rendered, hard to add link without rebuild
- **Language:** Norwegian
- **Path:** `/personvern`, `/vilkar` (Norwegian terms, matches the site's Norwegian-first positioning)
- **Integration steps:**
  1. Clone `Ola-Turmo/lovkode.no`, find the router file
  2. Add two new routes: `/personvern` and `/vilkar`
  3. Return HTML wrapped in the site's template (locate the layout function)
  4. Add a footer link in the worker-rendered HTML
  5. PR with Norwegian title: "Legg til /personvern og /vilkar (juridisk v2.0)"

### samsvarlig.no
- **Stack:** Cloudflare Worker + D1 + R2 + Queues
- **Color scheme:** likely the standard "norsk compliance" green (need to inspect)
- **Routing:** Worker has its own router — likely has `/api/*` and a frontend
- **Footer:** app-rendered
- **Language:** Norwegian
- **Path:** `/personvern`, `/vilkar`
- **Integration steps:**
  1. Clone `Ola-Turmo/samsvarlig.no/apps/web`
  2. Find the route handler for HTML pages (likely in `src/worker/index.ts`)
  3. Add two new routes: `/personvern` and `/vilkar`
  4. Use the existing HTML template pattern
  5. Add footer link
  6. PR with Norwegian title

### styr.ing
- **Stack:** Astro (5 confirmed from layout)
- **Color scheme:** emerald `#065f46` primary, gold `#fbbf24` accent, cream `#f6f2ea` background
- **Routing:** Astro file-based — `src/pages/personvern.astro` etc.
- **Footer:** no `<footer>` tag in raw HTML (Astro likely renders it client-side) — find the Layout component
- **Language:** Norwegian
- **Path:** `/personvern`, `/vilkar`
- **Integration steps:**
  1. Clone `Ola-Turmo/styr-ing-product`
  2. Find `src/layouts/Base.astro` or similar
  3. Add `src/pages/personvern.astro` and `src/pages/vilkar.astro` using the Layout wrapper
  4. In the layout, add `<a href="/personvern">Personvern</a> · <a href="/vilkar">Vilkår</a>` to the footer
  5. Use the v2 templates with the site's design tokens: emerald CTA buttons, cream background
  6. PR

### turmo.dev
- **Stack:** Static HTML (CF Pages)
- **Color scheme:** editorial dark `#070707`
- **Routing:** file-based — just add HTML files
- **Footer:** custom dark editorial, has links but no legal
- **Language:** English
- **Path:** `/privacy.html`, `/terms.html` (matches the static HTML style)
- **Integration steps:**
  1. Clone `Ola-Turmo/turmo-dev-site`
  2. Drop `privacy.html`, `terms.html`, `dpa.html`, `cookies.html` at root
  3. Add footer links to the existing `index.html`
  4. Match the dark editorial style — black bg, white text, minimal Tailwind
  5. PR

---

## 3. Common scaffold: a "design-safe" wrapper

Every site gets a wrapper that pulls the design tokens from the host site:

```astro
---
// Example for Astro sites (styr.ing, turmo.dev)
import BaseLayout from '../layouts/Base.astro';
---
<BaseLayout title="Personvern" description="...">
  <article class="prose prose-emerald max-w-3xl mx-auto py-12">
    {/* Paste the legal-pack template content here, with {COMPANY_NAME} substituted */}
  </article>
</BaseLayout>
```

For Next.js:

```tsx
// app/privacy/page.tsx
import Layout from '@/components/Layout';

export default function PrivacyPage() {
  return (
    <Layout title="Privacy" description="...">
      <article className="prose max-w-3xl mx-auto py-12">
        {/* Template content */}
      </article>
    </Layout>
  );
}
```

For Workers (samsvarlig, lovkode): add a route handler that returns HTML using the existing layout function.

---

## 4. Source-of-truth pattern

The legal-pack on `https://legal-pack.pages.dev/` stays as the canonical reference. The live sites just *link* to it as a fallback:

```html
<p>This policy is hosted on our marketing site at <a href="https://legal-pack.pages.dev/per-company/agenticinfluencer.agency/privacy.html">legal-pack.pages.dev</a> and is incorporated by reference into this site's terms.</p>
```

That way:
- If the live site's legal page goes stale, the legal-pack has the current version
- The legal-pack is a single source for Ola to edit + redeploy
- Legal pages on the live site can be lightweight "this site uses [policy X]" pages that link out

This is a SaaS best practice (Vercel, Stripe do this for archived policies).

---

## 5. Step-by-step execution plan

### Phase 1: Discovery (1-2 hours)
1. Clone each of the 6 repos (skip kurs.ing + AgentOnboard.ing)
2. For each, find the actual footer location, color tokens, and routing convention
3. Document any site that has unusual patterns (e.g., iframe-embedded, third-party CMS)
4. **Deliverable:** A `DEPLOYMENT_PLAN_<site>.md` per site with the exact files to create, the footer link to add, and the design tokens to use

### Phase 2: Generate per-site pages (2-3 hours)
1. Write a Python script that, for each site, takes the v2 templates and:
   - Substitutes the company name/domain/email
   - Strips the v2.0 default styling
   - Wraps in the host site's design system
2. Output goes into a staging directory: `/tmp/legal-deploy/<site>/`
3. **Deliverable:** Adapted HTML/TSX/Astro files ready to commit

### Phase 3: PR creation (1 hour)
1. For each site, clone fresh, create a branch `add-legal-pages-v2.0`
2. Copy the adapted files
3. Add the footer link
4. Run the site's build to verify no regressions
5. Open a PR with the standardized title: `Add /privacy, /terms, /dpa, /cookies pages (legal v2.0)`
6. **Deliverable:** 6 draft PRs awaiting Ola's review

### Phase 4: Validation (30 min)
1. For each PR, capture a CF Pages preview URL
2. Compare the deployed page against the live site's design language
3. If anything looks off, fix in the PR branch
4. **Deliverable:** Preview URLs documented in the plugin for each company

### Phase 5: Plugin updates
1. Add a `Legal v2.0 PR (2026-06-02)` connection to each company, pointing at the PR URL
2. Add a note in `profile.notes`: "Legal pages v2.0 staged in PR #N — awaiting Ola review"
3. **Deliverable:** Plugin state reflects "PR open, awaiting merge"

---

## 6. Risk mitigation

| Risk | Mitigation |
|---|---|
| Design tokens don't match the live site | Phase 1 discovery + design review before Phase 2 |
| Site uses a build system I don't understand | Phase 1 documents the build; Phase 2 doesn't touch the build, just adds files |
| Footer link doesn't match the site's link style | Phase 1 captures existing footer pattern; Phase 2 mirrors it exactly |
| Path conflicts with existing routes | Phase 1 lists all existing routes; Phase 2 picks non-conflicting paths |
| Mobile layout breaks | Phase 4 captures both desktop + mobile preview screenshots |
| The PR breaks the build | Phase 3 runs the build locally before pushing |
| I push directly to main by accident | Use a fresh clone + branch, never edit the local main checkout |
| Ola wants a different language (NO vs EN) for a site | Phase 1 documents current language; Phase 2 respects it |

---

## 7. The "don't break design" checklist

Before opening each PR, verify:

- [ ] The new page uses the same `<head>` template as other pages on the site (same charset, viewport, OG meta)
- [ ] The new page uses the same `<body>` wrapper / layout component
- [ ] The new page uses the same font family (don't introduce a new one)
- [ ] The new page uses the same color palette (don't introduce new hex values)
- [ ] The new page uses the same spacing rhythm (e.g., site uses `py-12` — use that, not `p-8`)
- [ ] The footer link to the new page matches the existing footer link style
- [ ] The new page renders correctly at 375px width (mobile) and 1440px (desktop)
- [ ] The new page doesn't 404 — verify the route exists in the build output
- [ ] The site's build still passes (CI green)
- [ ] No secrets, no test fixtures, no debug code

---

## 8. What I need from Ola

Before I start Phase 1:

1. **Approval to open draft PRs on these 6 repos:** AgenticInfluencer.agency, CatchUp.help, lovkode.no, samsvarlig.no, styr-ing-product, turmo-dev-site.
2. **Decide the language convention** for each site:
   - agenticinfluencer.agency → EN (default) or NO (if Norway-pivot)
   - catchup.help → EN (confirmed)
   - lovkode.no → NO (confirmed)
   - samsvarlig.no → NO (confirmed)
   - styr.ing → NO (confirmed)
   - turmo.dev → EN (confirmed, public-facing English)
3. **Decide the path convention** for each site:
   - /privacy, /personvern, /privacy/, or /personvern/?
   - /terms, /vilkar, /vilkår, /terms/, or /vilkar/?
4. **Decide the "depth" of each page** — full inline content (current template) or thin wrapper linking out to legal-pack.pages.dev (the source-of-truth pattern)?

I have sensible defaults for all of these but they affect every page, so worth a quick check.

---

## 9. Estimated effort

| Phase | Effort | Risk | Reversible |
|---|---|---|---|
| 1. Discovery | 1-2 hours | low | yes — read-only |
| 2. Generate pages | 2-3 hours | low | yes — local files only |
| 3. Open PRs | 1 hour | medium | yes — PR can be closed |
| 4. Validation | 30 min | low | yes — preview only |
| 5. Plugin updates | 15 min | low | yes — connections can be deleted |

**Total:** 4-6 hours wall time for 6 sites. Sequential, not parallel, because each site has a different stack and there's a small risk of mixing patterns.

If Ola wants me to skip the discovery + validation phases and just commit-and-PR directly, the wall time drops to 2-3 hours. But that means higher risk of design mismatches that Ola would have to fix in code review.

---

## 10. What I'm NOT doing in this session

I'm NOT:
- Pushing to any of the 6 repos
- Opening any PRs
- Modifying any live site
- Deploying anything to any CF Pages project

This is a plan, not execution. The user (Ola) reviews this plan, then decides whether to proceed.
