What's new — May 25 (AI Regenerate)
Pulse now has AI Regenerate — restyle any generated image with a specific change. Two regeneration tools: regenerate without background, and regenerate without a named object. Inline ✎ pills on every image + dedicated sidebar view. Full walkthrough.
Feature · Regenerate without bg
Click ✎ on any image → "Regenerate without background". ~30s, 1 credit. AI produces a cut-out-style variant. Scene and composition held; fine details may drift.
Feature · Regenerate without object
Describe what to remove ("the red car in the background"), hit Regenerate. ~30s, 2 credits. AI produces a new variant of the scene without that object.
Feature · Dedicated AI Regenerate view
Sidebar nav between Ad Studio and Auto Post. Pick any generated image from a thumbnail gallery, or paste a URL.
Feature · Inline ✎ pills
Every generated image in Ad Studio, Calendar posts, and Brand Book has a small ✎ pill. One click opens AI Regenerate in context.
Server-side enforced
can_edit_images feature flag. Demo users get it by default. Platform admins can toggle per-account from All Accounts.
Honest rebrand (v1 → v2)
This is regeneration, not pixel editing. v1 shipped as "Image Editor" but tests showed gpt-image-2 and nano-banana-2 both regenerate the whole scene rather than surgically edit pixels. v2 renamed everything to "AI Regenerate" + added explicit heads-up banners. v1 wasted spend has been refunded.
RapidRaw callout
For pixel-perfect editing (RAW color grading, true mask-based inpaint), use the open-source desktop app RapidRaw separately. Pulse can't ship that — it's AGPL-3.0 + desktop-only.
Earlier release — May 24 (multi-tenant launch)
Pulse is now ready for public demo. Every signup gets their own isolated workspace, a starter brand cloned in automatically, and a configurable credit + feature budget. Platform admins (you) get a full operator console under the new Admin sidebar.
Feature · Admin dashboard
Four-tab admin console for managing hundreds of users. All Accounts (every org with usage metrics), Pending Signups (approval queue), Template Brands (starter-brand library), Default Policy (auto-approve, default credits, default features). See §13–22.
Feature · Template brands
Mark any of your brands as a template — when a demo user is approved, the first template is deep-cloned into their workspace (brand row + brand brain + characters + visual refs). They get an editable copy. No credits spent, no AI re-generation. Setup guide.
Feature · Brand quotas
Per-account brand limit, enforced at the database. Trial accounts default to 1 brand; raise per-account from the All Accounts tab. The trigger raises a clean brand_quota_reached error the dashboard turns into a friendly toast. Quota guide.
Feature · Manual credit topups
Add credits to any account with one click. Expand any row in All Accounts, type an amount, hit + Add. Inserts an audited credit_transactions row tagged manual_topup. Topup guide.
Feature · Demo feature flags
Video generation is off by default for demo users. Server enforces via user_can_use_feature RPC — even if a user mucks with browser DOM, the edge function returns 403. Toggle per-account in All Accounts → expand row. Flag reference.
Feature · Suspend / reinstate
Suspend any account with one click + reason. Suspended orgs can't create brands or use any feature; the reason shows on next login attempt. Reversible. Suspension guide.
Feature · Live credit balance
Topbar credits update in real time. Subscribes to credit_transactions via Supabase Realtime — every spend or grant from any tab or background job updates instantly. Tab refocus also re-fetches.
Security · RLS lockdown
Every multi-tenant table now enforces org isolation. Dropped the anon_* dev policies that previously let any anonymous client read every brand on the platform. Demo users now see ONLY their own org's data. RLS reference.
Perf · 60% faster brand switch
Brand picker switches in ~525ms (was ~1300ms). Root cause: a wrapper around setBrand was re-firing every loader. Now: view-aware lazy loading + single prefGetMany batch query + brain cache. Network requests per switch dropped from 20 to 6.
Perf · Faster autosave
Blur events bypass the 700ms debounce — saves complete in ~150ms once you leave the field. Keystroke-driven debounce still applies to coalesce bursts.
Bug fix · Brand Book invisible logo
Logos with dark fills (Patagonia) rendered black-on-near-black on the cover. Now wrapped in a white pill when the primary color is dark.
Bug fix · Brand Book Export
The Export button was just window.print() — same as the Print button. Now exports a clean portable JSON of every brand identity field for handoff to designers/clients.
Bug fix · AI image baking in brand name
Three layers of fix: removed BRAND BUMPER rule from concept generator, removed wordmark instruction from image-gen prompt, added defense-in-depth scrubber that strips wordmark phrases from any legacy brief. CSS overlay alone handles the wordmark now.
Bug fix · Empty field indicator
Was alarming in orange ("Missing — run Extract to fill") for any empty Brand DNA field. Now a single neutral grey line listing all empty fields with a helpful Extract CTA — no false alarms.
Earlier release — May 23 (Brand Book + Ad Studio polish)
10 bug fixes + 3 feature upgrades shipped to production. Every workflow re-verified end-to-end on a fresh brand (Patagonia) with real spend.
Bug fix
Overview hero now reads BRAIN HEALTH X/100. Was incorrectly showing the brand-completeness score and labelling it as "HEALTH" — caused confusion when brain was 93/100 but pill said 0/100.
Bug fix
Paste a full Instagram or TikTok URL into a handle field — it now auto-extracts to a clean username. https://www.instagram.com/lululemon/ becomes lululemon. Same for TikTok and YouTube.
Bug fix
Save-failure toast cascade is gone. The tone of voice notes field was hitting a missing DB column; cascade of 10+ red toasts on every keystroke. Now silent + saved.
Bug fix
Viral Research no longer reports phantom trends. The scrape was claiming success while postgres silently rejected the whole batch on a single bad JSON char. Now: sanitise + per-row fallback + real counts in the job output.
Bug fix
Generated thumbnails are now permanent. Every scraped post thumbnail + every generated image and video gets rehosted to your own Supabase Storage — no more 24-hour CDN expiry breaking the demo.
Feature
Ad concepts now pull from your viral patterns. Top 5 trends + their AI-analyzed hook patterns get injected into the concept generator so output leans into mechanics already proven for your brand's audience.
Feature
Re-synthesize button is clearer. Now reads "Re-synthesize Brand Brain · 2 cr" with tooltip + inline explainer that it's the same action as the Brand Guide synthesize button — no more two-button confusion.
Feature
Image / Video toggle in Ad Studio respects the mode. Image mode shows the still even if a video was generated; flip to Video to see the i2v. Badges say IMAGE vs VIDEO so you always know what's playing.
Pulse is the brand brain that turns your strategy into ready-to-ship content — at agency speed.
Train it once. Every visual, every caption, every ad, every video reads from the same canonical source of truth. The better you train it, the more unmistakable your output becomes.

The Overview dashboard: active brand, brand brain health, quick-action cards into every generator. The black sidebar collapses to icons on smaller screens.
Why Brand Brain is everything.
Most AI content tools generate from a generic prompt. Pulse generates from your brand's specific identity — palette, voice, rituals, hero campaigns, cultural touchstones, don't-say list. That's the difference between "an AI image of a chocolate bar" and "a brand-true KitKat Christmas moment that lands in Singapore."
The simple math
Untrained brain → generic stock photos, off-palette colours, hallucinated logos, wrong market cues. Looks AI. Off-brand.
Trained brain → editorial-grade visuals that look like they came from your actual shoot. Palette locked, lighting locked, composition locked, market localized, wordmark composited.

Brand Brain card on Overview — version, health score (0–100), recalibrate by dimension (Content · Visual · Video). Aim for 80+ before generating client work.
Identity
Essence, promise, archetype, hero products, market positioning.
Voice
Tone, voice samples, do-say / don't-say list, banned terms.
Visual
Palette (with auto loud-colour demotion), lighting, composition rules, mood.
Content DNA
Rituals, hero campaigns, cultural touchstones — the things only your brand does.
Benchmarks
Competitor patterns + your own top-performing posts.
Video rules
Motion guardrails — no in-frame text, palette ratios, mandatory wordmark overlay.
Brand Guide — the source of truth.
This is where you tell Pulse who your brand is. Paste a URL and Pulse auto-extracts colours, voice, hero products, and competitors. Or start from scratch and fill it yourself.

Top of Brand Guide: 30-second auto-fill from URL. Pulse reads the site, finds country pages, parses brand colours and fonts, and researches scale-matched competitors automatically.
Paste your URL
Any homepage works — brand.com, brand.com.sg, even a regional sub-page. Pulse follows redirects and tries 3 fallback URLs with a real Chrome 120 user-agent (so Cloudflare doesn't block you).
New: handle fields accept ANY format — paste @brandname, brandname, or even the full https://www.instagram.com/brandname/ URL. Pulse normalises to a clean username automatically.
Pick your target market
Singapore, Malaysia, Indonesia, Thailand, Hong Kong, Japan, UK, US — 18 markets supported. Determines language, cultural touchstones, hawker-vs-hipster cues.
Click "Create + extract · 2 cr"
Pulse spends 2 credits to read the site, parse the colours from CSS, find your social handles, identify your scale-matched competitors, and write a draft brand guide.
The 30+ fields you can teach it

Middle section: brand essence, promise, archetype, voice samples, rituals, hero campaigns, cultural touchstones, don't-say list. Every empty field is a missed opportunity to lock in your brand.
Pro tip — train it like you'd onboard a new junior
Don't just paste the obvious. Tell it the things your team has internalised: "we never call them 'pieces', we call them 'fingers'." "We never show wine, only kopi." "Headlines always start with a verb." This is where the magic compounds.
Brand Brain — synthesized canon.
After Brand Guide is filled, click Synthesize · 2 cr to compile everything into a structured brain. Output is versioned and scored 0–100 on completeness.

One button, two labels
"Synthesize Brand Brain · 2 cr" on Brand Guide and "Re-synthesize Brand Brain · 2 cr" on the Brain card do the same thing. The label just changes depending on whether a brain already exists for this brand. Re-running picks up any new edits to Brand Guide fields and bumps the version number.
Recalibrate by dimension
Edit one slice without rebuilding the whole brain. Three independent dimensions:
Content recalibration
Tweak captions, hooks, voice — without touching visuals. Use when output sounds off but visuals are great.
Visual recalibration
Tweak palette, mood, composition — without touching copy. Use when output reads great but visuals drift.
Video recalibration
Motion guardrails — kicks in when video gen ships for your tier.
Visual Style Library — reference photos that anchor every render.
Drop in real product photography, mood references, location shots. Pulse uses these as image-to-image anchors so AI output never strays from your actual aesthetic.

Visual Style Library — drop images, videos, or paste URLs from Instagram / TikTok / YouTube / Pinterest. Each gets tagged (Hero · Product · Lifestyle · Mood) and pinned references get priority during generation.
Why it transforms output
Without references, AI image models hallucinate your product. KitKat becomes "Kikes." Wrappers come out garbled. Logos morph mid-frame.
With a pinned hero reference, AI receives an image-to-image anchor instead of just a text prompt. Real wrapper, real colours, real proportions — preserved.
Categories
- Hero — your money shot. Use 1–2 max.
- Product — individual SKUs, variants, packaging.
- Lifestyle — in-context use, locations, talent.
- Mood — abstract references for lighting / palette inspiration.

How AI uses them — under the hood
Whenever you click Generate visual, Pulse picks the most-relevant reference (matching category + pinned-first), feeds it to the image model as the visual anchor, and only varies what your brief asks to vary. The reference photo IS the opening frame.
Character Library — consistent faces across every post.
Upload portraits of your locked-in models, founders, or recurring talent. Pulse rebuilds them faithfully in every generation so your campaigns feel like the same continuous story — not a stock-photo collage.

Character library lives just under the Visual Style panel in Brand Guide. Drop a clean portrait, name it (e.g. "Anya — founder", "Mei — Singapore market"), and that character can be invoked by name in any generation.
Upload a clean portrait
Front-on, good lighting, no sunglasses or hats. Higher res = better consistency. JPG / PNG / WebP, max 5 MB.
Mark "Default" if it should appear in every render
One default character per brand. Default = used automatically when a generation needs a person. Override per-post if needed.
Optional: per-market characters
Different talent for SG vs MY? Add one of each. Tag with the market and Pulse picks the right one automatically.
Important — face-consistency limits
Modern image models are excellent at preserving faces from a reference, but identical reproduction across 30 renders is impossible. Expect ~85–90% consistency. For perfect identity (client-locked talent), do a single hero shoot and use those photos as references — don't ask AI to invent multiple angles of the same face.
Viral Research — what's working, why, right now.
Pulse scrapes your own + competitor Instagram and TikTok over the last 90 days, ranks every post by engagement velocity, and gets Claude to write a "why it worked" line on the top 15. So your team isn't guessing what to make next — they're stealing from what's already proven.

Viral Research grid — every card shows the actual thumbnail (permanently rehosted on Pulse's storage, never expires), engagement metrics, velocity tag (Stable / Rising / Exploding), and hook pattern (Mystery Teaser Drop, Stunt Reveal, etc).

Each card answers four questions
- What — caption + visual
- How well — likes / views / shares / comments + velocity
- Why it worked — Claude analysis of the psychological trigger
- Hook pattern — 2-4 word label naming the technique
Three modes
- My Brand — your own top posts (validates what's resonating).
- Competitor — top competitor posts (steal the technique).
- All — combined ranking.
Auto-rehost thumbnails — fix shipped May 2026
TikTok and Instagram CDN URLs expire in 6–24 hours. Pulse now rehosts every scraped thumbnail to permanent Supabase storage at scrape time, so your viral research grid never shows broken images again. You don't need to re-run the scrape to see thumbs.
Bulletproof scrape inserts — fix shipped May 23
Older scrapes could silently report success while postgres rejected the entire batch on one malformed character. v9 now sanitises every JSON-bound field and falls back to per-row inserts on bulk failure — so one bad post drops one trend, not all 25. The job output surfaces the real trends_count + any row errors.
Content Calendar — a month's worth of posts in 90 seconds.
Tell Pulse the month, the static-vs-reel ratio, and your campaign brief. It generates the full schedule (15-30 posts) — each one written, captioned, hashtagged, and structured with a visual brief ready for image generation.

Calendar generator — pick month, year, format mix (12 static + 3 reels + 0 carousels by default). Drop a campaign brief (TXT / DOCX / PDF) and Pulse adapts every post to it.
The post modal — edit anything, regen anything

Click any post → full edit modal. Move dates, change formats, edit captions/hashtags/visual briefs inline, drop a reference image for image-to-image guidance, or rewrite the whole idea with a different angle for 1 credit.
"Don't like this idea?"
Pink box at the top of the modal. Type a different direction — "make it about Vesak Day" or "use hawker centre culture" — and Pulse rewrites just this post for 1 credit.
Edit Caption / Hashtags / Visual brief
Inline Edit buttons. Free. Save → autosaves to the post.
Reference image dropzone
Drag in a product photo or mood reference. Pulse uses it as image-to-image guidance during the next generation.
Multi-platform aspect picker
IG Portrait 4:5 (default), IG Feed 1:1, Reel 9:16, Story 9:16, TikTok 9:16, FB 1:1. Pick multiple — Pulse generates one image per unique aspect.
Generate now · 1 cr
Generate the image from the current brief. Cheap iteration.
Save edits & regenerate · 1 cr/aspect
Saves your text edits AND regenerates the image using your reference. Use after you've tweaked the brief.

Lower half of the post modal — reference dropzone, platform aspect picker, and the two generate buttons. Approve / Reject / Move buttons live in the calendar grid for fast workflow review.
Ad Studio — 4 brand-true concepts, every campaign.
Type a campaign brief. Pulse returns four ad concepts — Hero / Lifestyle / Detail / CTA — each one tagged to a specific brand pillar with explicit "why this works" reasoning rooted in your brand brain. Then animate any concept into a 4-second i2v with locked product fidelity.

Ad Studio entry — Brand Brain pill (on / off), Image / Video mode toggle, 12/12 brand DNA fields injected per generation, campaign brief, hero product, target market, optional reference image dropzone for exact aesthetic match.
New in v9 — viral pattern injection
Before generating concepts, Pulse pulls this brand's top 5 trends from Viral Research and feeds the AI their hook patterns + "why it worked" reasoning. So when KitKat's top post is a "Mystery Teaser Drop" with 637k likes, the concepts lean into mystery-teaser mechanics — not generic chocolate-brand visuals. Your viral data feeds your ad output automatically.
4 concepts per run — each one different, all on-brand

Live output for a Christmas brief — Slot 1 (Hero / festive living-room snap) and Slot 2 (Lifestyle / kopi break) both rendered as i2v videos with brand-locked stills as opening frames. KitKat wordmark composited bottom-right via real HTML/CSS overlay so the model never has to hallucinate text.
The image-to-video pipeline (the bit that actually works)
Pulse writes 4 concepts using brand brain
Brand essence + promise + rituals + hero campaigns + cultural touchstones — all injected. Output includes headline, caption, visual brief, voiceover hint, and "why this works".
Generate the still (1 cr)
gpt-image-2 (with nano-banana-2 fallback) renders an editorial-grade still using the brand's palette, lighting, and composition rules. Real product preserved via your visual style library.
Approve the still inline
You see it. Regenerate cheap if needed. The still IS what the client will see in the static post, AND the opening frame of the video.
Animate that exact still (25 cr · 4s default)
Seedance 1.5 Pro takes the still as the literal first frame, adds subtle motion (camera push, hand gesture, steam drift) — never invents new objects or scene cuts. Audio defaults ON.
Real HTML/CSS overlays compose on top
Brand wordmark + headline overlay get rendered as real text on top of the video in the dashboard — never asked of the AI (which would garble "KitKat" into "Kikes"). What you see is what you ship.

Both concepts as live MP4s — fully audio, brand-true wordmark in the bottom-right corner of every frame. The text below each video is the same brand-pillar reasoning the AI used: rituals, hero campaigns, palette guardrails, banned terms checked.
Why image-to-video — not text-to-video
Text-to-video models hallucinate. They invent fake KitKats, garble wrappers, change lighting mid-shot. With i2v, the still you approved IS the opening frame — the model only adds motion, never invents content. Result: every video looks like it came from your actual shoot.
AI Regenerate — restyle any image with a change.
Two AI regeneration tools for taking a generated image and producing a new variant with a specific change: regenerate without background (clean cut-out style) and regenerate without an object (describe what to remove). Available inline on every generated visual (Ad Studio, Calendar, Brand Book) AND in a dedicated sidebar view.
generated/<brand>/ — each regeneration saves as a sibling variant at edited/<brand>/ so you can compare and choose. If you need pixel-perfect editing, use a desktop tool like RapidRaw separately — Pulse doesn't ship that today.
Two ways to open it
1 · Inline ✎ Edit pill. Every generated image has a small "✎ Edit" pill in the top-right corner. Hover any image in Ad Studio slot cards, Calendar post previews, or the Brand Book hero → click the pill → AI Regenerate opens with that image pre-loaded and tied to the right database record. On save, your post / ad slot / logo automatically updates to the new version.

The ✎ Edit pill in the top-right of every Ad Studio slot image. Same pattern on Calendar post previews + Brand Book logo.
2 · Dedicated sidebar view. "AI Regenerate" item in the left sidebar (between Ad Studio and Auto Post). Click it to open a gallery of every generated image for the current brand. Click any thumbnail to regenerate. There's also a URL paste field at the bottom — drop any image URL to regenerate it standalone.

Sidebar — "AI Regenerate" sits between Ad Studio and Auto Post.

Dedicated view — thumbnail gallery of every generated image for the current brand, plus a URL paste field at the bottom for one-off regenerations.
Tool 1 · Regenerate without background (1 click)
For producing a cut-out-style variant of any generated image. The AI keeps the subject + scene; the background becomes transparent.

Modal — image on the left, the two regeneration options on the right. The yellow heads-up banner at the top explicitly tells users this is regeneration, not pixel editing.
- Click the ✎ Edit pill on any image (or open it from the dedicated view).
- Modal opens with the image + the honest "AI regenerates your image" heads-up banner.
- Click the gold ◐ Regenerate without background button on the right.
- Wait ~30 seconds while nano-banana-2 regenerates. A loading overlay appears with a spinner.
- Done. New version with transparent background swaps in. Toast confirms "AI regenerated · 1 credit spent · Note: fine details may differ from original".

Success toast confirms credits spent + that fine details may differ. The new image swaps in immediately wherever it was being used.
The original image stays at brand-references/generated/<brand>/. The regenerated variant saves at brand-references/edited/<brand>/<uuid>.png. You can always switch back to the original.
Tool 2 · Regenerate without an object (describe what to remove)
For producing a variant where a specific thing is gone. Instead of brushing pixels (which would imply pixel-perfect editing — something AI regenerators don't do), you describe what to remove in plain language. The AI then regenerates the whole scene without it.
- Click ✎ Edit on any image.
- Click the ✕ Regenerate without an object button. A text field appears.
- Describe what to remove. Be specific — name the object AND where it is in the frame:
- ✓ "the red car in the background"
- ✓ "the empty coffee cup on the desk"
- ✓ "the small watermark in the bottom right"
- ✗ "that thing" (too vague — AI won't find it)
- ✗ "things I don't like" (too subjective)
- Click Regenerate · 2 credits. Wait ~30 seconds.
- New variant swaps in. The named object is gone; the surrounding scene is regenerated to fill the space.
Tip: for clean inpaint results, paint slightly LARGER than the object — give the AI a generous margin around the edges. Tight masks sometimes leave halo artifacts.
The Clear mask button wipes your painting if you want to start over. Cancel exits brush mode without spending credits.
Server-side enforcement (admins)
The editor is gated server-side via the can_edit_images feature flag (see §18 Feature gating). Demo accounts get it ON by default — it's low cost (1–2 cr per edit) and high value for the "try the product" experience. Disable per-user from Admin → All Accounts if needed.
Failed edits auto-refund credits. The edge function (edit-image v1) uses the same atomic spend_credits / refund_credits pattern as generate-visual.
What's not included (yet)
- Crop / rotate / canvas resize → v2 (Pintura embed planned)
- Color adjustment (exposure, contrast, saturation) → v2
- Text overlay → v2 (use the existing Ad Studio overlay editor instead)
- AI upscaling → v2 (Replicate Real-ESRGAN planned)
- Undo/redo within an edit session → save and re-edit instead
Review & Share — client approval without a login.
Generate a shareable approval link backed by a token-based RPC. Clients see the entire month's calendar, can approve / reject each post, leave comments. No account needed.

Each token expires in 30 days and is scoped to that brand only. Comments come back into the Pulse calendar grid in real time.
Auto Post — schedule directly to Instagram / TikTok / Facebook.
Once a post is approved, schedule it for any future date. Pulse handles the API call, image upload, caption + hashtag composition.

Available platforms depend on which OAuth integrations are connected per workspace. Failed publishes auto-retry and surface a clear error in the calendar.
Credits & Billing — exactly what each thing costs.
Every generative action costs credits. Failed jobs auto-refund. Subscription gives you a monthly bucket; top-ups available.

| Action | What you get | Cost |
|---|---|---|
| Extract Brand from URL | 30+ brand fields auto-filled | 2 cr |
| Synthesize Brand Brain | Brand canon · health score · versioned | 2 cr |
| Recalibrate dimension | Refine content / visual / video slice | 1 cr |
| Viral Research (full) | ~36 trends · 15 "why it worked" insights | 5 cr |
| Viral Research (refresh) | Re-scrape · keep insights | 3 cr |
| Generate calendar (full month) | 15–30 posts · captions · hashtags · visual briefs | 20 cr |
| Generate single post visual | 1 image per aspect ratio | 1 cr/aspect |
| Rewrite post with different angle | Caption + brief regenerated | 1 cr |
| Generate 4 ad concepts | Hero / Lifestyle / Detail / CTA | 2 cr |
| Generate ad slot image | One brand-locked still | 1 cr |
| Animate i2v · Seedance 1.5 Pro · 4s | 1280×720 · audio · brand-locked | 25 cr |
| Animate i2v · Kling 3.0 Standard · 5s | Smoother motion option | 30 cr |
| Animate i2v · Kling 3.0 Pro · 5s | Higher fidelity option | 50 cr |
| Animate i2v · Veo 3.1 Fast · 8s | 1080p, highest tier | 80 cr |
Failed generations are automatically refunded — you only pay for output you actually receive.
Admin overview — operating Pulse at scale.
The Admin sidebar item appears only for owners of platform-tier orgs (currently: AI Studio — you). It's a four-tab console for managing every demo account on the platform.

The Admin dashboard at a glance — All Accounts tab showing every demo org with live metrics.
account_tier = 'platform' AND role owner or admin. The check runs server-side via the is_platform_admin RPC — flipping the nav back on in DevTools won't grant access; the RPCs return unauthorized.
The four tabs
| Tab | What it does | When to use it |
|---|---|---|
| All accounts | Every org on the platform with live metrics (brand count vs quota, credits remaining + spent, last active, tier, suspended state). Click any row to expand inline actions. | Daily — quickly scan who's active, who's running low, who's stuck. |
| Pending signups | Demo users who verified their email but haven't been approved yet. Approve grants credits + clones the default template brand into their workspace. | Whenever the nav badge shows a number — see Part 1 below. |
| Template brands | The starter-brand library. Mark any of your existing brands as a template; new demo accounts get a full deep-copy on approval. | Once at launch — set up your default template. Update when your reference brands evolve. See Part 3. |
| Default policy | What every NEW demo signup inherits: auto-approve on/off, default credit grant, default feature flags. Per-account overrides happen in All Accounts. | Once at launch, occasionally to tune. |
Account tiers
Every organization has an account_tier that drives quota and admin visibility:
demo— public signups. Default 1 brand, 25 credits, video locked off. Subject to suspension + quota enforcement.trial— paid trial. Same as demo but you've raised brand quota / credits manually.paid— converted to paid. Quota tied to plan.platform— YOUR org. No quotas, can see admin dashboard, can approve other orgs' members.
Part 1 · Getting your first demo user.
This is the end-to-end story from the moment a stranger lands on Pulse to the moment they're using their first generated image. Every step is captured below.
Step 1 · Visitor signs up
A prospect lands on pulse-tester.netlify.app (or your branded domain) and sees the auth gate. They click "Sign up" and submit email + password.

The auth gate — Sign up / Sign in toggle. Anyone with the URL can submit; the gating happens after email verify.
Behind the scenes, submitting creates:
- An
auth.usersrow in Supabase Auth (Supabase sends the verification email automatically). - A new
organizationsrow — their own private workspace,account_tier='demo',max_brands=1. - An
organization_membersrow joining them to their new org asowner,account_type='demo',approval_status='pending'.
At this point they CAN'T sign in yet — email verification is required.
Step 2 · Visitor verifies their email
Supabase Auth sends a verification email. The user clicks the link.

Supabase Auth handles the verify-email flow automatically — the user clicks the magic link in their inbox.
Now their account is fully created and verified, but they're still in the pending approval queue. If they try to sign in, they'll see "Awaiting approval — your administrator will activate your account shortly."
Step 3 · You see the pending signup in Admin
Within a few seconds of verification, the user shows up in your Admin → Pending Signups tab. The sidebar item gets a yellow badge showing how many pending signups are waiting.

Sidebar — the Admin item shows a yellow "3" badge meaning 3 demo users are waiting for approval.
Click Admin in the sidebar, then click the Pending signups tab:

Pending signups tab — each row shows the user's email, signup time, signup source, and which default features they'd receive.
Step 4 · You click Approve
Click Approve · grant credits on the row. This is an atomic operation:
approval_statusflips to'approved', with timestamp + approver user_id logged.- A
credit_transactionsrow is inserted granting the default amount (25 credits unless you changed the policy). - The default template brand is deep-cloned into their workspace (see Part 3 for what "deep clone" copies).
- Their topbar credit pill updates instantly via Supabase Realtime — they don't need to refresh.

After Approve — a success toast confirms credits granted + template cloned. The row disappears from Pending; reappears in All Accounts.
Alternatively, click Reject to deny access. You'll be prompted for an optional reason (saved on the row for audit). The user can't sign in; their next login attempt shows "Access denied."
Step 5 · The user logs in and starts using Pulse
They sign in for the first time. Their workspace is already populated with the cloned template brand — they don't see an empty state, they see a fully-configured brand ready to generate from.

First login as a demo user — workspace already contains the cloned template (Patagonia here). No Admin sidebar item. Locked features (Video) are visibly dimmed.
That's the full lifecycle
Auto-approve mode (optional)
If you don't want manual approval — e.g. a promo push where you want zero friction — flip Auto-approve new demo signups ON in the Default Policy tab. Approval (and template clone, and credit grant) happens automatically at email verify. Skip Step 4 entirely.
Recommended: auto-approve OFF during the launch period so you can vet leads and tune your default credit grant based on early users' behaviour.
Part 2 · Day-to-day account management.
Once users are active, your daily work happens in the All Accounts tab. Every row is a complete user record — click to expand inline actions.

All Accounts — sortable by last-active (default), filterable by tier, searchable by name or email.
Reading the metrics
Each row shows:
- Account · owner email — org name + the owner's email + member count.
- Tier — colored badge: demo (gold), trial (blue), paid (green), platform (pink).
- Brands — pill showing used / quota. Turns orange when at limit.
- Credits left · spent — current balance + total spent to date. Turns orange when balance < 5.
- Last active — relative time since last credit transaction (spend or grant). "never" if they signed up but haven't used anything.
Step 1 · Expand a row
Click any row in the list. The row highlights gold and an expanded panel slides in below with three action widgets.

Expanded row showing the 3 inline action widgets — Grant credits, Brand quota, Account state.
Step 2 · Grant credits manually
A demo user has run out of their starter 25 credits and you want to extend them (sales conversation, demo extension, support gesture).

Grant credits widget — type an amount, click + Add.
- Type an amount in the input (e.g.
25). - Click + Add.
- A
credit_transactionsrow is inserted withreason='manual_topup'and metadata recording who granted it. The user's topbar pill updates via Realtime.
-10 if you over-granted by mistake. Be careful — the user may have already spent some of the credits, their balance can go negative, and new spend will fail until they're topped up.
Step 3 · Raise a brand quota
A demo user has filled their one brand slot and wants to add another. Their dashboard shows a "Brand limit reached" toast. They contact you.
In the same expanded panel:
- Find the Brand quota input — it shows the current value (e.g.
1). - Change to the new value (e.g.
3). - Click Update.
- Effect is immediate — the next brand-create attempt the user makes succeeds.
The quota is enforced at the database via a BEFORE INSERT trigger on the brands table. There's no UI workaround — a hand-crafted curl request will hit the same error.
Step 4 · Suspend an account
If a user abuses the platform (scraping at industrial scale, automation, ToS violations) you can suspend them with one click.

Suspended account — red "SUSPENDED" badge in the row, suspension reason visible in the expanded panel.
- Expand the row.
- In the Account state widget, click ⊘ Suspend.
- A prompt asks for an optional reason (e.g. "Bulk-scraping competitor profiles").
- The org's
suspendedflag flips totrue. The brand-quota trigger now raisesaccount_suspendedon any brand-create attempt — the user sees your reason in the toast.
To reinstate — same widget. Button now reads ✓ Reinstate. One click, suspended flag clears.
Step 5 · Search + filter
Use the search box at the top right to find an org by name or owner email. Use the tier dropdown to filter (e.g. show only paid accounts, or only demos in a current promo cohort).
Part 3 · Setting up the template brand.
When a demo user is approved, Pulse looks up the first brand marked as a template and deep-clones it into their workspace. They wake up with a complete brand already configured — colors, voice samples, brand brain, characters, visual references — ready to generate from.
This is the most important one-time setup step. Without a template, new demo users land on an empty Brand Guide and have to fill it in before generating anything — most will bounce.

Template brands tab — top card lists current templates with usage counts. Bottom card lets you mark any of your brands as a template.
Step 1 · Build a reference brand in your own workspace
Pick a brand that represents what your demo users will probably want to build — e.g. a high-completeness FMCG brand for retail prospects, a SaaS brand for tech prospects, etc. Build it in your own platform-tier workspace as you would normally:
- Add the brand (Brand Guide → fill identity + voice + visual identity).
- Synthesise the brand brain (push completeness above 80/100).
- Add a few visual references (mood board images, pinned references).
- Optionally add a default character.
Treat it as a finished brand you'd show a real client — that's exactly what new users will inherit.
Step 2 · Mark it as a template
In Admin → Template Brands, scroll to the bottom Mark one of your brands as a template card:
- Pick the brand from the dropdown (only your own brands appear).
- Optionally type a display label like
"KitKat — chocolate confectionery sample"(shown only to other admins). - Click Mark as template.
The brand appears in the list above with a DEFAULT · AUTO-CLONE gold badge if it's the first/oldest template.
Step 3 · What gets cloned on approval
| Table | Copied? | Notes |
|---|---|---|
brands | ✓ deep copy | Every field except identity. New ID, new org_id. template_source_id points to the source. |
brand_brain | ✓ deep copy | Entire identity/voice/visual/content_dna JSON. health_score preserved. Version reset to 1. |
brand_visual_references | ✓ deep copy | Every non-archived ref with new IDs. |
brand_characters | ✓ deep copy | Every non-archived character. usage_count reset to 0. |
posts | ✗ not copied | Empty calendar — user generates their own. |
ad_runs | ✗ not copied | User starts with zero ad runs. |
trends | ✗ not copied | User scrapes their own viral research. |
Updating templates
Templates are live brands in your workspace. Edit fields on the source — future clones reflect the change. Existing clones in user accounts are unaffected — they have their own copy.
Removing a template
Click Remove on the row. The brand stays in your workspace; it's just unflagged. Existing clones in user accounts are untouched.
created_at is the auto-clone default. Sort order in the list shows you which one wins. Future polish will add a "default toggle" to override this.
What the demo user sees.
Here's the dashboard from a demo user's seat — useful for understanding what your prospects experience and how feature gating shows up visually.
First login — workspace already configured

Demo user sees the cloned template brand in their picker. No Admin item in the sidebar (they're not a platform admin). Topbar shows their credit balance.
Locked features are visually dimmed
Sidebar items they don't have access to (e.g. Viral Research if you've disabled it for demos) appear at .45 opacity and show a tooltip on hover.

Ad Studio with Video mode locked off. The Video pill is dimmed; clicking it does nothing. The button has data-feature-locked="true" so even DevTools can't override it — the server-side gate will return 403.
Brand Book — cloned content already populated

The cloned template's Brand Book is fully rendered for the new user — colors, voice samples, products, font samples all already filled in. They can edit any field; their copy diverges from the source.
Hitting the brand quota
When a demo user tries to add a second brand and they're at max_brands=1:

Toast: "Brand limit reached — your account allows a limited number of brands. Contact your administrator to raise the limit, or upgrade your plan." The DB trigger raised brand_quota_reached; the dashboard converted it to this friendly message.
Feature flag reference.
Each demo account has a feature_flags JSON column deciding which generation features they can use. The default policy (set in the Default Policy tab) applies on signup; per-account overrides happen via the All Accounts tab.

Default Policy tab — auto-approve toggle, default credit grant, and the 7 feature flag checkboxes that apply to every new demo signup.
The seven flags
| Flag | What it controls | Default |
|---|---|---|
can_generate_image | generate-visual edge function (~1 cr/image) | ✓ on |
can_generate_video | generate-video edge function (25–80 cr/clip). Server-side enforced — 403 if off. | ✗ off |
can_use_ad_studio | Ad Studio view + generate-ad-concepts edge function | ✓ on |
can_use_calendar | Content Calendar view + generate-calendar edge function | ✓ on |
can_use_brand_book | Brand Book view | ✓ on |
can_use_viral_research | Viral Research view + scrape-trends edge function | ✓ on |
can_use_admin | Admin nav item visibility (irrelevant for demo) | ✗ off |
Server-side enforcement
The dashboard hides locked features in the UI — but that's just convenience. Truth is enforced by edge functions calling the user_can_use_feature RPC before any credit spend. If a demo user opens DevTools and tries to call generate-video directly with their JWT, they get HTTP 403:
{
"error": "feature_locked",
"reason": "demo_account_no_video_access",
"message": "Video generation is not available on your demo account. Ask your administrator to enable it, or use image generation instead."
}
Per-user override
To enable video for one specific user (without changing the org-wide default):
- Admin → Pending Signups → scroll to All demo members at the bottom.
- Filter to Approved.
- Find the user. Below their email, each flag is a checkbox.
- Tick Generate video / reels. The RPC updates their
feature_flagslive.
Tenant isolation — every user sees only their own data.
Pulse uses Postgres Row-Level Security (RLS) policies that filter every query by org membership. Demo user A cannot see demo user B's brands, posts, ad runs, or credits — at any layer, including hand-crafted REST calls.
The isolation guarantee
For every multi-tenant table (brands, posts, ad_runs, brand_brain, brand_visual_references, brand_characters, trends, credit_transactions, brand_preferences, schedules, post_comments, jobs), every SELECT/INSERT/UPDATE/DELETE policy uses the same filter:
org_id IN (SELECT user_org_ids())
where user_org_ids() is a SECURITY DEFINER function returning the set of org_ids the current authenticated user is a member of. Enforcement happens at the database — not the application — so a hand-crafted REST call with the user's JWT only sees their own rows.
The May 24 lockdown
Before launch, every multi-tenant table had a permissive anon_* policy left over from dev that returned true for any anonymous request. This was a critical pre-launch gap: an unauthenticated client could read every brand on the platform. All those policies have been dropped. Only two paths to data now exist:
- Authenticated user → member policies filter by their org membership.
- Service role (edge functions) → bypass RLS for legitimate cross-tenant work like
scrape-trendsinserts.
How to audit isolation yourself
Sign in as a demo test user and run from the browser DevTools:
const { count } = await sb.from('brands').select('id', { count:'exact', head:true });
console.log('brands visible to me:', count);
You'll see only the demo user's own brands (typically 1 — the cloned template). Try the same with an anon client (no Authorization header) — you'll see zero.
Troubleshooting common admin scenarios.
"I clicked Approve but the user still can't sign in"
Verify their email actually got verified — the auth gate blocks login until then. In Supabase Dashboard → Authentication → Users, find their email and confirm Email confirmed shows a timestamp. If not, resend the verification email from Supabase (it doesn't have a UI button in Pulse yet).
"All Accounts tab says 'You don't have platform-admin access'"
Your current session isn't recognized as a platform admin. Two possible causes:
- You're using dev=1 mode without a session. Sign in once via the real auth gate (drop the
?dev=1param), then return to?dev=1— your session token is stashed in localStorage and devBootstrap will inherit it. - Your org's account_tier isn't 'platform'. Run
SELECT account_tier FROM organizations WHERE slug='ai-studio'. Should beplatform. If not, set it.
"Approve button returns 'unauthorized'"
You're not signed in with a session that has auth.uid(). Same fix as above — sign in via the real auth gate.
"User says they can't add a second brand"
Expected — demo accounts default to max_brands=1. Raise their quota in the All Accounts expanded row.
"User says they got 'Account suspended'"
Either you (or another admin) suspended them. Look in the All Accounts list for the red SUSPENDED badge. Click the row to see the reason. Click ✓ Reinstate to undo.
"Pending signup queue is empty but I know users signed up"
Either: (a) they haven't verified their email yet — pending only shows verified users; (b) you have auto_approve_signups=true in default policy, so they were approved automatically — check All Accounts.
"Template brand wasn't cloned to a new user"
Check: (1) at least one brand has is_template=true; (2) the org's seed_brand_copied was false at approval time (the clone is idempotent — only fires once per org). If you want to re-clone, set seed_brand_copied=false on the org and re-run SELECT clone_template_brand_to_org(<template_id>, <org_id>).
SQL recipes
Direct DB queries that bypass the dashboard, for ops debugging:
-- list every demo org with usage
SELECT name, account_tier, max_brands,
(SELECT count(*) FROM brands WHERE org_id = o.id) AS brand_count,
(SELECT get_org_balance(o.id)) AS credits_left,
total_credits_spent, last_active_at, suspended
FROM organizations o WHERE account_tier = 'demo'
ORDER BY last_active_at DESC NULLS LAST;
-- per-feature spend breakdown across the platform
SELECT reason, count(*) AS calls, SUM(ABS(amount)) AS total_credits
FROM credit_transactions WHERE amount < 0
GROUP BY reason ORDER BY total_credits DESC;
-- inactive demos > 7 days, candidates for revocation
SELECT name, last_active_at, total_credits_spent
FROM organizations
WHERE account_tier = 'demo'
AND (last_active_at IS NULL OR last_active_at < now() - interval '7 days')
ORDER BY created_at DESC;
The Training Playbook — get from 60/100 to 95/100.
Pulse rewards specificity. The brands that look best on Pulse aren't necessarily the biggest brands — they're the ones whose teams took 30 minutes to write down what they already knew.
The 30-minute uplift checklist
If you only do these eight things, your brand brain jumps from generic to unmistakable.
Write your brand essence as one sentence
"Have a Break, Have a KitKat." Not "premium chocolate snack with global recognition." Use plain language. Brain reads this verbatim into every prompt.
List 3 rituals only your brand does
The snap. The pause. The break-from-life moment. These become the structural backbone of every generated concept.
Paste 5 voice samples (real captions you've shipped)
Best line you ever wrote, second-best, then 3 typical posts. Tone of voice copies these patterns directly.
List your hero campaigns by name
"KitKat Bench partnerships." "Have a Break." "Senses launch." Pulse uses these as creative direction anchors.
Define your don't-say list
Banned words, off-brand phrases. "Never say cheap. Never say AI. Never use 'unleash'." Brand brain enforces this as a hard guardrail.
Upload 3 hero photos + 1 portrait of your locked talent
The references are what stop the model from inventing fake products. Pin the best one. (Visual Style Library + Character Library)
Run "Find competitors"
Pulse picks 2–4 scale-matched competitors automatically. Confirm or replace them. Their content fuels Viral Research and benchmark anchoring.
Synthesize · 2 cr · aim for 80+ health
If health is under 80, the brain tells you which fields are still empty. Fill them, click Recalibrate (just the affected dimension), and you're done.
What "well-trained" actually looks like
The real unlock
Pulse isn't faster — it's consistent. The reason a single freelancer can hold a 30-brand book of business is because Pulse holds every brand's identity in its head between sessions. You're not re-explaining the brand to AI every time. You explained it once. It remembers.
Built by AI Studio · brand brain v6 · video pipeline v6 · scrape-trends v7
Documentation last refreshed from a live tenant — every screenshot is a real workspace, not a mockup.