Follow-Up Studio
Inputs
1 · Prospect & Call Context

Who you spoke to and how the message must sound. The city drives the German sign-off (“Beste Grüße nach …”), the send time drives the thank-you opener.

HubSpot connection

Create a private app in HubSpot (Settings → Integrations → Private Apps) with the scopes crm.objects.contacts.read and crm.objects.companies.read, then paste its token here. It is stored in this browser only.

HubSpot's API sends no CORS headers, so a browser refuses every direct call to it. A tiny proxy has to sit in between. This project ships one, and it deploys with the app — nothing to maintain separately.
How to deploy the proxy — once, about three minutes

A · The app already runs on Cloudflare Pages from Git — the easy case.

  1. The file functions/hubspot/[[path]].js is already in the repository. Pages picks up anything under functions/ at the repo root automatically — there is no code editor to find in the dashboard, and no separate Worker to create.
  2. Commit and push. The next deployment publishes the app and the proxy together.
  3. Leave this field empty. The app then calls its own domain, /hubspot/…, which is same-origin — CORS never even applies.
  4. Check it worked: open https://<your-domain>/hubspot/crm/v3/objects/contacts. A JSON error about a missing Authorization header is the good answer — it proves the proxy is live. A 404 means the deployment has not picked it up yet.

B · Anywhere else — opened from a file, served from localhost, or hosted somewhere without Functions.

  1. Cloudflare dashboard → Workers & PagesCreateWorkersCreate Worker. Name it hubspot-proxy, then Deploy.
  2. On the Worker's page click Edit code, delete the template, paste the contents of deploy/hubspot-proxy-worker.js from this project, then Deploy again.
  3. Settings → Variables and Secrets → add ALLOWED_ORIGINS with the origins that may call it, comma-separated, e.g. https://followup-studio.cxlever.io,http://localhost:8777.
  4. Copy the Worker URL (https://hubspot-proxy.<subdomain>.workers.dev) into this field.
  5. One Worker can serve every CxLEVER app that talks to HubSpot. List each app's origin in ALLOWED_ORIGINS, separated by commas, and paste the same URL into each app. The Worker holds no token of its own, so nothing is shared between the apps except the route.

Already connected a Worker to Git and it will not take variables? Cloudflare then says “Variables cannot be added to a Worker that only has static assets” — wrangler deploy found no wrangler.toml, so it published the repository as files instead of running the script. Route A makes that Worker unnecessary; disconnect or delete it.

Either way the proxy stores nothing and holds no secret. Your private app token travels in the request header from this browser, exactly as it would to HubSpot directly, and only read paths are forwarded — a leaked URL cannot write into your CRM.

* Paste the actual website/webpage content or scrape(s) into 2 · Inputs below. The URL alone is only a hint for the AI — pasted content is what stops it from inventing things.
The HubSpot import fills both from the contact’s associated companies — the primary company first, the second company after it. With only one company, the second field takes that company’s other URL when its website and domain differ.
2 · Inputs — Transcript, Website, CRM

The message can only be as deep as what you paste here. Block A is mandatory; B and C are what make the mirror paragraph land — every fact the AI uses from them is listed back to you in the internal note.

Drag & drop one or more files straight onto this box — .txt, .md, .vtt and .srt subtitles, .json, .csv. Several files are appended one after another, each under its own filename header.
Drop saved pages or scrapes here — .html files are reduced to their readable text automatically.

Nothing you paste leaves this browser unless you press Generate in the Live Generate panel — and then it goes straight to the AI provider you chose, never to a CxLEVER server.

3 · Preset & Next Step

The preset decides the architecture of the message — which blocks appear, in which order, and how long each piece may be.

Short stands on its own, for prospects who get no e-mail. The note right after the e-mail does one job: it says the detailed analysis has just landed in their inbox, names the topics it covers, and invites a reply.
The last two shape the e-mail only. Copy E-Mail keeps that formatting when you paste into Gmail, Outlook or HubSpot; the plain-text and LinkedIn versions drop it, because neither channel renders it.
The field above shapes the closing paragraph: who sits at the table and what you need before the meeting. This one is for content the AI must weave in wherever it fits — a commitment made on the call, a name to credit, a constraint to acknowledge.

For the deepest messages, paste this prompt into one of the latest top models — e.g. Claude Opus 4.8, Gemini 3.1 Pro, GPT-5.x or Mistral Large — then paste the JSON it returns into the Spec editor below.

Follow-Up Spec Editor

The message set as JSON — the file everything else is rendered from. You rarely need to open this: generate below, edit in the preview. It is here for writing a message by hand, for pasting JSON back from an AI, and for reading the error when something does not parse.

Live Generate (BYOM) & Refine

Runs the same prompt against your own AI provider. Everything is optional — the app works fully offline without it. Keys are stored only in this browser and sent directly to the provider you pick, over HTTPS. Nothing else leaves your machine.

A full message set (e-mail plus the LinkedIn versions and the internal note) needs roughly 4.000–8.000 output tokens. Too low truncates the JSON.
Quality Check

Scores the message set against the CxLEVER follow-up rules — salutation, capitalised Du-forms, forbidden phrases, double punctuation, bullet symbols, sign-off, length, one CTA — plus a hallucination check that flags every number and every product or vendor name in the message that appears nowhere in your inputs.

Tone of Voice / House Rules — Sender, Forbidden Phrases, Subjects

Your standing rules. They go into every prompt and every quality check, so the app enforces the same style each time.

Tone-of-Voice Profiles

Keep your own tone-of-voice prompts here and pick the one this message should follow. The AI receives the profile name, the link and — if you paste it — the text itself. Paste the text: no AI can open your Google Doc from inside this app.

Versions & Snapshots

Save snapshot stores a dated copy of the current message set with its quality score. Diff shows exactly what changed against the set you have open now — useful to compare the draft you generated with the one you actually sent. Snapshots live in this browser only.

Run Diagnostics

Self-test of the app's dependencies and current config. No data is sent unless you click “Test connection” above.

Message Preview
CxLEVER Follow-Up Studio v1.6.2 · spec schema v1.1 · offline core
Made with in Germany. Powered by CxLEVER.