TRMG · Private Mission Control TRMG

Docs · Reference

Launch Control Operations Manual

Converted from the Claude artifact Launch Control Operations Manual · last updated 2026-10-02 · converted 2026-10-17 · Claude Docs document, one tab. Formatting changes only; the wording is the artifact's.

Oct 2, 2026 · Tristan Rogers

Purpose and scope

This manual is how TRMG builds, ships and runs Launch Control, and how a dealer's month moves through it. It is the reference for anyone working on the product or using it, and it replaces memory: if a step is not written here or in the repo, it is not yet a process.

Launch Control turns one offer brief into compliant creative for every channel a dealer runs: Meta, Google Display, TikTok, website banners, live HTML email, print and out of home. Every frame is checked against OEM, dealer, channel and agency rules before it can go out for approval. The example client throughout is Beck & Beck Buick GMC; all launch content in the system today is example data.

Who it serves

PersonWhat they use it for
Dealer operations staffBring a monthly offer to market quickly without breaking OEM or co-op rules
TRMG marketingBuild, adjust and deliver creative across channels from one brief
Approvers (dealer GM, GM co-op reviewer, TRMG creative lead)Sign off on their part of each version
TRMG leadershipDecide what gets built next and approve every change to the live product

What this manual covers: the system and its environments, who does what, the change process from request to deploy, quality gates, releases and rollbacks, the database, the monthly launch cycle, brand kits, assets, access, integrations, security, accounts and costs, working with Claude, current status, troubleshooting and a glossary.

Where the source of truth lives: the GitHub repository trmg1/launch-control. This manual summarizes it; when they disagree, the repo wins and this manual gets corrected.

System overview

One Cloudflare Worker serves the app, the login page and the API from launchcontrol.trmg.cloud; GitHub holds everything it is built from, and only builds from main reach production data.

[Embedded content in the artifact: Launch Control architecture · from repository to live data. A drawn diagram in the source; it does not translate to markdown.]

A push goes to GitHub, where Actions runs the checks, and to Cloudflare, which builds main as production and every other branch as a preview. The lane switch inside the Worker decides which database and storage a build may use.

PartLives inDoes
Appprototype/src, compiled by prototype/build.pyEvery screen: Launches, workspace, Approvals, Brand kits, Library, Integrations, Team
Login pageprototype/src/login.htmlSign-in by link, code or first-time setup
Frame templatesprototype/src/templates.js, email.jsOne layout per shape builds every size; email is live HTML
Compliance engineprototype/src/checks.js, rules.jsEvaluates every launch against the brand kits as it is typed
Workerworker/index.js, wrangler.jsoncServes the app, requires sign-in, mounts the API, applies the lane
APIapi/srcSign-in, roles, launches, versions, comments, team, webhooks, assets, Mailchimp
Brand kitsbrand-kits/Rules as data beside their source guidelines
Asset registryassets/manifest.jsonEvery image, logo and font with rights and CDN key
Database structuremigrations/Numbered changes to D1
Checks.github/workflows/ci.yml, scripts/Kit validation, tests, build on every push

Environments and lanes

There are four places Launch Control runs, and only one of them is real. Production is the only environment that may touch real launches, people or approvals.

EnvironmentWhereBuilt fromDataWho uses it
Productionlaunchcontrol.trmg.cloudThe main branch, automatically on every mergeProduction database (DB), once connectedThe team and dealers
PreviewA Cloudflare workers.dev link per branch, shown on its pull requestAny branch other than mainPreview database (DB_PREVIEW) or none; never productionWhoever reviews that pull request
LocalThis Mac, through wrangler devWhatever is checked outA throwaway local databaseClaude, for end-to-end tests before pushing
Demo artifactThe claude.ai artifact linkA copy published by handEach viewer's own browser onlySales demos and quick looks

How a build knows its lane. Every build writes build.json with the branch and commit it came from. The Worker reads it: a build from main is production; anything else, including an unknown branch, is a preview. A preview swaps in the preview database and storage, and shows an orange banner naming its branch. /api/health on any environment reports its lane, branch and commit, so anyone can check which version they are looking at.

Rules that follow from this

  • Never point a preview at the production database, even temporarily.
  • Never share a preview link outside the team; it is public, though it holds only test data.
  • The demo artifact never signs in and never shares data. Use it to show the product, not to run a launch.

Roles and responsibilities

Tristan owns the product and approves every change that reaches production; Claude builds, tests and documents. Inside the app, five roles decide what each signed-in person can do.

Building the product

ResponsibilityTristan (owner)Claude (builder)
Decide what gets built and in what orderDecidesProposes, keeps docs/ROADMAP.md current
Write the code, tests and docsReviews in the previewDoes
Run checks before pushingDoes: kit validation, tests, build, browser run
Open the pull requestClicks Create on the prefilled linkPushes the branch and sends the link
Approve and merge to mainOnly TristanNever merges, never commits to main
Confirm the deployChecks /api/health after each merge
Roll back a bad deployCan do it in one clickCan do it, then fixes on a new branch
Accounts, payment, API keysOwns them; pastes keys into Cloudflare himselfGives the exact screen and field
Invite the team and set rolesDoes, on the Team screenExplains, never sees passwords or keys

Using the product (roles in the app)

RoleCan doTypical person
AdminEverything, including the Team screen, integrations and webhooksTristan, a TRMG lead
MarketingBuild, edit, send and deliver creative; edit disclaimers; preview brand kit changes; upload assetsTRMG marketing staff
Dealer opsBuild, edit and send creative; disclaimers stay as the GM library has themDealer operations staff
ApproverApprove or request changes in their own slot onlyDealer GM, GM co-op reviewer, TRMG creative lead
ViewerSee everything and commentAnyone who needs visibility

The server enforces these on every request. Hiding a button is only a convenience; it is never the protection.

The change process

Every change, however small, travels the same path: branch, pull request, checks, preview, merge, deploy, verify. Nothing reaches launchcontrol.trmg.cloud any other way.

Step by step

  1. Request. Tristan names the goal in a sentence or two: who it is for and what done looks like. Screenshots and client examples help. Or he says "next on the roadmap".
  2. Plan. For anything larger than a small fix, Claude replies with what will be built and anything needed from Tristan (an account, a decision, a key).
  3. Branch. Claude starts a branch from the latest main.
  4. Build and test. Claude writes the change, its tests and its docs, then runs the full checks locally plus a real browser run for anything on screen.
  5. Push and link. Claude pushes the branch and sends one prefilled pull request link.
  6. Open the pull request. Tristan clicks the link, then Create pull request. The title and description are already written.
  7. Checks. GitHub runs the checks (about two minutes). Red means Claude fixes it on the same branch; the pull request updates itself.
  8. Preview. Cloudflare builds the branch and adds a preview link to the pull request. Tristan opens it and tries the change.
  9. Merge. Tristan clicks Merge pull request, Confirm merge, then Delete branch.
  10. Deploy and verify. Cloudflare deploys main in about two minutes. Tristan says "merged"; Claude confirms /api/health shows production at the new commit, deletes any leftover branch, and updates the roadmap.

Branch names

Kind of changePrefixExample
New capabilityfeature/feature/email-codes
Bug fixfix/fix/story-headline-wrap
Documentation onlydocs/docs/onboarding-guide
Tooling or setupsetup/setup/branch-workflow

Lowercase, words joined by hyphens, one purpose per branch.

Every pull request answers four things (the template asks for them): what changes, why, how to check it in the preview, and whether it changes the database.

Definition of done

  • Checks are green on the pull request
  • Tristan has looked at it in the preview
  • Any database change is a new numbered migration, applied to the preview database first
  • Docs are updated in the same pull request (README, WORKFLOW, ROADMAP, or this manual)
  • After merge, /api/health shows production at the new commit

Pace. One branch at a time while the team learns the routine. Later, two or three can run side by side, each with its own preview.

Quality gates

A change must pass three automatic checks on GitHub and a human look at the preview before it can merge. A red check means stop.

GateWhat it provesRunsCommand
Brand kitsEvery kit file is valid: known checks, correct parameters, no misspelled placeholders, no dashes as separators. Every example launch in brand-kits/fixtures/launches.json still gets its expected results (11 cases today)Every push and pull requestnode scripts/validate-kits.mjs
TestsThe API, sign-in, roles, approvals, comments, webhooks, Mailchimp drafts, asset uploads, the Worker and the lanes (35 tests today)Every push and pull requestnode --test api/test/*.test.mjs
BuildThe app and login page compileEvery push and pull requestpython3 prototype/build.py
Deploy dry runCloudflare would accept the Worker and its settingsClaude, before pushing config changesnpx wrangler deploy --dry-run
Browser runThe feature works in a real browser, signed in as the roles it affectsClaude, for anything on screenLocal Worker + scripted Chrome
Preview reviewIt does what was asked, and nothing else changedTristan, on every pull requestThe Cloudflare preview link

House rules every change follows

  • No spaced dashes as separators anywhere: in creative, in the app, in docs, in commit messages. Use a colon, a semicolon, a middle dot, or let weight and size carry the break. The kit validator enforces this on kit files.
  • Every fix to a misfiring rule starts with a new fixture that reproduces it, so it stays fixed.
  • Tests ship in the same pull request as the code they cover.
  • Secrets never enter the repository or a chat.

Releases, verification and rollback

Every merge to main is a release, live in about two minutes; if it goes wrong, roll back first and fix second.

How a release happens

  1. A pull request merges into main.
  2. Cloudflare's Git integration for the Worker launch-control runs the build command python3 prototype/build.py, then npx wrangler deploy using wrangler.jsonc.
  3. The new version takes all traffic at launchcontrol.trmg.cloud. Cloudflare keeps every earlier version.

How to verify a release

Open https://launchcontrol.trmg.cloud/api/health. It must show "lane":"production", "branch":"main", and a commit matching the merge. Then open the app and check the thing that changed. Claude does both after every "merged".

How to roll back (one minute)

  1. Open the Cloudflare dashboard, then Workers & Pages, then launch-control.
  2. Open Deployments.
  3. Find the last version that worked, open its menu, choose Rollback, and confirm.
  4. Check /api/health: the commit now shows the older version.
  5. Tell Claude what went wrong. The fix comes on a fix/ branch through the normal process; the next merge replaces the rollback.

What a rollback does not undo: database migrations, secrets and data written since the release. That is why migrations only ever add things (see Database operations).

Hotfixes. An urgent fix still uses a branch and a pull request, just a small one with only the fix. Skipping the process is how a fix breaks something else.

Release record. GitHub keeps the history: every merged pull request is a numbered release note (what, why, how it was checked). Pull request #1, the branch workflow, merged on Oct 2, 2026.

Database operations

The database is Cloudflare D1, two of them: launch-control for production and launch-control-preview for branch previews. Neither is connected yet; that is the next roadmap item.

What it holds

TableHolds
users, sessions, login_codes, login_linksPeople, their roles and approval slots, and sign-in (secrets stored only as keyed hashes)
launchesEach launch's brief, approval state and version number, with a revision counter
launch_versionsEvery version exactly as it was sent for approval, with the kit versions and check results at that moment
commentsPinned feedback: frame, position, version, author, resolved or open
webhooks, events, deliveriesEndpoints, every event sent, and each delivery's attempts
assetsUploaded files: content hash, CDN key, size

How the structure changes: migrations

The structure lives in numbered files in migrations/. 0001_initial.sql is the first. Each runs once per database, in order, and the database records which have run.

  1. A change is a new file, for example 0002_add_frame_adjustments.sql. Never edit one that has been applied.
  2. Add first, remove later. A new table or column ships with the code that uses it; anything old is removed in a later release, once nothing uses it. Rolling back code never undoes a migration, so this keeps rollbacks safe.
  3. Order: Claude applies the migration to the preview database while the pull request is open (npx wrangler d1 migrations apply launch-control-preview --remote), then to production right before Tristan merges (npx wrangler d1 migrations apply launch-control --remote).
  4. The pull request template's Database box says whether a migration is included.

How saves stay safe with several people

Every save of a brief carries the revision it started from. If a teammate saved first, the save is refused, the app loads their version and says so. Approval state only changes through dedicated actions (send, approve, request changes, next version), so editing a brief can never approve anything.

Backups and recovery. D1's Time Travel can restore a database to an earlier point in time. Confirm the retention window for the account's plan when the database is connected, and record it here.

Monthly launch operations

Each month runs on one loop: new OEM incentives arrive, each dealer's launches are briefed, checked, approved by three people, then delivered and reported. The Launches screen shows the month as a timeline of programs with every launch beneath them.

The cycle

  1. Incentives land. When GM publishes a program (for example GMC Truck Month, Oct 1 to Oct 31), marketing updates brand-kits/gm-offers/programs.json through a pull request: name, OEM, start, end, and the chip wording. This is the one change made every month.
  2. Launches are created. Marketing or dealer ops starts a launch per offer: program, vehicle, offer type (price stack, APR or brand USP), copy, end date, disclaimer and channels. Duplicating last month's launch is the fast path.
  3. Compliance runs live. As the brief is typed, every frame is checked against the dealer kit, the GM offer rules, the channel specs and TRMG delivery rules. Blocking issues must be fixed before sending; warnings need a person's judgement.
  4. Send for approval. Sending freezes the version (v1, v2, ...) with the exact brief, kit versions and check results. Three approvers are asked: the dealer general manager, the GM co-op reviewer and the TRMG creative lead.
  5. Review and feedback. Each approver opens the frames, pins comments to exact spots, and either approves their slot or requests changes.
  6. Iterate. Changes requested, or any edit after sending, starts the next version. Version compare shows the previous version beside the current one. Comments are resolved as they are addressed.
  7. Approved. When all three slots approve, the launch is approved and the delivery actions unlock.
  8. Deliver. Approved creative goes to its channels: PNG frames for Meta, Google and print, live HTML for email (a Mailchimp draft once connected), website banners for the dealer CMS. A delivery event tells connected systems.
  9. Report. Links carry the launch slug as their UTM campaign, so reporting in AgencyAnalytics groups results by launch.
  10. Close the month. Expired offers block automatically on their end date. Rights on vehicle photos that end before an offer are flagged in the Library.

Approval rules

RuleWhy
A version can't be sent with blocking issuesNothing non-compliant reaches an approver
Approvers act only in their own slotA GM can't sign for co-op, and the reverse
Any edit after sending starts a new versionWhat was approved is exactly what ships
Only approved launches can be delivered or exported to a send platformUnapproved creative never reaches a customer
Each version records the brand kit versions it was checked againstThe audit trail a co-op claim needs

Suggested rhythm, to confirm with dealers: incentives entered within a day of release, first versions sent within two days, approvals turned around within one business day.

Brand kit management

Brand kits are the rules Launch Control checks against, kept as files in GitHub next to the guidelines they came from. Six kits hold 27 rules today.

KitFolderTierHoldsRules
GM offer rulesbrand-kits/gm-offersOEM complianceProgram match, offer dates, disclosures, APR qualifier, price math, photo rights; plus programs.json6
GMCbrand-kits/gmcOEM brandNothing yet: no GMC guidelines received0
Buickbrand-kits/buickOEM brandColors and type from the Buick tokens; no written rules yet0
Beck & Beckbrand-kits/beck-beckDealer brandHeadlines, separators, length, Envista USP, pill buttons, legal plates, vehicle placement7
Channel specsbrand-kits/channelsChannelEvery format's sizes, plus safe zones, email size and subject limits, bulletin word count12
TRMGbrand-kits/trmgAgencyBoard surface and export naming2

How a rule is written. A rule names a check from the check library (prototype/src/checks.js), gives it parameters and its own pass and fail wording, and has a severity: block, warn or off. Locked rules are guaranteed by the templates and can't be switched off. Brand managers change wording, limits and severity; a new kind of check is an engineering change.

How a kit changes

  1. Edit kit.json and bump its version, or change a severity on the Brand kits screen, which shows the change as a pull request preview.
  2. Open a pull request. The validator fails it if anything is malformed or any example launch changes outcome.
  3. Review the preview to see exactly what the new rules block.
  4. Merge. Every version sent for approval afterwards records the new kit version.

Cadence

WhenWhat
MonthlyNew incentive programs in programs.json
When guidelines changeUpdate the source markdown and the rules together, in one pull request
When a rule misfiresAdd a fixture that reproduces it first, then fix the rule
New dealerCopy beck-beck/, replace its source files, have Claude draft rules from the new guidelines, review them as a pull request, then add the folder to KIT_ORDER in prototype/build.py
New OEM guidelinesSame as a new dealer, in the OEM kit's folder

Asset management

Every image, logo and font the templates use is registered in assets/manifest.json, with its rights and where it is used; git keeps the record, and the files themselves are meant to live on the CDN. Eight assets are registered today.

What each record carries: a stable id, a human name, kind (vehicle, backdrop, logo, font), the kit it belongs to, tags, and rights (source and end date). The build adds the file's size, dimensions, SHA-256 content hash, CDN key and URL.

Content-hashed names. A file's CDN key includes the first 10 characters of its content hash, for example kits/beck-beck/vehicles/veh-sierra-1500-at4.688e661541.png. The same bytes always get the same key, so duplicates are caught and files can be cached forever. A changed image gets a new URL, so nothing already published changes underneath anyone.

Rights are a compliance check. Rule GM-06 compares a vehicle photo's license end date with the offer's end date and flags the launch when the license ends first. The example Yukon XL photo is set to end Oct 15, 2026, so the Yukon launch shows that warning.

Adding or replacing an asset

  1. Upload it on the Library screen (today it is hashed and measured in the browser; once storage is connected it uploads to R2), or send it to Claude.
  2. Record its rights: where it came from and when the license ends. An asset with no rights record is flagged.
  3. Claude adds it to the manifest in a pull request; the build computes its key.
  4. After merge, node scripts/sync-assets.mjs uploads it to the bucket. Re-running is safe.

Open item: the Futura font. It came with the client's files under a desktop license. Confirm the license covers web and email embedding, or switch to a licensed web font, before it is served from a public CDN.

Planned CDN: an R2 bucket with cdn.trmg.cloud as its custom domain (roadmap item 5). Until then, email exports carry {{CDN}} placeholders and the app embeds images directly.

Access management

Once the database is connected, every page except /login needs a signed-in person (switched on Oct 2, 2026), and admins manage who that is on the Team screen.

Organizations. Everyone belongs to one organization. TRMG sees every client. Each client, in automotive or any other industry, sees only its own launches and people; anything else answers as if it didn't exist. TRMG admins add clients on the Team screen. A Client admin at each dealer group adds, changes and disables their own people, and can't touch anyone else. This ships with feature/client-workspaces.

Dealers and groups. Below a client sit dealer groups and dealers (sub-clients outside automotive). Hi Tech Motorcars, for example, has the Hi Tech Luxury Imports group (Aston Martin Austin, Bentley Austin, Lotus of Austin, Rolls-Royce Motor Cars Austin, Hi Tech Luxury Collection) and Georgetown INFINITI on its own. Platinum Land has Highland Branch, The Estates at Highland Branch and Platinum Land. A launch is for the whole client, a group, or one dealer. Each person's Access on the Team screen is every dealer, or chosen groups and dealers, and a group covers every dealer in it, including ones added later. Someone with Georgetown INFINITI sees only that store's launches; someone with the Luxury Imports group sees its five stores and its group campaigns; someone with every dealer sees everything at that client. Changes apply on the person's next click.

Client sign-in, planned. Dealer staff will use Sign in with Microsoft with their Outlook work login, and TRMG will use Sign in with Google. Either way a session lasts 30 days and every visit restarts it. Some dealer groups' IT must approve a new app once before their staff can use it.

Ways to sign in

MethodHow it worksAvailable
Setup link/login?setup=<token> creates the first admin while there are no people yet, then stops workingWhen the database connects
Sign-in linkAn admin creates it on the Team screen and sends it by any channel. Works once, on one device, for 7 daysWhen the database connects
Email codeA 6-digit code by email, valid 10 minutes, at most 5 per hour per addressAfter Resend is connected (roadmap item 4)

Sessions last 30 days on a device. Signing out ends that session; disabling a person ends all of theirs at once.

What each role can do

PermissionAdminMarketingDealer opsApproverViewer
See launchesYesYesYesYesYes
CommentYesYesYesYesYes
Edit briefsYesYesYes
Edit disclaimersYesYes
Send for approvalYesYesYes
ApproveAny slotOwn slot
Deliver and exportYesYes
Brand kit rulesYesYes
Upload assetsYesYes
Integrations and webhooksYes
TeamYes

Onboarding a person

  1. Team screen, then Add a person: email, name, role, and for approvers their slot (general manager, co-op reviewer or creative lead).
  2. Click Add and get link, then Copy link.
  3. Send it to them directly. They open it and click Sign in to Launch Control.

Offboarding: on the Team screen, click Disable next to the person. Their sessions end immediately and their links stop working. Their comments and history stay.

Guard rails: there must always be at least one active admin; the system refuses to demote or disable the last one. Review the Team list monthly and disable anyone who has left.

Integrations and webhooks

Launch Control tells other systems what happened through signed webhooks, and pushes approved creative to the platforms each channel runs on. Webhooks go live with the database; platform connectors arrive one roadmap item at a time.

Events sent

EventSent when
launch.createdA launch is created or duplicated
launch.version_startedAn edit or a change request starts a new version
launch.submittedA version is sent for approval
approval.recordedOne approver signs off
launch.changes_requestedAn approver requests changes
launch.approvedAll three slots have approved
comment.createdFeedback is pinned to a frame
comment.resolvedFeedback is resolved or reopened
compliance.blockedA launch picks up a blocking issue
delivery.requestedApproved creative is pushed to a channel
pingAn admin sends a test event

How delivery works. Each event is a JSON POST with an LC-Signature header: an HMAC SHA-256 of the timestamp and body, keyed with that endpoint's secret. Receivers verify it and reject anything older than five minutes; the Integrations screen has copy-ready code. The first attempt runs immediately; failures retry on the minute cron after 1, 2, 4, 8, 16, 32 and 64 minutes, then are marked failed. A receiver answering 410 Gone pauses its endpoint.

Managing endpoints (admins): Integrations screen, then Add an endpoint: a name, an https:// URL, and the events it should receive. Copy the signing secret when it is shown; it is never shown again. Pause, test or remove endpoints from the same screen, and read every event's delivery status in the event log.

Inbound webhooks. Other systems post to /api/v1/inbound/<source>, signed the same way or with a token in the URL. They become inbound.<source> events that endpoints can subscribe to. Planned uses: Stripo saving an edited email, an OEM incentive feed, monday.com status changes.

Connections

SystemDoesStatusNeeds from TRMG
monday.comMirrors each launch as an item; status follows the eventsReady through webhooksThe board's webhook or automation URL
Stratos CRMStarts lead routing when a launch is approvedReady through webhooksThe receiving URL
SlackPosts comments, change requests and approvalsReady through webhooksAn incoming webhook URL
AgencyAnalyticsGroups results by launch through UTM tagsTags already on every linkNothing
MailchimpCreates a draft campaign from an approved email, never sendsBuilt and tested; not connectedAPI key and audience
StripoHand edits in the Stripo editor, returning as a new versionPlannedPlugin ID and secret
Meta, Google Ads, DudaPush approved frames to ad accounts and the dealer sitePlannedAccount access

Security and data handling

The rule of thumb: secrets live only in Cloudflare, permissions are checked on the server, and test data never mixes with real data.

Built into the system

ProtectionHow
Sign-in secrets are never stored readableSession cookies, sign-in links and email codes are stored only as HMAC hashes keyed with AUTH_SECRET, so a copy of the database can't be used to sign in
CookiesHttpOnly, Secure, SameSite=Lax, 30 days
PermissionsChecked by the API on every request; approvers limited to their own slot
Approval integrityA plain save can't change approval state; sent versions are frozen
Cross-site requestsWrites from any other website are refused
No account discoveryThe email code form answers the same way whether or not an address has access
Rate limits5 email codes per address per hour; 5 tries per code
Previews isolatedNon-main builds never get the production database or storage
Not indexedEvery page sends noindex; framing by other sites is blocked
Webhook authenticityEvery delivery signed; inbound webhooks verified

People rules

  • Keys, tokens and passwords are never pasted into chat, email or the repository. They go straight into the Worker's Variables and Secrets in Cloudflare.
  • The GitHub repository stays private. It holds client brand files and a licensed font.
  • Preview links stay inside the team.
  • Disable people the day they leave.
  • Real customer data (names, emails) is not in the system and should not be added until it is needed and reviewed.

Known gaps, tracked on the roadmap

  • Compliance results on submit come from the browser; the server will re-run the checks itself (roadmap item 3).
  • Sign-in routes have per-address limits but no wider rate limiting yet.
  • main can't be protected by GitHub rules on the free plan; for now it is a habit that only Tristan merges.

Accounts, domains, credentials and costs

Everything runs on accounts TRMG owns, on free tiers today.

Accounts

ServiceAccountUsed forPlan
GitHubtrmg1 (personal account)The private repository trmg1/launch-control, checks on every pushFree
CloudflareTristan@trmg.io's accountThe Worker launch-control, its Git builds, DNS for trmg.cloud, and soon D1 and R2Free tier today
ResendNot created yetEmail sign-in codesFree tier planned
MailchimpTo be decided: TRMG's or each dealer'sDraft campaigns from approved emailsOpen question

Domains

DomainDNS hostRole
launchcontrol.trmg.cloudCloudflareProduction app, login and API
cdn.trmg.cloudCloudflarePlanned asset CDN
trmg.ioGoogle, with the site on DudaTRMG's main site and Google Workspace email. Not used by Launch Control; moving its DNS would mean copying every website, email and CRM record exactly

Credentials and where they live

CredentialLives inWho can change it
Deploy key for pushing to GitHubThis Mac (~/.ssh/id_ed25519_launch-control), registered on the repo with write accessTristan, on the repo's Deploy keys page
Wrangler (Cloudflare command line) authorizationThis Mac, after Tristan clicks AllowTristan; npx wrangler logout revokes it
AUTH_SECRET, BOOTSTRAP_TOKENWorker secrets in CloudflareSet during database connection
RESEND_API_KEY, MAILCHIMP_API_KEYWorker secrets in CloudflareTristan pastes them in himself
Webhook signing secretsThe database; shown once when an endpoint is addedAdmins, on the Integrations screen

Costs to expect

  • Today: none beyond existing subscriptions.
  • Optional: GitHub Pro (a few dollars a month) to make GitHub enforce pull requests and green checks on main.
  • Later: Cloudflare's paid Workers plan only if traffic or storage outgrows the free tier; Resend's paid tier only above its free sending limit.

Working with Claude

Claude is the builder on this project: it writes, tests and documents every change, and Tristan decides and approves. Conversations end and get compressed, so the project's memory lives in files, not in any one chat.

Asking for work

  • Say the goal, who it is for, and what done looks like. "Dealers need to duplicate last month's launches in one click" beats "add a button".
  • Send screenshots of anything confusing or broken, and client examples of what good looks like.
  • "Next on the roadmap" is always a valid request.
  • Expect a short plan back for anything bigger than a small fix, naming anything Claude needs from you.

What Claude always does

  • Works on a branch, never on main; Tristan merges.
  • Runs every check, and a real browser test for anything on screen, before sending a link.
  • Says plainly what was verified and what wasn't.
  • Updates the docs in the same pull request.
  • Asks before anything hard to undo or outward facing: deleting, sending, sharing, spending.

What Claude never does

  • Asks for passwords or keys in chat.
  • Merges its own pull requests or changes production data directly.
  • Guesses at facts it can't check; it marks them as open questions instead.

Where context lives

PlaceHolds
The repository (README.md, docs/WORKFLOW.md, docs/ROADMAP.md, api/README.md)How the system works, how we work, what's next
This manualThe operating picture in one place
Claude's memory notes on this MacAccount details, where things live, the agreed workflow, what's pending
Pull requestsEvery change, why it was made, and how it was checked

Sessions. A fresh session per roadmap item keeps conversations focused. Automatic compression can be turned off in Claude Code with /config; if it is off and a conversation fills, start a new session and point Claude at this manual and the roadmap.

Approvals that happen on this Mac. Cloudflare authorization opens a browser page on the Mac where Claude's commands run, with a 2-minute window. Before Claude starts one, it says so; be at this Mac to click Allow.

Current status and roadmap

The product, sign-in, roles, shared data and webhooks are built and tested; they switch on when the databases are connected, which is waiting on one Cloudflare authorization click at this Mac.

Shipped

DateWhatWhere
Oct 2, 2026Production and preview databases connected; sign-in switched onPull request #2
Oct 2, 2026Branch workflow: guide, roadmap, pull request template, migrations, preview isolationPull request #1
Oct 2, 2026Sign-in, roles, Team screen, shared launches and comments, live webhooks, one Worker for app and APICommit 7cfc129
Oct 2, 2026Live at launchcontrol.trmg.cloud from GitHub through CloudflareWorker launch-control
Oct 1, 2026Brand kits as files with a validator; asset registry; integrations screen; email as live HTML; out of home layout; vehicles on one ground line; feedback, versions and approvalsPrototype releases

Next, in order

#BranchUnlocksNeeds from Tristan
1feature/client-workspacesClients as separate organizations; Client admin roleReview the preview, merge (pull request open Oct 2)
2feature/microsoft-signinSign in with Microsoft for dealer staff on OutlookRegister the app in Microsoft's developer portal
3feature/google-signinSign in with Google for the TRMG teamCreate a sign-in client in Google Cloud
4kits/hi-tech-motorcarsHi Tech's own brand kitHi Tech's guidelines, logo and fonts
5feature/server-complianceThe server re-runs every brand kit check on submitNothing
6feature/email-codesSign in by emailed code, for anyone without Microsoft or GoogleA free Resend account with trmg.cloud verified
7feature/cdnAssets at cdn.trmg.cloud; real image links in emails; Library uploadsNothing
8feature/exportPNG at 2x per frame and a ZIP per channelNothing
9feature/frame-adjustmentsPer-frame tweaks that survive brief editsNothing
10feature/mailchimpThe Create Mailchimp draft button worksAPI key and audience
11feature/trmg-webhooksmonday.com, Stratos and Slack receive eventsTheir receiving URLs
12fix/header-wrapThe header fits on one line at laptop widthsNothing

Later: incentive programs from an OEM feed through the inbound webhook; a GMC brand kit when guidelines arrive; Stripo editing; Meta, Google Ads and Duda delivery.

Open questions for Tristan

  • Whose Mailchimp account receives drafts: TRMG's, or each dealer's?
  • Does the Futura license cover web and email embedding?
  • Who are the first five people to invite, and in which roles?
  • Is GitHub Pro worth adding now so GitHub enforces the merge rules?

Troubleshooting

Most problems have a known cause and a one-step fix; when in doubt, check /api/health first, then send Claude a screenshot.

SymptomLikely causeFix
The live site looks wrong right after a mergeThe new release has a bugRoll back in Cloudflare Deployments, then report it
A check on the pull request is redA test, a kit rule or the build failedTell Claude; the fix goes on the same branch
No Cloudflare preview on a pull requestBuilds for non-production branches are offCloudflare, Workers & Pages, launch-control, Settings, Build: turn on non-production branch builds
Cloudflare can't find the repository when connectingThe Cloudflare GitHub app can't see itgithub.com/settings/installations, Cloudflare Workers and Pages, Configure, add launch-control
Header says "Not connected: changes stay in this browser"The database isn't connected (expected until roadmap item 2)None needed; finish item 2
Orange "Preview" bannerYou are on a branch preview, not productionUse launchcontrol.trmg.cloud for real work
Sign-in link says it has expiredLinks work once and for 7 daysAn admin makes a new one on the Team screen
"Email codes aren't switched on yet"Resend isn't connectedUse a sign-in link from an admin
Too many codes5 codes per hour per addressWait an hour, or use a sign-in link
"Your role can't do that"The action needs another roleAsk an admin to change the role on the Team screen
A teammate saved at the same momentTwo people edited the same launchThe app shows their version; redo your edit
"Send for approval" is greyed outBlocking compliance issuesFix the items marked Blocked in the Compliance panel
Approve buttons missing for an approverWrong or missing approval slotAdmin sets the slot on the Team screen
Webhook deliveries failingThe receiver is down or rejecting the signatureEvent log shows status and last error; retries run for about two hours
Cloudflare authorization timed outThe Allow page opened on the Mac and wasn't clicked within 2 minutesBe at this Mac when Claude starts it, then click Allow
Mailchimp draft failsKey not set, or the launch isn't approvedAdd the key in Worker secrets; approve the launch first

Glossary

TermMeaning here
BranchA separate line of work in the repository; changes on it don't affect main until merged
mainThe branch that is live at launchcontrol.trmg.cloud
Pull request (PR)A GitHub page proposing a branch for main, with its changes, checks and preview
MergeAccepting a pull request into main, which deploys it
Checks (CI)The automatic kit validation, tests and build GitHub runs on every push
PreviewA temporary copy of the app built from a branch, with an orange banner and the preview database
LaneProduction or preview; decided by the branch a build came from
RollbackSwitching the live site back to an earlier version in Cloudflare
WorkerThe Cloudflare program launch-control that serves the app, the login page and the API
WranglerCloudflare's command line tool, used from this Mac to set up and inspect the Worker
D1Cloudflare's database; Launch Control uses two, production and preview
R2Cloudflare's file storage, planned for assets behind cdn.trmg.cloud
MigrationA numbered file in migrations/ that changes the database structure once
Brand kitA folder of rules and source guidelines (OEM, dealer, channel or agency) that creative is checked against
Check libraryThe code (checks.js) that kit rules point to by name
FixtureAn example launch with expected results that every kit change must still produce
SeverityBlock (stops sending), warn (flag for a person) or off
LaunchOne offer brought to market: its brief, frames, versions, approvals and comments
VersionA frozen copy of a launch as sent for approval (v1, v2, ...)
Approval slotOne of the three sign-offs: general manager, co-op reviewer, creative lead
FrameOne ad size in one channel, such as the Meta square feed at 1080×1080
WebhookA signed message Launch Control sends to another system when something happens
HMACA keyed hash used to sign webhooks and protect stored sign-in secrets
SecretA key or token kept only in Cloudflare's Variables and Secrets, never in the repo or chat
Deploy keyThe key on this Mac that lets Claude push branches to the one repository
Content hashA fingerprint of a file's bytes, part of every CDN file name