# Campaign Release Studio — architecture

An independent, local React/TypeScript frontend connects campaign planning, creative proofs, customer intent, review and a simulated operational handoff. It is a **frontend theme system**, with generic export interfaces. No WordPress theme, Dealer.com integration, CMS deployment, advertising account or live CRM is implemented.

The original working version is preserved at `outputs/campaign-release-desk`. The reversible upgrade lives separately at `outputs/campaign-release-studio`; it uses the distinct `campaign-release-studio.v2` local-storage key. The original mechanical cases remain reachable through `/desk` in the upgrade.

## Repository boundaries

| Boundary                                           | Responsibility                                                                                                                                                                                                                                                                                                                                                |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `src/main.tsx`, `src/studio/StudioApp.tsx`         | Route Experience, Studio, Measurement and Strategy & evidence; choose campaign; offer validated local import/reset; expose the independent-demo disclosure. `/desk` and original service sample routes retain the mechanical workflow.                                                                                                                        |
| `src/studio/catalog.ts`, `Media.tsx`, `studio.css` | Allowlisted local images with individual source/license/credit metadata; reusable option content; road/water identities; theme tokens, media treatment, layout and responsive recipes.                                                                                                                                                                        |
| `src/studio/Customer.tsx`                          | Explore a direction and its detail; select a synthetic location/timing; validate fictional contact and use case; persist a contextual local enquiry; show its receipt. No external lead adapter runs.                                                                                                                                                         |
| `src/studio/Workspace.tsx`, `workspace.css`        | Brief → Creative → Release → Handoff. Bounded source/variant editing, frozen review dialogs, explicit draft generation, detailed checks, demonstration-clock editing, package preparation and local queue actions. Workspace selectors are scoped with `ws-`.                                                                                                 |
| `src/studio/Creative.tsx`                          | Landing, email and social proofs combine source media/action with the selected channel's actual headline, body and disclosure. Motion remains source-derived, with manual frames, bounded playback and a reduced-motion equivalent; it is not a fourth approved transmission channel. The exact text/tracking/disclosure record also appears below the proof. |
| `src/domain/types.ts`, `creative.ts`, `upgrade.ts` | Typed experience, intent and event contracts; compatible theme/asset/option/department rules; strict bounds; upgrade fixtures; expected-revision experience edits; intent-complete local enquiries and session-based events.                                                                                                                                  |
| `src/domain/engine.ts`                             | Pure review, date/DST, expiry, content, destination, UTM, lead routing, history and import/export rules retained from the original engine. Inquiry campaigns add creative configuration checks without inventing price or inventory terms.                                                                                                                    |
| `src/store.ts`                                     | Serialized transactions, local persistence/status, validated cross-tab updates, storage-failure behavior. Invalid cross-tab records retain current work.                                                                                                                                                                                                      |
| `src/studio/export.ts`, `src/utils.ts`             | Revalidate the reviewed snapshot; prepare a local ZIP and expose an explicit download link through the loopback-only adapter; standalone hosts fall back to a blob download request. The interface does not confirm filesystem delivery. Generic packages and adapter notes define the production boundary.                                                   |
| `src/components/ui.tsx`                            | Shared button, labeled field, select, modal dialog, status and error primitives. Native dialogs manage keyboard focus and return it to the opener.                                                                                                                                                                                                            |

## Local artifact delivery

`scripts/local-artifacts.ts` is a Vite dev/preview middleware adapter, bound to loopback. It accepts same-origin ZIP posts with a dedicated MIME type, a bounded campaign filename, a 12 MiB limit and a ZIP signature. Files are written atomically under `exports/browser` with content-hash names; download requests validate the allowlisted filename and unchanged bytes. This exists only for local artifact preparation, not lead delivery or production CMS publishing. A browser click records a download request, while host receipt is separately verified in QA.

## One shared content model, two identities

`Campaign.offerText` supplies the headline. `Campaign.experience` supplies theme, eyebrow, story, action, hero asset, direction IDs, receiving department, audience and objective. Existing campaign fields retain owner, local start/end/timezone, disclosure, destination, synthetic locations, channels, revision and approval. Inquiry campaigns use `offerKind: "inquiry"`; illustrative directions are not inventory listings or financial offers.

Friendly Automotive uses an editorial automotive composition and condensed display typography. Unriehl Marine uses an immersive marine composition, expressive serif typography and a different story rhythm. Themes share semantic controls, approved content and media contracts; their layout, type and interaction treatment do more than switch colors. Photography rights and depiction limits are documented in [ASSET-RIGHTS.md](ASSET-RIGHTS.md).

Website, email and social variants retain independent text, tracking, revisions and approvals. A source mutation clears source and channel approvals. Regeneration is explicit and creates new channel drafts; it cannot silently approve them. A motion study derives from the source and is labeled separately from those three channel records.

## Review and release invariants

Source editing starts with a frozen campaign snapshot and calls `updateExperience` using its expected revision. Core owner/window/disclosure changes run atomically through `updateCampaign`; if both experience and core fields change, the engine may advance more than one revision in that transaction. Unchanged fields preserve state.

Review dialogs show the actual source headline, image, brief, action, directions, disclosure and window. Variant review shows each location/channel headline and revision, with details for its full text, destination, tracking and disclosure. A named reviewer explicitly approves the displayed records. Full snapshot fingerprints also reject changed records imported under the same revision number. A failed edit retains its draft in the open dialog; a stale batch saves no partial approvals.

The release gate recomputes all deterministic checks from current records and the visible simulation clock. It covers ownership, active window, content/completeness, disclosure, destination, UTMs, revision approvals, local routes and inquiry creative configuration. End time is exclusive; ambiguous/nonexistent DST wall times are rejected. Source/channel review may precede a campaign’s active date, while export and enquiry acceptance require the full release gate to pass.

## Handoff and measurement

The local enquiry carries option, intended use, timing, department, source channel, campaign and location. Validation distinguishes original source tags from the current queue. Correct routing preserves source tags; acknowledgment and resolution are local work states. Resolution is not a sale or booking. Historic intent remains preserved when a campaign changes and can be flagged for reconciliation.

Recorded events are `page_view`, `option_select`, `detail_view`, `inquiry_start` and `inquiry_submit`, with local session, campaign, location, channel, option where applicable, actual timestamp and source revision. Views deduplicate per session/campaign/location/channel. Measurement reports observed local sessions; workspace counters identify event counts and repeat behavior. No seeded ad impressions, revenue or conversion lift is presented. Local intent completeness is not real sales qualification. Resets, repeated enquiries, manual source parameters, cross-device journeys and absent consent/ad/CRM integration limit attribution.

## Production adapter boundary

A production release would need an authorized content/media library and CMS adapter, authenticated approvers, tested location/department mappings, consent-aware analytics, and a CRM delivery/qualification/outcome adapter. Public inventory links are explicit external handoffs, not a stock feed. Each production adapter would need its own authorization, error/retry behavior and integration verification.

Build and test commands are `npm run typecheck`, `npm test` and `npm run build`. Rendered desktop/mobile and download checks require browser verification; source compilation alone does not establish them. See [QA.md](QA.md) and the final delivery report for exact observed passes, failures and untested boundaries.

Independent portfolio prototype by Mousa Batarseh — demo data — not affiliated with Jim Riehl’s Friendly Automotive Group. [hireme@mousabatarseh.com](mailto:hireme@mousabatarseh.com) · [mousabatarseh.com](https://mousabatarseh.com/)
