Skip to content

Repository files navigation

Branda logo

Paste a public domain. Get scroll-stopping, on-brand ads in seconds.

MIT LicensePowered by Context.devPRs welcomeNext.js 15

Make it yours: fork Branda into your own ad maker, or integrate its brand-research pipeline into an existing repo. Sign up for Context.dev to get your API key, then follow the quick start.

Branda — generate on-brand ads from a public domain


Built by the Context.dev team 🥠

Branda is an open-source ad generator that turns a public website domain into four to six polished, on-brand marketing creatives. The hosted experience needs no login, brief, or settings — the domain is the only input. Branda pulls the brand's identity from the Context.dev Brand API, uses its extracted styleguide palette and Google Font when available, and grounds one to three distinct products with structured web extraction. It then morphs the page in place into a gallery: three company ads followed by one ad for each extracted product.

Paste notion.com and Branda will:

  • 🎨 Pull the brand's logo and industry plus its styleguide palette and eligible Google Font
  • 👀 Read the homepage as Markdown so the copy can reflect the brand's real voice
  • 📦 Extract one to three distinct, fact-checked products with Context.dev web.extract and a JSON Schema generated from Zod
  • 🧠 Have an LLM pick a distinct creative direction and write tailored copy for three company ads plus one ad per extracted product
  • 🖼️ Render 4–6 distinct 1:1 ads in parallel — every ad uses a different image model (OpenAI, xAI, Google, ByteDance, Recraft)
  • ⚡ Mark successful briefs and ads for shared-CDN caching to reduce duplicate generation while entries are fresh
  • 📥 Download each ad (or every finished ad) and share to X, with best-effort clipboard copying when the browser permits it

Examples

Real outputs, straight from Branda — one public domain in, 4–6 ads out:

Stripe ad generated by BrandaNotion ad generated by BrandaLinear ad generated by Branda
stripe.comnotion.comlinear.app
Vercel ad generated by BrandaOpenAI ad generated by BrandaWebflow ad generated by Branda
vercel.comopenai.comwebflow.com

Example outputs are illustrative. Product names, logos, and trademarks belong to their respective owners; their appearance here does not imply sponsorship or endorsement, and the MIT license does not grant rights to those third-party marks.


Table of contents


What you get

  • Domain → 4–6 ads, one input — no formats to pick, no messages to write, no style dropdowns. Paste a domain and the page morphs into a live gallery as each ad lands.
  • Grounded in the real brand — logo and industry come from the Brand API; colors and an eligible Google Font come from the site's extracted styleguide, not a generic palette.
  • Company plus products — every Ad Run starts with exactly three company ads, followed by one to three ads for distinct products extracted and fact-checked against the site with Context.dev.
  • 12 creative directions — an LLM picks one distinct direction per ad, then writes a tailored headline and subheadline for the company or specific product being advertised.
  • Up to 6 image models racinggpt-image-1, gpt-image-2, and grok-imagine-image take the three company slots; one to three of imagen-4.0, seedream-4.5, and recraft-v4.1 render the product slots. Every ad streams in the moment its model finishes.
  • Fact-grounded copy — company headlines draw from the real homepage, while Product headlines draw from structured extraction and prompts that require factual positioning.
  • CDN-cacheable — successful brief and ad responses include shared-cache headers, reducing duplicate generation work behind Vercel or another compatible CDN.
  • All downloadable — every ad individually, or every finished ad at once. Sharing opens the X composer and copies the first finished image when the browser supports clipboard images.

The 12 creative directions

Every generation picks 4–6 distinct directions from these:

KeyStyleBest for
product_heroEditorial product shot, dramatic studio lightingPhysical products, hardware
isometricSaaS-landing-page isometric diagramB2B SaaS, dev tools, APIs
typographicSwiss-design poster, massive typeStatement-driven or abstract products
macro_materialExtreme close-up of a material/surfaceBeauty, food, fashion, premium finishes
gradient_fieldPure atmospheric gradientAI products, fintech, abstract services
editorial_spreadMagazine spread (Kinfolk/Monocle vibe)Lifestyle, food/drink, travel
sculptural_objectAbstract 3D object in studio spaceTech/AI with no physical product
data_vizChart-as-artAnalytics, BI, observability
blueprintTechnical schematic drawingEngineering, hardware, infrastructure
retro_arcadeLate-80s neon/grid aestheticGaming, playful brands
monochrome_cropTight single-hue detail cropLuxury, watches, minimalist brands
collageCut-paper layered collageAgencies, education, media

All twelve prompt templates share a strict typography spec (the only text allowed is the headline, subheadline, and wordmark) and hard rules (no hex codes, no placeholder text, no people/faces/hands). Styleguide colors are converted to phrases like "vivid purple", because image models literally print strings like #543cfc onto the art when given raw codes. When the styleguide's primary typography references a verified Google Font, its family name is passed into every image prompt; otherwise the prompt uses a neutral sans-serif fallback.


How it works

┌──────────────┐ GET /api/brief?domain=…&v=3 ┌──────────────────┐
│ Paste domain │ ──────────────────────────▶ │ Context.dev API │
└──────────────┘ └──────────────────┘
│ brand + homepage md + styleguide palette/typography
│ + 1–3 fact-grounded products via web.extract + Zod JSON Schema
▼
┌────────────────────────────────────────────────────┐
│ one LLM call plans 3 company concepts followed by │ gpt-5.4-mini
│ 1–3 product concepts, with grounded copy for each; │
│ distinct models: 3 primary, then 1–3 secondary │
└────────────────────────────────────────────────────┘
│ { brief, concepts[4..6] } ← cached on Vercel CDN
▼
4–6 × GET /api/ad?domain=…&concept=…&model=…&headline=…
│ each returns one 1:1 image ← cached on Vercel CDN
▼
Ads stream into the gallery · Download · Share on X
  1. The briefGET /api/brief makes four Context.dev calls in parallel: Brand data, homepage Markdown, styleguide extraction, and structured web extraction. Product extraction uses a JSON Schema generated from Zod and Context.dev fact checking. The planner derives two describable colors from the styleguide's accent/background/text palette and carries a typography family only when the styleguide marks it as a Google Font. One LLM call then writes three company concepts followed by one concept for each of the one to three distinct Products. Successful responses are shared-cacheable per versioned domain key (s-maxage=3600, one-day stale-while-revalidate).
  2. The ads — the client fires 4–6 parallel GET /api/ad requests, one per Planned Concept. Everything the prompt needs — including whether the subject is the company or a specific Product — travels in the query string, so compatible CDNs can cache each finished image by its full URL (s-maxage=86400, seven-day stale-while-revalidate). The three primary models can receive a validated raster logo as an image reference; unsupported or rejected logo inputs fall back to text-only generation. Transient failures retry with backoff; failed slots expose a per-ad Retry button, and errors are never cached.
  3. Ship — each ad fades into the dynamically sized gallery as its model finishes. Download one, download every finished ad, or share to X.

Context.dev APIs used

Branda makes exactly four Context.dev calls, all isolated in src/lib/context.ts. These links are the canonical API pages listed in the Context.dev documentation sitemap.

SDK operationWhat Branda uses it forAPI reference
client.brand.retrieveBrand name, description, slogan, industry, and logoRetrieve Brand Data
client.web.webScrapeMdHomepage Markdown for grounded company copy and reachability checksScrape Markdown
client.web.extractStyleguideAccent/background/text colors, visual mood, and eligible Google Font metadataExtract Styleguide
client.web.extractOne to three Products against a Zod-derived JSON Schema, with fact checkingExtract Structured Data

Want to use the same APIs in your own app? Create a Context.dev API key.


Quick start

Prerequisites:

# 1. Clone
git clone https://github.com/context-dot-dev/ad-maker.git
cd ad-maker
# 2. Install
npm install
# 3. Configure
cp .env.example .env
# add CONTEXT_DEV_API_KEY and AI_GATEWAY_API_KEY to .env# 4. Run
npm run dev # http://localhost:3000

Open http://localhost:3000, paste a domain, and watch 4–6 ads roll in. That's it.

Note

A single Vercel AI Gateway key serves everything Branda uses — concept picking, copy, and up to six image models — from one credit balance, with no per-provider keys to manage.


Configuration

All configuration is environment variables (see .env.example).

VariableRequiredDescription
CONTEXT_DEV_API_KEYYesContext.dev key — powers all four Context.dev API calls
AI_GATEWAY_API_KEYYesVercel AI Gateway key — powers concept picking + copy (gpt-5.4-mini) and up to six image models

API keys are read only by server code. Never prefix either secret with NEXT_PUBLIC_, commit .env, or paste a key into an issue, log, or screenshot.


Customize or integrate

The UI and renderer are separable from Context.dev enrichment, so you can reuse the adapter without adopting the gallery or image-generation stack.


Deploy safely

npm run build && npm run start runs the production app. On Vercel, import the repo and set the two required environment variables; the route hints allow up to 120 seconds for brief planning and 300 seconds for image rendering, so other hosts need equivalent request limits.

The included /api/brief and /api/ad routes invoke billable services and are intentionally callable by the browser. Before exposing your own deployment, add authentication and/or rate limiting appropriate to your audience, set provider spend alerts, and understand the cost of up to four Context.dev calls, one text-model call, and six image-model calls per uncached Ad Run. Successful responses benefit from a compatible shared CDN cache; failures use no-store.

The app loads Plausible (privacy-friendly, cookieless analytics) via a script tag in src/app/layout.tsx; forks should swap in their own Plausible script URL or remove the tag. The default UI also requests a Google-hosted font and Google favicon service; privacy-sensitive forks can self-host or remove those requests.


Scripts

CommandWhat it does
npm run devStart the Next.js dev server
npm run build / npm run startProduction build / serve
npm run typecheckTypeScript checks
npm testRun the interface and policy test suite
npm run test:watchRun tests in watch mode while developing
npm run verifyRun type checks, tests, and the production build

Project structure

The canonical domain language and module relationships live in CONTEXT.md.

src/
app/
api/
brief/route.ts # domain → brand + products + 4–6 concepts w/ copy (CDN-cached)
ad/route.ts # one concept → one 1:1 ad image (CDN-cached by URL)
page.tsx # the single page — hero morphs into the gallery
components/
ad-maker.tsx # hero, brand bar, progress, dynamic 4–6-slot gallery
hooks/
use-ad-maker.ts # legal Gallery stages, parallel rendering, retries, URL ownership
lib/
ad-run-policy.ts # run composition, ordering, and shared field limits
ad-run.ts # shared Ad Run contract, invariants, and canonical GET codecs
brand-color.ts # canonical Brand color validation
font-family.ts # safe styleguide Google Font family validation
context.ts # Context.dev Brand, page, styleguide, and Product adapter
net.ts # canonical domain normalization
public-raster.ts # DNS-pinned, size-bounded public logo loading
public-url.ts # cross-runtime public URL syntax policy
generate/
directions.ts # cross-runtime Creative Direction catalog
models.ts # Image Model tiers, names, and capabilities
concepts.ts # server-only prompt implementations
brief.ts # homepage summary + concept copywriting
colors.ts # hex → describable color phrases
gateway.ts # internal Vercel AI Gateway adapter
planner.ts # domain → validated Brief + 4–6 Planned Concepts
renderer.ts # one Planned Concept → retried Rendered Ad
public/ # logo, cover, ad examples

Tech stack

  • Next.js 15 (App Router) + React 19 + TypeScript
  • Context.devBrand data, homepage Markdown, styleguide extraction, and structured Product extraction
  • 🤖 Vercel AI SDK + AI Gatewaygpt-5.4-mini for concept picking & copy; gpt-image-1, gpt-image-2, grok-imagine-image, imagen-4.0, seedream-4.5, and recraft-v4.1 for the ads (one per ad)
  • 🌍 Vercel CDN — briefs and finished ads cached at the edge via Cache-Control: s-maxage
  • 🎨 Tailwind CSS + Geist font

Contributing

Contributions are very welcome — new creative directions, better prompts, alternative image models, UI polish, you name it.

  1. Fork the repo and create a branch: git checkout -b feat/my-feature
  2. Make your change — keep it focused; small PRs get reviewed fast
  3. Check it passesnpm run verify
  4. Open a PR describing what changed and why (screenshots or generated ads are a huge plus)

Found a bug or have an idea? Open an issue — no contribution is too small.

See CONTRIBUTING.md for the full guide.


Built using Context.dev

Branda gets its Brand metadata, logos, colors, homepage content, visual styleguide, and fact-grounded Products from a single API. Want to build your own brand-aware tool or agent?

importContextDevfrom"context.dev";import{zodSchema}from"ai";import{z}from"zod";constclient=newContextDev({apiKey: process.env.CONTEXT_DEV_API_KEY});constproductExtraction=z.object({products: z.array(z.object({name: z.string(),description: z.string(),}),).min(1).max(3),});constschema=awaitzodSchema(productExtraction).jsonSchema;const[brand,homepage,styleguide,productData]=awaitPromise.all([client.brand.retrieve({type: "by_domain",domain: "notion.com"}),client.web.webScrapeMd({url: "https://notion.com",useMainContentOnly: true,}),client.web.extractStyleguide({domain: "notion.com"}),client.web.extract({url: "https://notion.com",
schema,factCheck: true,}),]);const{ products }=productExtraction.parse(productData.data);

👉 Get your free API key →


License

MIT © Context.dev

Built with 🥠 by the Context.dev team.


Make it yours

Fork Branda to launch your own version, or copy the Context.dev adapter into an app you already maintain. Sign up for Context.dev and get your API key to start building.

About

MIT license open source ad maker

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - context-dot-dev/ad-maker: MIT license open source ad maker · GitHub
Skip to content

Repository files navigation

Branda logo

Paste a public domain. Get scroll-stopping, on-brand ads in seconds.

MIT LicensePowered by Context.devPRs welcomeNext.js 15

Make it yours: fork Branda into your own ad maker, or integrate its brand-research pipeline into an existing repo. Sign up for Context.dev to get your API key, then follow the quick start.

Branda — generate on-brand ads from a public domain


Built by the Context.dev team 🥠

Branda is an open-source ad generator that turns a public website domain into four to six polished, on-brand marketing creatives. The hosted experience needs no login, brief, or settings — the domain is the only input. Branda pulls the brand's identity from the Context.dev Brand API, uses its extracted styleguide palette and Google Font when available, and grounds one to three distinct products with structured web extraction. It then morphs the page in place into a gallery: three company ads followed by one ad for each extracted product.

Paste notion.com and Branda will:

  • 🎨 Pull the brand's logo and industry plus its styleguide palette and eligible Google Font
  • 👀 Read the homepage as Markdown so the copy can reflect the brand's real voice
  • 📦 Extract one to three distinct, fact-checked products with Context.dev web.extract and a JSON Schema generated from Zod
  • 🧠 Have an LLM pick a distinct creative direction and write tailored copy for three company ads plus one ad per extracted product
  • 🖼️ Render 4–6 distinct 1:1 ads in parallel — every ad uses a different image model (OpenAI, xAI, Google, ByteDance, Recraft)
  • ⚡ Mark successful briefs and ads for shared-CDN caching to reduce duplicate generation while entries are fresh
  • 📥 Download each ad (or every finished ad) and share to X, with best-effort clipboard copying when the browser permits it

Examples

Real outputs, straight from Branda — one public domain in, 4–6 ads out:

Stripe ad generated by BrandaNotion ad generated by BrandaLinear ad generated by Branda
stripe.comnotion.comlinear.app
Vercel ad generated by BrandaOpenAI ad generated by BrandaWebflow ad generated by Branda
vercel.comopenai.comwebflow.com

Example outputs are illustrative. Product names, logos, and trademarks belong to their respective owners; their appearance here does not imply sponsorship or endorsement, and the MIT license does not grant rights to those third-party marks.


Table of contents


What you get

  • Domain → 4–6 ads, one input — no formats to pick, no messages to write, no style dropdowns. Paste a domain and the page morphs into a live gallery as each ad lands.
  • Grounded in the real brand — logo and industry come from the Brand API; colors and an eligible Google Font come from the site's extracted styleguide, not a generic palette.
  • Company plus products — every Ad Run starts with exactly three company ads, followed by one to three ads for distinct products extracted and fact-checked against the site with Context.dev.
  • 12 creative directions — an LLM picks one distinct direction per ad, then writes a tailored headline and subheadline for the company or specific product being advertised.
  • Up to 6 image models racinggpt-image-1, gpt-image-2, and grok-imagine-image take the three company slots; one to three of imagen-4.0, seedream-4.5, and recraft-v4.1 render the product slots. Every ad streams in the moment its model finishes.
  • Fact-grounded copy — company headlines draw from the real homepage, while Product headlines draw from structured extraction and prompts that require factual positioning.
  • CDN-cacheable — successful brief and ad responses include shared-cache headers, reducing duplicate generation work behind Vercel or another compatible CDN.
  • All downloadable — every ad individually, or every finished ad at once. Sharing opens the X composer and copies the first finished image when the browser supports clipboard images.

The 12 creative directions

Every generation picks 4–6 distinct directions from these:

KeyStyleBest for
product_heroEditorial product shot, dramatic studio lightingPhysical products, hardware
isometricSaaS-landing-page isometric diagramB2B SaaS, dev tools, APIs
typographicSwiss-design poster, massive typeStatement-driven or abstract products
macro_materialExtreme close-up of a material/surfaceBeauty, food, fashion, premium finishes
gradient_fieldPure atmospheric gradientAI products, fintech, abstract services
editorial_spreadMagazine spread (Kinfolk/Monocle vibe)Lifestyle, food/drink, travel
sculptural_objectAbstract 3D object in studio spaceTech/AI with no physical product
data_vizChart-as-artAnalytics, BI, observability
blueprintTechnical schematic drawingEngineering, hardware, infrastructure
retro_arcadeLate-80s neon/grid aestheticGaming, playful brands
monochrome_cropTight single-hue detail cropLuxury, watches, minimalist brands
collageCut-paper layered collageAgencies, education, media

All twelve prompt templates share a strict typography spec (the only text allowed is the headline, subheadline, and wordmark) and hard rules (no hex codes, no placeholder text, no people/faces/hands). Styleguide colors are converted to phrases like "vivid purple", because image models literally print strings like #543cfc onto the art when given raw codes. When the styleguide's primary typography references a verified Google Font, its family name is passed into every image prompt; otherwise the prompt uses a neutral sans-serif fallback.


How it works

┌──────────────┐ GET /api/brief?domain=…&v=3 ┌──────────────────┐
│ Paste domain │ ──────────────────────────▶ │ Context.dev API │
└──────────────┘ └──────────────────┘
│ brand + homepage md + styleguide palette/typography
│ + 1–3 fact-grounded products via web.extract + Zod JSON Schema
▼
┌────────────────────────────────────────────────────┐
│ one LLM call plans 3 company concepts followed by │ gpt-5.4-mini
│ 1–3 product concepts, with grounded copy for each; │
│ distinct models: 3 primary, then 1–3 secondary │
└────────────────────────────────────────────────────┘
│ { brief, concepts[4..6] } ← cached on Vercel CDN
▼
4–6 × GET /api/ad?domain=…&concept=…&model=…&headline=…
│ each returns one 1:1 image ← cached on Vercel CDN
▼
Ads stream into the gallery · Download · Share on X
  1. The briefGET /api/brief makes four Context.dev calls in parallel: Brand data, homepage Markdown, styleguide extraction, and structured web extraction. Product extraction uses a JSON Schema generated from Zod and Context.dev fact checking. The planner derives two describable colors from the styleguide's accent/background/text palette and carries a typography family only when the styleguide marks it as a Google Font. One LLM call then writes three company concepts followed by one concept for each of the one to three distinct Products. Successful responses are shared-cacheable per versioned domain key (s-maxage=3600, one-day stale-while-revalidate).
  2. The ads — the client fires 4–6 parallel GET /api/ad requests, one per Planned Concept. Everything the prompt needs — including whether the subject is the company or a specific Product — travels in the query string, so compatible CDNs can cache each finished image by its full URL (s-maxage=86400, seven-day stale-while-revalidate). The three primary models can receive a validated raster logo as an image reference; unsupported or rejected logo inputs fall back to text-only generation. Transient failures retry with backoff; failed slots expose a per-ad Retry button, and errors are never cached.
  3. Ship — each ad fades into the dynamically sized gallery as its model finishes. Download one, download every finished ad, or share to X.

Context.dev APIs used

Branda makes exactly four Context.dev calls, all isolated in src/lib/context.ts. These links are the canonical API pages listed in the Context.dev documentation sitemap.

SDK operationWhat Branda uses it forAPI reference
client.brand.retrieveBrand name, description, slogan, industry, and logoRetrieve Brand Data
client.web.webScrapeMdHomepage Markdown for grounded company copy and reachability checksScrape Markdown
client.web.extractStyleguideAccent/background/text colors, visual mood, and eligible Google Font metadataExtract Styleguide
client.web.extractOne to three Products against a Zod-derived JSON Schema, with fact checkingExtract Structured Data

Want to use the same APIs in your own app? Create a Context.dev API key.


Quick start

Prerequisites:

# 1. Clone
git clone https://github.com/context-dot-dev/ad-maker.git
cd ad-maker
# 2. Install
npm install
# 3. Configure
cp .env.example .env
# add CONTEXT_DEV_API_KEY and AI_GATEWAY_API_KEY to .env# 4. Run
npm run dev # http://localhost:3000

Open http://localhost:3000, paste a domain, and watch 4–6 ads roll in. That's it.

Note

A single Vercel AI Gateway key serves everything Branda uses — concept picking, copy, and up to six image models — from one credit balance, with no per-provider keys to manage.


Configuration

All configuration is environment variables (see .env.example).

VariableRequiredDescription
CONTEXT_DEV_API_KEYYesContext.dev key — powers all four Context.dev API calls
AI_GATEWAY_API_KEYYesVercel AI Gateway key — powers concept picking + copy (gpt-5.4-mini) and up to six image models

API keys are read only by server code. Never prefix either secret with NEXT_PUBLIC_, commit .env, or paste a key into an issue, log, or screenshot.


Customize or integrate

The UI and renderer are separable from Context.dev enrichment, so you can reuse the adapter without adopting the gallery or image-generation stack.


Deploy safely

npm run build && npm run start runs the production app. On Vercel, import the repo and set the two required environment variables; the route hints allow up to 120 seconds for brief planning and 300 seconds for image rendering, so other hosts need equivalent request limits.

The included /api/brief and /api/ad routes invoke billable services and are intentionally callable by the browser. Before exposing your own deployment, add authentication and/or rate limiting appropriate to your audience, set provider spend alerts, and understand the cost of up to four Context.dev calls, one text-model call, and six image-model calls per uncached Ad Run. Successful responses benefit from a compatible shared CDN cache; failures use no-store.

The app loads Plausible (privacy-friendly, cookieless analytics) via a script tag in src/app/layout.tsx; forks should swap in their own Plausible script URL or remove the tag. The default UI also requests a Google-hosted font and Google favicon service; privacy-sensitive forks can self-host or remove those requests.


Scripts

CommandWhat it does
npm run devStart the Next.js dev server
npm run build / npm run startProduction build / serve
npm run typecheckTypeScript checks
npm testRun the interface and policy test suite
npm run test:watchRun tests in watch mode while developing
npm run verifyRun type checks, tests, and the production build

Project structure

The canonical domain language and module relationships live in CONTEXT.md.

src/
app/
api/
brief/route.ts # domain → brand + products + 4–6 concepts w/ copy (CDN-cached)
ad/route.ts # one concept → one 1:1 ad image (CDN-cached by URL)
page.tsx # the single page — hero morphs into the gallery
components/
ad-maker.tsx # hero, brand bar, progress, dynamic 4–6-slot gallery
hooks/
use-ad-maker.ts # legal Gallery stages, parallel rendering, retries, URL ownership
lib/
ad-run-policy.ts # run composition, ordering, and shared field limits
ad-run.ts # shared Ad Run contract, invariants, and canonical GET codecs
brand-color.ts # canonical Brand color validation
font-family.ts # safe styleguide Google Font family validation
context.ts # Context.dev Brand, page, styleguide, and Product adapter
net.ts # canonical domain normalization
public-raster.ts # DNS-pinned, size-bounded public logo loading
public-url.ts # cross-runtime public URL syntax policy
generate/
directions.ts # cross-runtime Creative Direction catalog
models.ts # Image Model tiers, names, and capabilities
concepts.ts # server-only prompt implementations
brief.ts # homepage summary + concept copywriting
colors.ts # hex → describable color phrases
gateway.ts # internal Vercel AI Gateway adapter
planner.ts # domain → validated Brief + 4–6 Planned Concepts
renderer.ts # one Planned Concept → retried Rendered Ad
public/ # logo, cover, ad examples

Tech stack

  • Next.js 15 (App Router) + React 19 + TypeScript
  • Context.devBrand data, homepage Markdown, styleguide extraction, and structured Product extraction
  • 🤖 Vercel AI SDK + AI Gatewaygpt-5.4-mini for concept picking & copy; gpt-image-1, gpt-image-2, grok-imagine-image, imagen-4.0, seedream-4.5, and recraft-v4.1 for the ads (one per ad)
  • 🌍 Vercel CDN — briefs and finished ads cached at the edge via Cache-Control: s-maxage
  • 🎨 Tailwind CSS + Geist font

Contributing

Contributions are very welcome — new creative directions, better prompts, alternative image models, UI polish, you name it.

  1. Fork the repo and create a branch: git checkout -b feat/my-feature
  2. Make your change — keep it focused; small PRs get reviewed fast
  3. Check it passesnpm run verify
  4. Open a PR describing what changed and why (screenshots or generated ads are a huge plus)

Found a bug or have an idea? Open an issue — no contribution is too small.

See CONTRIBUTING.md for the full guide.


Built using Context.dev

Branda gets its Brand metadata, logos, colors, homepage content, visual styleguide, and fact-grounded Products from a single API. Want to build your own brand-aware tool or agent?

importContextDevfrom"context.dev";import{zodSchema}from"ai";import{z}from"zod";constclient=newContextDev({apiKey: process.env.CONTEXT_DEV_API_KEY});constproductExtraction=z.object({products: z.array(z.object({name: z.string(),description: z.string(),}),).min(1).max(3),});constschema=awaitzodSchema(productExtraction).jsonSchema;const[brand,homepage,styleguide,productData]=awaitPromise.all([client.brand.retrieve({type: "by_domain",domain: "notion.com"}),client.web.webScrapeMd({url: "https://notion.com",useMainContentOnly: true,}),client.web.extractStyleguide({domain: "notion.com"}),client.web.extract({url: "https://notion.com",
schema,factCheck: true,}),]);const{ products }=productExtraction.parse(productData.data);

👉 Get your free API key →


License

MIT © Context.dev

Built with 🥠 by the Context.dev team.


Make it yours

Fork Branda to launch your own version, or copy the Context.dev adapter into an app you already maintain. Sign up for Context.dev and get your API key to start building.

About

MIT license open source ad maker

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - context-dot-dev/ad-maker: MIT license open source ad maker · GitHub
Skip to content

Repository files navigation

Branda logo

Paste a public domain. Get scroll-stopping, on-brand ads in seconds.

MIT LicensePowered by Context.devPRs welcomeNext.js 15

Make it yours: fork Branda into your own ad maker, or integrate its brand-research pipeline into an existing repo. Sign up for Context.dev to get your API key, then follow the quick start.

Branda — generate on-brand ads from a public domain


Built by the Context.dev team 🥠

Branda is an open-source ad generator that turns a public website domain into four to six polished, on-brand marketing creatives. The hosted experience needs no login, brief, or settings — the domain is the only input. Branda pulls the brand's identity from the Context.dev Brand API, uses its extracted styleguide palette and Google Font when available, and grounds one to three distinct products with structured web extraction. It then morphs the page in place into a gallery: three company ads followed by one ad for each extracted product.

Paste notion.com and Branda will:

  • 🎨 Pull the brand's logo and industry plus its styleguide palette and eligible Google Font
  • 👀 Read the homepage as Markdown so the copy can reflect the brand's real voice
  • 📦 Extract one to three distinct, fact-checked products with Context.dev web.extract and a JSON Schema generated from Zod
  • 🧠 Have an LLM pick a distinct creative direction and write tailored copy for three company ads plus one ad per extracted product
  • 🖼️ Render 4–6 distinct 1:1 ads in parallel — every ad uses a different image model (OpenAI, xAI, Google, ByteDance, Recraft)
  • ⚡ Mark successful briefs and ads for shared-CDN caching to reduce duplicate generation while entries are fresh
  • 📥 Download each ad (or every finished ad) and share to X, with best-effort clipboard copying when the browser permits it

Examples

Real outputs, straight from Branda — one public domain in, 4–6 ads out:

Stripe ad generated by BrandaNotion ad generated by BrandaLinear ad generated by Branda
stripe.comnotion.comlinear.app
Vercel ad generated by BrandaOpenAI ad generated by BrandaWebflow ad generated by Branda
vercel.comopenai.comwebflow.com

Example outputs are illustrative. Product names, logos, and trademarks belong to their respective owners; their appearance here does not imply sponsorship or endorsement, and the MIT license does not grant rights to those third-party marks.


Table of contents


What you get

  • Domain → 4–6 ads, one input — no formats to pick, no messages to write, no style dropdowns. Paste a domain and the page morphs into a live gallery as each ad lands.
  • Grounded in the real brand — logo and industry come from the Brand API; colors and an eligible Google Font come from the site's extracted styleguide, not a generic palette.
  • Company plus products — every Ad Run starts with exactly three company ads, followed by one to three ads for distinct products extracted and fact-checked against the site with Context.dev.
  • 12 creative directions — an LLM picks one distinct direction per ad, then writes a tailored headline and subheadline for the company or specific product being advertised.
  • Up to 6 image models racinggpt-image-1, gpt-image-2, and grok-imagine-image take the three company slots; one to three of imagen-4.0, seedream-4.5, and recraft-v4.1 render the product slots. Every ad streams in the moment its model finishes.
  • Fact-grounded copy — company headlines draw from the real homepage, while Product headlines draw from structured extraction and prompts that require factual positioning.
  • CDN-cacheable — successful brief and ad responses include shared-cache headers, reducing duplicate generation work behind Vercel or another compatible CDN.
  • All downloadable — every ad individually, or every finished ad at once. Sharing opens the X composer and copies the first finished image when the browser supports clipboard images.

The 12 creative directions

Every generation picks 4–6 distinct directions from these:

KeyStyleBest for
product_heroEditorial product shot, dramatic studio lightingPhysical products, hardware
isometricSaaS-landing-page isometric diagramB2B SaaS, dev tools, APIs
typographicSwiss-design poster, massive typeStatement-driven or abstract products
macro_materialExtreme close-up of a material/surfaceBeauty, food, fashion, premium finishes
gradient_fieldPure atmospheric gradientAI products, fintech, abstract services
editorial_spreadMagazine spread (Kinfolk/Monocle vibe)Lifestyle, food/drink, travel
sculptural_objectAbstract 3D object in studio spaceTech/AI with no physical product
data_vizChart-as-artAnalytics, BI, observability
blueprintTechnical schematic drawingEngineering, hardware, infrastructure
retro_arcadeLate-80s neon/grid aestheticGaming, playful brands
monochrome_cropTight single-hue detail cropLuxury, watches, minimalist brands
collageCut-paper layered collageAgencies, education, media

All twelve prompt templates share a strict typography spec (the only text allowed is the headline, subheadline, and wordmark) and hard rules (no hex codes, no placeholder text, no people/faces/hands). Styleguide colors are converted to phrases like "vivid purple", because image models literally print strings like #543cfc onto the art when given raw codes. When the styleguide's primary typography references a verified Google Font, its family name is passed into every image prompt; otherwise the prompt uses a neutral sans-serif fallback.


How it works

┌──────────────┐ GET /api/brief?domain=…&v=3 ┌──────────────────┐
│ Paste domain │ ──────────────────────────▶ │ Context.dev API │
└──────────────┘ └──────────────────┘
│ brand + homepage md + styleguide palette/typography
│ + 1–3 fact-grounded products via web.extract + Zod JSON Schema
▼
┌────────────────────────────────────────────────────┐
│ one LLM call plans 3 company concepts followed by │ gpt-5.4-mini
│ 1–3 product concepts, with grounded copy for each; │
│ distinct models: 3 primary, then 1–3 secondary │
└────────────────────────────────────────────────────┘
│ { brief, concepts[4..6] } ← cached on Vercel CDN
▼
4–6 × GET /api/ad?domain=…&concept=…&model=…&headline=…
│ each returns one 1:1 image ← cached on Vercel CDN
▼
Ads stream into the gallery · Download · Share on X
  1. The briefGET /api/brief makes four Context.dev calls in parallel: Brand data, homepage Markdown, styleguide extraction, and structured web extraction. Product extraction uses a JSON Schema generated from Zod and Context.dev fact checking. The planner derives two describable colors from the styleguide's accent/background/text palette and carries a typography family only when the styleguide marks it as a Google Font. One LLM call then writes three company concepts followed by one concept for each of the one to three distinct Products. Successful responses are shared-cacheable per versioned domain key (s-maxage=3600, one-day stale-while-revalidate).
  2. The ads — the client fires 4–6 parallel GET /api/ad requests, one per Planned Concept. Everything the prompt needs — including whether the subject is the company or a specific Product — travels in the query string, so compatible CDNs can cache each finished image by its full URL (s-maxage=86400, seven-day stale-while-revalidate). The three primary models can receive a validated raster logo as an image reference; unsupported or rejected logo inputs fall back to text-only generation. Transient failures retry with backoff; failed slots expose a per-ad Retry button, and errors are never cached.
  3. Ship — each ad fades into the dynamically sized gallery as its model finishes. Download one, download every finished ad, or share to X.

Context.dev APIs used

Branda makes exactly four Context.dev calls, all isolated in src/lib/context.ts. These links are the canonical API pages listed in the Context.dev documentation sitemap.

SDK operationWhat Branda uses it forAPI reference
client.brand.retrieveBrand name, description, slogan, industry, and logoRetrieve Brand Data
client.web.webScrapeMdHomepage Markdown for grounded company copy and reachability checksScrape Markdown
client.web.extractStyleguideAccent/background/text colors, visual mood, and eligible Google Font metadataExtract Styleguide
client.web.extractOne to three Products against a Zod-derived JSON Schema, with fact checkingExtract Structured Data

Want to use the same APIs in your own app? Create a Context.dev API key.


Quick start

Prerequisites:

# 1. Clone
git clone https://github.com/context-dot-dev/ad-maker.git
cd ad-maker
# 2. Install
npm install
# 3. Configure
cp .env.example .env
# add CONTEXT_DEV_API_KEY and AI_GATEWAY_API_KEY to .env# 4. Run
npm run dev # http://localhost:3000

Open http://localhost:3000, paste a domain, and watch 4–6 ads roll in. That's it.

Note

A single Vercel AI Gateway key serves everything Branda uses — concept picking, copy, and up to six image models — from one credit balance, with no per-provider keys to manage.


Configuration

All configuration is environment variables (see .env.example).

VariableRequiredDescription
CONTEXT_DEV_API_KEYYesContext.dev key — powers all four Context.dev API calls
AI_GATEWAY_API_KEYYesVercel AI Gateway key — powers concept picking + copy (gpt-5.4-mini) and up to six image models

API keys are read only by server code. Never prefix either secret with NEXT_PUBLIC_, commit .env, or paste a key into an issue, log, or screenshot.


Customize or integrate

The UI and renderer are separable from Context.dev enrichment, so you can reuse the adapter without adopting the gallery or image-generation stack.


Deploy safely

npm run build && npm run start runs the production app. On Vercel, import the repo and set the two required environment variables; the route hints allow up to 120 seconds for brief planning and 300 seconds for image rendering, so other hosts need equivalent request limits.

The included /api/brief and /api/ad routes invoke billable services and are intentionally callable by the browser. Before exposing your own deployment, add authentication and/or rate limiting appropriate to your audience, set provider spend alerts, and understand the cost of up to four Context.dev calls, one text-model call, and six image-model calls per uncached Ad Run. Successful responses benefit from a compatible shared CDN cache; failures use no-store.

The app loads Plausible (privacy-friendly, cookieless analytics) via a script tag in src/app/layout.tsx; forks should swap in their own Plausible script URL or remove the tag. The default UI also requests a Google-hosted font and Google favicon service; privacy-sensitive forks can self-host or remove those requests.


Scripts

CommandWhat it does
npm run devStart the Next.js dev server
npm run build / npm run startProduction build / serve
npm run typecheckTypeScript checks
npm testRun the interface and policy test suite
npm run test:watchRun tests in watch mode while developing
npm run verifyRun type checks, tests, and the production build

Project structure

The canonical domain language and module relationships live in CONTEXT.md.

src/
app/
api/
brief/route.ts # domain → brand + products + 4–6 concepts w/ copy (CDN-cached)
ad/route.ts # one concept → one 1:1 ad image (CDN-cached by URL)
page.tsx # the single page — hero morphs into the gallery
components/
ad-maker.tsx # hero, brand bar, progress, dynamic 4–6-slot gallery
hooks/
use-ad-maker.ts # legal Gallery stages, parallel rendering, retries, URL ownership
lib/
ad-run-policy.ts # run composition, ordering, and shared field limits
ad-run.ts # shared Ad Run contract, invariants, and canonical GET codecs
brand-color.ts # canonical Brand color validation
font-family.ts # safe styleguide Google Font family validation
context.ts # Context.dev Brand, page, styleguide, and Product adapter
net.ts # canonical domain normalization
public-raster.ts # DNS-pinned, size-bounded public logo loading
public-url.ts # cross-runtime public URL syntax policy
generate/
directions.ts # cross-runtime Creative Direction catalog
models.ts # Image Model tiers, names, and capabilities
concepts.ts # server-only prompt implementations
brief.ts # homepage summary + concept copywriting
colors.ts # hex → describable color phrases
gateway.ts # internal Vercel AI Gateway adapter
planner.ts # domain → validated Brief + 4–6 Planned Concepts
renderer.ts # one Planned Concept → retried Rendered Ad
public/ # logo, cover, ad examples

Tech stack

  • Next.js 15 (App Router) + React 19 + TypeScript
  • Context.devBrand data, homepage Markdown, styleguide extraction, and structured Product extraction
  • 🤖 Vercel AI SDK + AI Gatewaygpt-5.4-mini for concept picking & copy; gpt-image-1, gpt-image-2, grok-imagine-image, imagen-4.0, seedream-4.5, and recraft-v4.1 for the ads (one per ad)
  • 🌍 Vercel CDN — briefs and finished ads cached at the edge via Cache-Control: s-maxage
  • 🎨 Tailwind CSS + Geist font

Contributing

Contributions are very welcome — new creative directions, better prompts, alternative image models, UI polish, you name it.

  1. Fork the repo and create a branch: git checkout -b feat/my-feature
  2. Make your change — keep it focused; small PRs get reviewed fast
  3. Check it passesnpm run verify
  4. Open a PR describing what changed and why (screenshots or generated ads are a huge plus)

Found a bug or have an idea? Open an issue — no contribution is too small.

See CONTRIBUTING.md for the full guide.


Built using Context.dev

Branda gets its Brand metadata, logos, colors, homepage content, visual styleguide, and fact-grounded Products from a single API. Want to build your own brand-aware tool or agent?

importContextDevfrom"context.dev";import{zodSchema}from"ai";import{z}from"zod";constclient=newContextDev({apiKey: process.env.CONTEXT_DEV_API_KEY});constproductExtraction=z.object({products: z.array(z.object({name: z.string(),description: z.string(),}),).min(1).max(3),});constschema=awaitzodSchema(productExtraction).jsonSchema;const[brand,homepage,styleguide,productData]=awaitPromise.all([client.brand.retrieve({type: "by_domain",domain: "notion.com"}),client.web.webScrapeMd({url: "https://notion.com",useMainContentOnly: true,}),client.web.extractStyleguide({domain: "notion.com"}),client.web.extract({url: "https://notion.com",
schema,factCheck: true,}),]);const{ products }=productExtraction.parse(productData.data);

👉 Get your free API key →


License

MIT © Context.dev

Built with 🥠 by the Context.dev team.


Make it yours

Fork Branda to launch your own version, or copy the Context.dev adapter into an app you already maintain. Sign up for Context.dev and get your API key to start building.

About

MIT license open source ad maker

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - context-dot-dev/ad-maker: MIT license open source ad maker · GitHub
Skip to content

Repository files navigation

Branda logo

Paste a public domain. Get scroll-stopping, on-brand ads in seconds.

MIT LicensePowered by Context.devPRs welcomeNext.js 15

Make it yours: fork Branda into your own ad maker, or integrate its brand-research pipeline into an existing repo. Sign up for Context.dev to get your API key, then follow the quick start.

Branda — generate on-brand ads from a public domain


Built by the Context.dev team 🥠

Branda is an open-source ad generator that turns a public website domain into four to six polished, on-brand marketing creatives. The hosted experience needs no login, brief, or settings — the domain is the only input. Branda pulls the brand's identity from the Context.dev Brand API, uses its extracted styleguide palette and Google Font when available, and grounds one to three distinct products with structured web extraction. It then morphs the page in place into a gallery: three company ads followed by one ad for each extracted product.

Paste notion.com and Branda will:

  • 🎨 Pull the brand's logo and industry plus its styleguide palette and eligible Google Font
  • 👀 Read the homepage as Markdown so the copy can reflect the brand's real voice
  • 📦 Extract one to three distinct, fact-checked products with Context.dev web.extract and a JSON Schema generated from Zod
  • 🧠 Have an LLM pick a distinct creative direction and write tailored copy for three company ads plus one ad per extracted product
  • 🖼️ Render 4–6 distinct 1:1 ads in parallel — every ad uses a different image model (OpenAI, xAI, Google, ByteDance, Recraft)
  • ⚡ Mark successful briefs and ads for shared-CDN caching to reduce duplicate generation while entries are fresh
  • 📥 Download each ad (or every finished ad) and share to X, with best-effort clipboard copying when the browser permits it

Examples

Real outputs, straight from Branda — one public domain in, 4–6 ads out:

Stripe ad generated by BrandaNotion ad generated by BrandaLinear ad generated by Branda
stripe.comnotion.comlinear.app
Vercel ad generated by BrandaOpenAI ad generated by BrandaWebflow ad generated by Branda
vercel.comopenai.comwebflow.com

Example outputs are illustrative. Product names, logos, and trademarks belong to their respective owners; their appearance here does not imply sponsorship or endorsement, and the MIT license does not grant rights to those third-party marks.


Table of contents


What you get

  • Domain → 4–6 ads, one input — no formats to pick, no messages to write, no style dropdowns. Paste a domain and the page morphs into a live gallery as each ad lands.
  • Grounded in the real brand — logo and industry come from the Brand API; colors and an eligible Google Font come from the site's extracted styleguide, not a generic palette.
  • Company plus products — every Ad Run starts with exactly three company ads, followed by one to three ads for distinct products extracted and fact-checked against the site with Context.dev.
  • 12 creative directions — an LLM picks one distinct direction per ad, then writes a tailored headline and subheadline for the company or specific product being advertised.
  • Up to 6 image models racinggpt-image-1, gpt-image-2, and grok-imagine-image take the three company slots; one to three of imagen-4.0, seedream-4.5, and recraft-v4.1 render the product slots. Every ad streams in the moment its model finishes.
  • Fact-grounded copy — company headlines draw from the real homepage, while Product headlines draw from structured extraction and prompts that require factual positioning.
  • CDN-cacheable — successful brief and ad responses include shared-cache headers, reducing duplicate generation work behind Vercel or another compatible CDN.
  • All downloadable — every ad individually, or every finished ad at once. Sharing opens the X composer and copies the first finished image when the browser supports clipboard images.

The 12 creative directions

Every generation picks 4–6 distinct directions from these:

KeyStyleBest for
product_heroEditorial product shot, dramatic studio lightingPhysical products, hardware
isometricSaaS-landing-page isometric diagramB2B SaaS, dev tools, APIs
typographicSwiss-design poster, massive typeStatement-driven or abstract products
macro_materialExtreme close-up of a material/surfaceBeauty, food, fashion, premium finishes
gradient_fieldPure atmospheric gradientAI products, fintech, abstract services
editorial_spreadMagazine spread (Kinfolk/Monocle vibe)Lifestyle, food/drink, travel
sculptural_objectAbstract 3D object in studio spaceTech/AI with no physical product
data_vizChart-as-artAnalytics, BI, observability
blueprintTechnical schematic drawingEngineering, hardware, infrastructure
retro_arcadeLate-80s neon/grid aestheticGaming, playful brands
monochrome_cropTight single-hue detail cropLuxury, watches, minimalist brands
collageCut-paper layered collageAgencies, education, media

All twelve prompt templates share a strict typography spec (the only text allowed is the headline, subheadline, and wordmark) and hard rules (no hex codes, no placeholder text, no people/faces/hands). Styleguide colors are converted to phrases like "vivid purple", because image models literally print strings like #543cfc onto the art when given raw codes. When the styleguide's primary typography references a verified Google Font, its family name is passed into every image prompt; otherwise the prompt uses a neutral sans-serif fallback.


How it works

┌──────────────┐ GET /api/brief?domain=…&v=3 ┌──────────────────┐
│ Paste domain │ ──────────────────────────▶ │ Context.dev API │
└──────────────┘ └──────────────────┘
│ brand + homepage md + styleguide palette/typography
│ + 1–3 fact-grounded products via web.extract + Zod JSON Schema
▼
┌────────────────────────────────────────────────────┐
│ one LLM call plans 3 company concepts followed by │ gpt-5.4-mini
│ 1–3 product concepts, with grounded copy for each; │
│ distinct models: 3 primary, then 1–3 secondary │
└────────────────────────────────────────────────────┘
│ { brief, concepts[4..6] } ← cached on Vercel CDN
▼
4–6 × GET /api/ad?domain=…&concept=…&model=…&headline=…
│ each returns one 1:1 image ← cached on Vercel CDN
▼
Ads stream into the gallery · Download · Share on X
  1. The briefGET /api/brief makes four Context.dev calls in parallel: Brand data, homepage Markdown, styleguide extraction, and structured web extraction. Product extraction uses a JSON Schema generated from Zod and Context.dev fact checking. The planner derives two describable colors from the styleguide's accent/background/text palette and carries a typography family only when the styleguide marks it as a Google Font. One LLM call then writes three company concepts followed by one concept for each of the one to three distinct Products. Successful responses are shared-cacheable per versioned domain key (s-maxage=3600, one-day stale-while-revalidate).
  2. The ads — the client fires 4–6 parallel GET /api/ad requests, one per Planned Concept. Everything the prompt needs — including whether the subject is the company or a specific Product — travels in the query string, so compatible CDNs can cache each finished image by its full URL (s-maxage=86400, seven-day stale-while-revalidate). The three primary models can receive a validated raster logo as an image reference; unsupported or rejected logo inputs fall back to text-only generation. Transient failures retry with backoff; failed slots expose a per-ad Retry button, and errors are never cached.
  3. Ship — each ad fades into the dynamically sized gallery as its model finishes. Download one, download every finished ad, or share to X.

Context.dev APIs used

Branda makes exactly four Context.dev calls, all isolated in src/lib/context.ts. These links are the canonical API pages listed in the Context.dev documentation sitemap.

SDK operationWhat Branda uses it forAPI reference
client.brand.retrieveBrand name, description, slogan, industry, and logoRetrieve Brand Data
client.web.webScrapeMdHomepage Markdown for grounded company copy and reachability checksScrape Markdown
client.web.extractStyleguideAccent/background/text colors, visual mood, and eligible Google Font metadataExtract Styleguide
client.web.extractOne to three Products against a Zod-derived JSON Schema, with fact checkingExtract Structured Data

Want to use the same APIs in your own app? Create a Context.dev API key.


Quick start

Prerequisites:

# 1. Clone
git clone https://github.com/context-dot-dev/ad-maker.git
cd ad-maker
# 2. Install
npm install
# 3. Configure
cp .env.example .env
# add CONTEXT_DEV_API_KEY and AI_GATEWAY_API_KEY to .env# 4. Run
npm run dev # http://localhost:3000

Open http://localhost:3000, paste a domain, and watch 4–6 ads roll in. That's it.

Note

A single Vercel AI Gateway key serves everything Branda uses — concept picking, copy, and up to six image models — from one credit balance, with no per-provider keys to manage.


Configuration

All configuration is environment variables (see .env.example).

VariableRequiredDescription
CONTEXT_DEV_API_KEYYesContext.dev key — powers all four Context.dev API calls
AI_GATEWAY_API_KEYYesVercel AI Gateway key — powers concept picking + copy (gpt-5.4-mini) and up to six image models

API keys are read only by server code. Never prefix either secret with NEXT_PUBLIC_, commit .env, or paste a key into an issue, log, or screenshot.


Customize or integrate

The UI and renderer are separable from Context.dev enrichment, so you can reuse the adapter without adopting the gallery or image-generation stack.


Deploy safely

npm run build && npm run start runs the production app. On Vercel, import the repo and set the two required environment variables; the route hints allow up to 120 seconds for brief planning and 300 seconds for image rendering, so other hosts need equivalent request limits.

The included /api/brief and /api/ad routes invoke billable services and are intentionally callable by the browser. Before exposing your own deployment, add authentication and/or rate limiting appropriate to your audience, set provider spend alerts, and understand the cost of up to four Context.dev calls, one text-model call, and six image-model calls per uncached Ad Run. Successful responses benefit from a compatible shared CDN cache; failures use no-store.

The app loads Plausible (privacy-friendly, cookieless analytics) via a script tag in src/app/layout.tsx; forks should swap in their own Plausible script URL or remove the tag. The default UI also requests a Google-hosted font and Google favicon service; privacy-sensitive forks can self-host or remove those requests.


Scripts

CommandWhat it does
npm run devStart the Next.js dev server
npm run build / npm run startProduction build / serve
npm run typecheckTypeScript checks
npm testRun the interface and policy test suite
npm run test:watchRun tests in watch mode while developing
npm run verifyRun type checks, tests, and the production build

Project structure

The canonical domain language and module relationships live in CONTEXT.md.

src/
app/
api/
brief/route.ts # domain → brand + products + 4–6 concepts w/ copy (CDN-cached)
ad/route.ts # one concept → one 1:1 ad image (CDN-cached by URL)
page.tsx # the single page — hero morphs into the gallery
components/
ad-maker.tsx # hero, brand bar, progress, dynamic 4–6-slot gallery
hooks/
use-ad-maker.ts # legal Gallery stages, parallel rendering, retries, URL ownership
lib/
ad-run-policy.ts # run composition, ordering, and shared field limits
ad-run.ts # shared Ad Run contract, invariants, and canonical GET codecs
brand-color.ts # canonical Brand color validation
font-family.ts # safe styleguide Google Font family validation
context.ts # Context.dev Brand, page, styleguide, and Product adapter
net.ts # canonical domain normalization
public-raster.ts # DNS-pinned, size-bounded public logo loading
public-url.ts # cross-runtime public URL syntax policy
generate/
directions.ts # cross-runtime Creative Direction catalog
models.ts # Image Model tiers, names, and capabilities
concepts.ts # server-only prompt implementations
brief.ts # homepage summary + concept copywriting
colors.ts # hex → describable color phrases
gateway.ts # internal Vercel AI Gateway adapter
planner.ts # domain → validated Brief + 4–6 Planned Concepts
renderer.ts # one Planned Concept → retried Rendered Ad
public/ # logo, cover, ad examples

Tech stack

  • Next.js 15 (App Router) + React 19 + TypeScript
  • Context.devBrand data, homepage Markdown, styleguide extraction, and structured Product extraction
  • 🤖 Vercel AI SDK + AI Gatewaygpt-5.4-mini for concept picking & copy; gpt-image-1, gpt-image-2, grok-imagine-image, imagen-4.0, seedream-4.5, and recraft-v4.1 for the ads (one per ad)
  • 🌍 Vercel CDN — briefs and finished ads cached at the edge via Cache-Control: s-maxage
  • 🎨 Tailwind CSS + Geist font

Contributing

Contributions are very welcome — new creative directions, better prompts, alternative image models, UI polish, you name it.

  1. Fork the repo and create a branch: git checkout -b feat/my-feature
  2. Make your change — keep it focused; small PRs get reviewed fast
  3. Check it passesnpm run verify
  4. Open a PR describing what changed and why (screenshots or generated ads are a huge plus)

Found a bug or have an idea? Open an issue — no contribution is too small.

See CONTRIBUTING.md for the full guide.


Built using Context.dev

Branda gets its Brand metadata, logos, colors, homepage content, visual styleguide, and fact-grounded Products from a single API. Want to build your own brand-aware tool or agent?

importContextDevfrom"context.dev";import{zodSchema}from"ai";import{z}from"zod";constclient=newContextDev({apiKey: process.env.CONTEXT_DEV_API_KEY});constproductExtraction=z.object({products: z.array(z.object({name: z.string(),description: z.string(),}),).min(1).max(3),});constschema=awaitzodSchema(productExtraction).jsonSchema;const[brand,homepage,styleguide,productData]=awaitPromise.all([client.brand.retrieve({type: "by_domain",domain: "notion.com"}),client.web.webScrapeMd({url: "https://notion.com",useMainContentOnly: true,}),client.web.extractStyleguide({domain: "notion.com"}),client.web.extract({url: "https://notion.com",
schema,factCheck: true,}),]);const{ products }=productExtraction.parse(productData.data);

👉 Get your free API key →


License

MIT © Context.dev

Built with 🥠 by the Context.dev team.


Make it yours

Fork Branda to launch your own version, or copy the Context.dev adapter into an app you already maintain. Sign up for Context.dev and get your API key to start building.

About

MIT license open source ad maker

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - context-dot-dev/ad-maker: MIT license open source ad maker · GitHub
Skip to content

Repository files navigation

Branda logo

Paste a public domain. Get scroll-stopping, on-brand ads in seconds.

MIT LicensePowered by Context.devPRs welcomeNext.js 15

Make it yours: fork Branda into your own ad maker, or integrate its brand-research pipeline into an existing repo. Sign up for Context.dev to get your API key, then follow the quick start.

Branda — generate on-brand ads from a public domain


Built by the Context.dev team 🥠

Branda is an open-source ad generator that turns a public website domain into four to six polished, on-brand marketing creatives. The hosted experience needs no login, brief, or settings — the domain is the only input. Branda pulls the brand's identity from the Context.dev Brand API, uses its extracted styleguide palette and Google Font when available, and grounds one to three distinct products with structured web extraction. It then morphs the page in place into a gallery: three company ads followed by one ad for each extracted product.

Paste notion.com and Branda will:

  • 🎨 Pull the brand's logo and industry plus its styleguide palette and eligible Google Font
  • 👀 Read the homepage as Markdown so the copy can reflect the brand's real voice
  • 📦 Extract one to three distinct, fact-checked products with Context.dev web.extract and a JSON Schema generated from Zod
  • 🧠 Have an LLM pick a distinct creative direction and write tailored copy for three company ads plus one ad per extracted product
  • 🖼️ Render 4–6 distinct 1:1 ads in parallel — every ad uses a different image model (OpenAI, xAI, Google, ByteDance, Recraft)
  • ⚡ Mark successful briefs and ads for shared-CDN caching to reduce duplicate generation while entries are fresh
  • 📥 Download each ad (or every finished ad) and share to X, with best-effort clipboard copying when the browser permits it

Examples

Real outputs, straight from Branda — one public domain in, 4–6 ads out:

Stripe ad generated by BrandaNotion ad generated by BrandaLinear ad generated by Branda
stripe.comnotion.comlinear.app
Vercel ad generated by BrandaOpenAI ad generated by BrandaWebflow ad generated by Branda
vercel.comopenai.comwebflow.com

Example outputs are illustrative. Product names, logos, and trademarks belong to their respective owners; their appearance here does not imply sponsorship or endorsement, and the MIT license does not grant rights to those third-party marks.


Table of contents


What you get

  • Domain → 4–6 ads, one input — no formats to pick, no messages to write, no style dropdowns. Paste a domain and the page morphs into a live gallery as each ad lands.
  • Grounded in the real brand — logo and industry come from the Brand API; colors and an eligible Google Font come from the site's extracted styleguide, not a generic palette.
  • Company plus products — every Ad Run starts with exactly three company ads, followed by one to three ads for distinct products extracted and fact-checked against the site with Context.dev.
  • 12 creative directions — an LLM picks one distinct direction per ad, then writes a tailored headline and subheadline for the company or specific product being advertised.
  • Up to 6 image models racinggpt-image-1, gpt-image-2, and grok-imagine-image take the three company slots; one to three of imagen-4.0, seedream-4.5, and recraft-v4.1 render the product slots. Every ad streams in the moment its model finishes.
  • Fact-grounded copy — company headlines draw from the real homepage, while Product headlines draw from structured extraction and prompts that require factual positioning.
  • CDN-cacheable — successful brief and ad responses include shared-cache headers, reducing duplicate generation work behind Vercel or another compatible CDN.
  • All downloadable — every ad individually, or every finished ad at once. Sharing opens the X composer and copies the first finished image when the browser supports clipboard images.

The 12 creative directions

Every generation picks 4–6 distinct directions from these:

KeyStyleBest for
product_heroEditorial product shot, dramatic studio lightingPhysical products, hardware
isometricSaaS-landing-page isometric diagramB2B SaaS, dev tools, APIs
typographicSwiss-design poster, massive typeStatement-driven or abstract products
macro_materialExtreme close-up of a material/surfaceBeauty, food, fashion, premium finishes
gradient_fieldPure atmospheric gradientAI products, fintech, abstract services
editorial_spreadMagazine spread (Kinfolk/Monocle vibe)Lifestyle, food/drink, travel
sculptural_objectAbstract 3D object in studio spaceTech/AI with no physical product
data_vizChart-as-artAnalytics, BI, observability
blueprintTechnical schematic drawingEngineering, hardware, infrastructure
retro_arcadeLate-80s neon/grid aestheticGaming, playful brands
monochrome_cropTight single-hue detail cropLuxury, watches, minimalist brands
collageCut-paper layered collageAgencies, education, media

All twelve prompt templates share a strict typography spec (the only text allowed is the headline, subheadline, and wordmark) and hard rules (no hex codes, no placeholder text, no people/faces/hands). Styleguide colors are converted to phrases like "vivid purple", because image models literally print strings like #543cfc onto the art when given raw codes. When the styleguide's primary typography references a verified Google Font, its family name is passed into every image prompt; otherwise the prompt uses a neutral sans-serif fallback.


How it works

┌──────────────┐ GET /api/brief?domain=…&v=3 ┌──────────────────┐
│ Paste domain │ ──────────────────────────▶ │ Context.dev API │
└──────────────┘ └──────────────────┘
│ brand + homepage md + styleguide palette/typography
│ + 1–3 fact-grounded products via web.extract + Zod JSON Schema
▼
┌────────────────────────────────────────────────────┐
│ one LLM call plans 3 company concepts followed by │ gpt-5.4-mini
│ 1–3 product concepts, with grounded copy for each; │
│ distinct models: 3 primary, then 1–3 secondary │
└────────────────────────────────────────────────────┘
│ { brief, concepts[4..6] } ← cached on Vercel CDN
▼
4–6 × GET /api/ad?domain=…&concept=…&model=…&headline=…
│ each returns one 1:1 image ← cached on Vercel CDN
▼
Ads stream into the gallery · Download · Share on X
  1. The briefGET /api/brief makes four Context.dev calls in parallel: Brand data, homepage Markdown, styleguide extraction, and structured web extraction. Product extraction uses a JSON Schema generated from Zod and Context.dev fact checking. The planner derives two describable colors from the styleguide's accent/background/text palette and carries a typography family only when the styleguide marks it as a Google Font. One LLM call then writes three company concepts followed by one concept for each of the one to three distinct Products. Successful responses are shared-cacheable per versioned domain key (s-maxage=3600, one-day stale-while-revalidate).
  2. The ads — the client fires 4–6 parallel GET /api/ad requests, one per Planned Concept. Everything the prompt needs — including whether the subject is the company or a specific Product — travels in the query string, so compatible CDNs can cache each finished image by its full URL (s-maxage=86400, seven-day stale-while-revalidate). The three primary models can receive a validated raster logo as an image reference; unsupported or rejected logo inputs fall back to text-only generation. Transient failures retry with backoff; failed slots expose a per-ad Retry button, and errors are never cached.
  3. Ship — each ad fades into the dynamically sized gallery as its model finishes. Download one, download every finished ad, or share to X.

Context.dev APIs used

Branda makes exactly four Context.dev calls, all isolated in src/lib/context.ts. These links are the canonical API pages listed in the Context.dev documentation sitemap.

SDK operationWhat Branda uses it forAPI reference
client.brand.retrieveBrand name, description, slogan, industry, and logoRetrieve Brand Data
client.web.webScrapeMdHomepage Markdown for grounded company copy and reachability checksScrape Markdown
client.web.extractStyleguideAccent/background/text colors, visual mood, and eligible Google Font metadataExtract Styleguide
client.web.extractOne to three Products against a Zod-derived JSON Schema, with fact checkingExtract Structured Data

Want to use the same APIs in your own app? Create a Context.dev API key.


Quick start

Prerequisites:

# 1. Clone
git clone https://github.com/context-dot-dev/ad-maker.git
cd ad-maker
# 2. Install
npm install
# 3. Configure
cp .env.example .env
# add CONTEXT_DEV_API_KEY and AI_GATEWAY_API_KEY to .env# 4. Run
npm run dev # http://localhost:3000

Open http://localhost:3000, paste a domain, and watch 4–6 ads roll in. That's it.

Note

A single Vercel AI Gateway key serves everything Branda uses — concept picking, copy, and up to six image models — from one credit balance, with no per-provider keys to manage.


Configuration

All configuration is environment variables (see .env.example).

VariableRequiredDescription
CONTEXT_DEV_API_KEYYesContext.dev key — powers all four Context.dev API calls
AI_GATEWAY_API_KEYYesVercel AI Gateway key — powers concept picking + copy (gpt-5.4-mini) and up to six image models

API keys are read only by server code. Never prefix either secret with NEXT_PUBLIC_, commit .env, or paste a key into an issue, log, or screenshot.


Customize or integrate

The UI and renderer are separable from Context.dev enrichment, so you can reuse the adapter without adopting the gallery or image-generation stack.


Deploy safely

npm run build && npm run start runs the production app. On Vercel, import the repo and set the two required environment variables; the route hints allow up to 120 seconds for brief planning and 300 seconds for image rendering, so other hosts need equivalent request limits.

The included /api/brief and /api/ad routes invoke billable services and are intentionally callable by the browser. Before exposing your own deployment, add authentication and/or rate limiting appropriate to your audience, set provider spend alerts, and understand the cost of up to four Context.dev calls, one text-model call, and six image-model calls per uncached Ad Run. Successful responses benefit from a compatible shared CDN cache; failures use no-store.

The app loads Plausible (privacy-friendly, cookieless analytics) via a script tag in src/app/layout.tsx; forks should swap in their own Plausible script URL or remove the tag. The default UI also requests a Google-hosted font and Google favicon service; privacy-sensitive forks can self-host or remove those requests.


Scripts

CommandWhat it does
npm run devStart the Next.js dev server
npm run build / npm run startProduction build / serve
npm run typecheckTypeScript checks
npm testRun the interface and policy test suite
npm run test:watchRun tests in watch mode while developing
npm run verifyRun type checks, tests, and the production build

Project structure

The canonical domain language and module relationships live in CONTEXT.md.

src/
app/
api/
brief/route.ts # domain → brand + products + 4–6 concepts w/ copy (CDN-cached)
ad/route.ts # one concept → one 1:1 ad image (CDN-cached by URL)
page.tsx # the single page — hero morphs into the gallery
components/
ad-maker.tsx # hero, brand bar, progress, dynamic 4–6-slot gallery
hooks/
use-ad-maker.ts # legal Gallery stages, parallel rendering, retries, URL ownership
lib/
ad-run-policy.ts # run composition, ordering, and shared field limits
ad-run.ts # shared Ad Run contract, invariants, and canonical GET codecs
brand-color.ts # canonical Brand color validation
font-family.ts # safe styleguide Google Font family validation
context.ts # Context.dev Brand, page, styleguide, and Product adapter
net.ts # canonical domain normalization
public-raster.ts # DNS-pinned, size-bounded public logo loading
public-url.ts # cross-runtime public URL syntax policy
generate/
directions.ts # cross-runtime Creative Direction catalog
models.ts # Image Model tiers, names, and capabilities
concepts.ts # server-only prompt implementations
brief.ts # homepage summary + concept copywriting
colors.ts # hex → describable color phrases
gateway.ts # internal Vercel AI Gateway adapter
planner.ts # domain → validated Brief + 4–6 Planned Concepts
renderer.ts # one Planned Concept → retried Rendered Ad
public/ # logo, cover, ad examples

Tech stack

  • Next.js 15 (App Router) + React 19 + TypeScript
  • Context.devBrand data, homepage Markdown, styleguide extraction, and structured Product extraction
  • 🤖 Vercel AI SDK + AI Gatewaygpt-5.4-mini for concept picking & copy; gpt-image-1, gpt-image-2, grok-imagine-image, imagen-4.0, seedream-4.5, and recraft-v4.1 for the ads (one per ad)
  • 🌍 Vercel CDN — briefs and finished ads cached at the edge via Cache-Control: s-maxage
  • 🎨 Tailwind CSS + Geist font

Contributing

Contributions are very welcome — new creative directions, better prompts, alternative image models, UI polish, you name it.

  1. Fork the repo and create a branch: git checkout -b feat/my-feature
  2. Make your change — keep it focused; small PRs get reviewed fast
  3. Check it passesnpm run verify
  4. Open a PR describing what changed and why (screenshots or generated ads are a huge plus)

Found a bug or have an idea? Open an issue — no contribution is too small.

See CONTRIBUTING.md for the full guide.


Built using Context.dev

Branda gets its Brand metadata, logos, colors, homepage content, visual styleguide, and fact-grounded Products from a single API. Want to build your own brand-aware tool or agent?

importContextDevfrom"context.dev";import{zodSchema}from"ai";import{z}from"zod";constclient=newContextDev({apiKey: process.env.CONTEXT_DEV_API_KEY});constproductExtraction=z.object({products: z.array(z.object({name: z.string(),description: z.string(),}),).min(1).max(3),});constschema=awaitzodSchema(productExtraction).jsonSchema;const[brand,homepage,styleguide,productData]=awaitPromise.all([client.brand.retrieve({type: "by_domain",domain: "notion.com"}),client.web.webScrapeMd({url: "https://notion.com",useMainContentOnly: true,}),client.web.extractStyleguide({domain: "notion.com"}),client.web.extract({url: "https://notion.com",
schema,factCheck: true,}),]);const{ products }=productExtraction.parse(productData.data);

👉 Get your free API key →


License

MIT © Context.dev

Built with 🥠 by the Context.dev team.


Make it yours

Fork Branda to launch your own version, or copy the Context.dev adapter into an app you already maintain. Sign up for Context.dev and get your API key to start building.

About

MIT license open source ad maker

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - context-dot-dev/ad-maker: MIT license open source ad maker · GitHub
Skip to content

Repository files navigation

Branda logo

Paste a public domain. Get scroll-stopping, on-brand ads in seconds.

MIT LicensePowered by Context.devPRs welcomeNext.js 15

Make it yours: fork Branda into your own ad maker, or integrate its brand-research pipeline into an existing repo. Sign up for Context.dev to get your API key, then follow the quick start.

Branda — generate on-brand ads from a public domain


Built by the Context.dev team 🥠

Branda is an open-source ad generator that turns a public website domain into four to six polished, on-brand marketing creatives. The hosted experience needs no login, brief, or settings — the domain is the only input. Branda pulls the brand's identity from the Context.dev Brand API, uses its extracted styleguide palette and Google Font when available, and grounds one to three distinct products with structured web extraction. It then morphs the page in place into a gallery: three company ads followed by one ad for each extracted product.

Paste notion.com and Branda will:

  • 🎨 Pull the brand's logo and industry plus its styleguide palette and eligible Google Font
  • 👀 Read the homepage as Markdown so the copy can reflect the brand's real voice
  • 📦 Extract one to three distinct, fact-checked products with Context.dev web.extract and a JSON Schema generated from Zod
  • 🧠 Have an LLM pick a distinct creative direction and write tailored copy for three company ads plus one ad per extracted product
  • 🖼️ Render 4–6 distinct 1:1 ads in parallel — every ad uses a different image model (OpenAI, xAI, Google, ByteDance, Recraft)
  • ⚡ Mark successful briefs and ads for shared-CDN caching to reduce duplicate generation while entries are fresh
  • 📥 Download each ad (or every finished ad) and share to X, with best-effort clipboard copying when the browser permits it

Examples

Real outputs, straight from Branda — one public domain in, 4–6 ads out:

Stripe ad generated by BrandaNotion ad generated by BrandaLinear ad generated by Branda
stripe.comnotion.comlinear.app
Vercel ad generated by BrandaOpenAI ad generated by BrandaWebflow ad generated by Branda
vercel.comopenai.comwebflow.com

Example outputs are illustrative. Product names, logos, and trademarks belong to their respective owners; their appearance here does not imply sponsorship or endorsement, and the MIT license does not grant rights to those third-party marks.


Table of contents


What you get

  • Domain → 4–6 ads, one input — no formats to pick, no messages to write, no style dropdowns. Paste a domain and the page morphs into a live gallery as each ad lands.
  • Grounded in the real brand — logo and industry come from the Brand API; colors and an eligible Google Font come from the site's extracted styleguide, not a generic palette.
  • Company plus products — every Ad Run starts with exactly three company ads, followed by one to three ads for distinct products extracted and fact-checked against the site with Context.dev.
  • 12 creative directions — an LLM picks one distinct direction per ad, then writes a tailored headline and subheadline for the company or specific product being advertised.
  • Up to 6 image models racinggpt-image-1, gpt-image-2, and grok-imagine-image take the three company slots; one to three of imagen-4.0, seedream-4.5, and recraft-v4.1 render the product slots. Every ad streams in the moment its model finishes.
  • Fact-grounded copy — company headlines draw from the real homepage, while Product headlines draw from structured extraction and prompts that require factual positioning.
  • CDN-cacheable — successful brief and ad responses include shared-cache headers, reducing duplicate generation work behind Vercel or another compatible CDN.
  • All downloadable — every ad individually, or every finished ad at once. Sharing opens the X composer and copies the first finished image when the browser supports clipboard images.

The 12 creative directions

Every generation picks 4–6 distinct directions from these:

KeyStyleBest for
product_heroEditorial product shot, dramatic studio lightingPhysical products, hardware
isometricSaaS-landing-page isometric diagramB2B SaaS, dev tools, APIs
typographicSwiss-design poster, massive typeStatement-driven or abstract products
macro_materialExtreme close-up of a material/surfaceBeauty, food, fashion, premium finishes
gradient_fieldPure atmospheric gradientAI products, fintech, abstract services
editorial_spreadMagazine spread (Kinfolk/Monocle vibe)Lifestyle, food/drink, travel
sculptural_objectAbstract 3D object in studio spaceTech/AI with no physical product
data_vizChart-as-artAnalytics, BI, observability
blueprintTechnical schematic drawingEngineering, hardware, infrastructure
retro_arcadeLate-80s neon/grid aestheticGaming, playful brands
monochrome_cropTight single-hue detail cropLuxury, watches, minimalist brands
collageCut-paper layered collageAgencies, education, media

All twelve prompt templates share a strict typography spec (the only text allowed is the headline, subheadline, and wordmark) and hard rules (no hex codes, no placeholder text, no people/faces/hands). Styleguide colors are converted to phrases like "vivid purple", because image models literally print strings like #543cfc onto the art when given raw codes. When the styleguide's primary typography references a verified Google Font, its family name is passed into every image prompt; otherwise the prompt uses a neutral sans-serif fallback.


How it works

┌──────────────┐ GET /api/brief?domain=…&v=3 ┌──────────────────┐
│ Paste domain │ ──────────────────────────▶ │ Context.dev API │
└──────────────┘ └──────────────────┘
│ brand + homepage md + styleguide palette/typography
│ + 1–3 fact-grounded products via web.extract + Zod JSON Schema
▼
┌────────────────────────────────────────────────────┐
│ one LLM call plans 3 company concepts followed by │ gpt-5.4-mini
│ 1–3 product concepts, with grounded copy for each; │
│ distinct models: 3 primary, then 1–3 secondary │
└────────────────────────────────────────────────────┘
│ { brief, concepts[4..6] } ← cached on Vercel CDN
▼
4–6 × GET /api/ad?domain=…&concept=…&model=…&headline=…
│ each returns one 1:1 image ← cached on Vercel CDN
▼
Ads stream into the gallery · Download · Share on X
  1. The briefGET /api/brief makes four Context.dev calls in parallel: Brand data, homepage Markdown, styleguide extraction, and structured web extraction. Product extraction uses a JSON Schema generated from Zod and Context.dev fact checking. The planner derives two describable colors from the styleguide's accent/background/text palette and carries a typography family only when the styleguide marks it as a Google Font. One LLM call then writes three company concepts followed by one concept for each of the one to three distinct Products. Successful responses are shared-cacheable per versioned domain key (s-maxage=3600, one-day stale-while-revalidate).
  2. The ads — the client fires 4–6 parallel GET /api/ad requests, one per Planned Concept. Everything the prompt needs — including whether the subject is the company or a specific Product — travels in the query string, so compatible CDNs can cache each finished image by its full URL (s-maxage=86400, seven-day stale-while-revalidate). The three primary models can receive a validated raster logo as an image reference; unsupported or rejected logo inputs fall back to text-only generation. Transient failures retry with backoff; failed slots expose a per-ad Retry button, and errors are never cached.
  3. Ship — each ad fades into the dynamically sized gallery as its model finishes. Download one, download every finished ad, or share to X.

Context.dev APIs used

Branda makes exactly four Context.dev calls, all isolated in src/lib/context.ts. These links are the canonical API pages listed in the Context.dev documentation sitemap.

SDK operationWhat Branda uses it forAPI reference
client.brand.retrieveBrand name, description, slogan, industry, and logoRetrieve Brand Data
client.web.webScrapeMdHomepage Markdown for grounded company copy and reachability checksScrape Markdown
client.web.extractStyleguideAccent/background/text colors, visual mood, and eligible Google Font metadataExtract Styleguide
client.web.extractOne to three Products against a Zod-derived JSON Schema, with fact checkingExtract Structured Data

Want to use the same APIs in your own app? Create a Context.dev API key.


Quick start

Prerequisites:

# 1. Clone
git clone https://github.com/context-dot-dev/ad-maker.git
cd ad-maker
# 2. Install
npm install
# 3. Configure
cp .env.example .env
# add CONTEXT_DEV_API_KEY and AI_GATEWAY_API_KEY to .env# 4. Run
npm run dev # http://localhost:3000

Open http://localhost:3000, paste a domain, and watch 4–6 ads roll in. That's it.

Note

A single Vercel AI Gateway key serves everything Branda uses — concept picking, copy, and up to six image models — from one credit balance, with no per-provider keys to manage.


Configuration

All configuration is environment variables (see .env.example).

VariableRequiredDescription
CONTEXT_DEV_API_KEYYesContext.dev key — powers all four Context.dev API calls
AI_GATEWAY_API_KEYYesVercel AI Gateway key — powers concept picking + copy (gpt-5.4-mini) and up to six image models

API keys are read only by server code. Never prefix either secret with NEXT_PUBLIC_, commit .env, or paste a key into an issue, log, or screenshot.


Customize or integrate

The UI and renderer are separable from Context.dev enrichment, so you can reuse the adapter without adopting the gallery or image-generation stack.


Deploy safely

npm run build && npm run start runs the production app. On Vercel, import the repo and set the two required environment variables; the route hints allow up to 120 seconds for brief planning and 300 seconds for image rendering, so other hosts need equivalent request limits.

The included /api/brief and /api/ad routes invoke billable services and are intentionally callable by the browser. Before exposing your own deployment, add authentication and/or rate limiting appropriate to your audience, set provider spend alerts, and understand the cost of up to four Context.dev calls, one text-model call, and six image-model calls per uncached Ad Run. Successful responses benefit from a compatible shared CDN cache; failures use no-store.

The app loads Plausible (privacy-friendly, cookieless analytics) via a script tag in src/app/layout.tsx; forks should swap in their own Plausible script URL or remove the tag. The default UI also requests a Google-hosted font and Google favicon service; privacy-sensitive forks can self-host or remove those requests.


Scripts

CommandWhat it does
npm run devStart the Next.js dev server
npm run build / npm run startProduction build / serve
npm run typecheckTypeScript checks
npm testRun the interface and policy test suite
npm run test:watchRun tests in watch mode while developing
npm run verifyRun type checks, tests, and the production build

Project structure

The canonical domain language and module relationships live in CONTEXT.md.

src/
app/
api/
brief/route.ts # domain → brand + products + 4–6 concepts w/ copy (CDN-cached)
ad/route.ts # one concept → one 1:1 ad image (CDN-cached by URL)
page.tsx # the single page — hero morphs into the gallery
components/
ad-maker.tsx # hero, brand bar, progress, dynamic 4–6-slot gallery
hooks/
use-ad-maker.ts # legal Gallery stages, parallel rendering, retries, URL ownership
lib/
ad-run-policy.ts # run composition, ordering, and shared field limits
ad-run.ts # shared Ad Run contract, invariants, and canonical GET codecs
brand-color.ts # canonical Brand color validation
font-family.ts # safe styleguide Google Font family validation
context.ts # Context.dev Brand, page, styleguide, and Product adapter
net.ts # canonical domain normalization
public-raster.ts # DNS-pinned, size-bounded public logo loading
public-url.ts # cross-runtime public URL syntax policy
generate/
directions.ts # cross-runtime Creative Direction catalog
models.ts # Image Model tiers, names, and capabilities
concepts.ts # server-only prompt implementations
brief.ts # homepage summary + concept copywriting
colors.ts # hex → describable color phrases
gateway.ts # internal Vercel AI Gateway adapter
planner.ts # domain → validated Brief + 4–6 Planned Concepts
renderer.ts # one Planned Concept → retried Rendered Ad
public/ # logo, cover, ad examples

Tech stack

  • Next.js 15 (App Router) + React 19 + TypeScript
  • Context.devBrand data, homepage Markdown, styleguide extraction, and structured Product extraction
  • 🤖 Vercel AI SDK + AI Gatewaygpt-5.4-mini for concept picking & copy; gpt-image-1, gpt-image-2, grok-imagine-image, imagen-4.0, seedream-4.5, and recraft-v4.1 for the ads (one per ad)
  • 🌍 Vercel CDN — briefs and finished ads cached at the edge via Cache-Control: s-maxage
  • 🎨 Tailwind CSS + Geist font

Contributing

Contributions are very welcome — new creative directions, better prompts, alternative image models, UI polish, you name it.

  1. Fork the repo and create a branch: git checkout -b feat/my-feature
  2. Make your change — keep it focused; small PRs get reviewed fast
  3. Check it passesnpm run verify
  4. Open a PR describing what changed and why (screenshots or generated ads are a huge plus)

Found a bug or have an idea? Open an issue — no contribution is too small.

See CONTRIBUTING.md for the full guide.


Built using Context.dev

Branda gets its Brand metadata, logos, colors, homepage content, visual styleguide, and fact-grounded Products from a single API. Want to build your own brand-aware tool or agent?

importContextDevfrom"context.dev";import{zodSchema}from"ai";import{z}from"zod";constclient=newContextDev({apiKey: process.env.CONTEXT_DEV_API_KEY});constproductExtraction=z.object({products: z.array(z.object({name: z.string(),description: z.string(),}),).min(1).max(3),});constschema=awaitzodSchema(productExtraction).jsonSchema;const[brand,homepage,styleguide,productData]=awaitPromise.all([client.brand.retrieve({type: "by_domain",domain: "notion.com"}),client.web.webScrapeMd({url: "https://notion.com",useMainContentOnly: true,}),client.web.extractStyleguide({domain: "notion.com"}),client.web.extract({url: "https://notion.com",
schema,factCheck: true,}),]);const{ products }=productExtraction.parse(productData.data);

👉 Get your free API key →


License

MIT © Context.dev

Built with 🥠 by the Context.dev team.


Make it yours

Fork Branda to launch your own version, or copy the Context.dev adapter into an app you already maintain. Sign up for Context.dev and get your API key to start building.

About

MIT license open source ad maker

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - context-dot-dev/ad-maker: MIT license open source ad maker · GitHub
Skip to content

Repository files navigation

Branda logo

Paste a public domain. Get scroll-stopping, on-brand ads in seconds.

MIT LicensePowered by Context.devPRs welcomeNext.js 15

Make it yours: fork Branda into your own ad maker, or integrate its brand-research pipeline into an existing repo. Sign up for Context.dev to get your API key, then follow the quick start.

Branda — generate on-brand ads from a public domain


Built by the Context.dev team 🥠

Branda is an open-source ad generator that turns a public website domain into four to six polished, on-brand marketing creatives. The hosted experience needs no login, brief, or settings — the domain is the only input. Branda pulls the brand's identity from the Context.dev Brand API, uses its extracted styleguide palette and Google Font when available, and grounds one to three distinct products with structured web extraction. It then morphs the page in place into a gallery: three company ads followed by one ad for each extracted product.

Paste notion.com and Branda will:

  • 🎨 Pull the brand's logo and industry plus its styleguide palette and eligible Google Font
  • 👀 Read the homepage as Markdown so the copy can reflect the brand's real voice
  • 📦 Extract one to three distinct, fact-checked products with Context.dev web.extract and a JSON Schema generated from Zod
  • 🧠 Have an LLM pick a distinct creative direction and write tailored copy for three company ads plus one ad per extracted product
  • 🖼️ Render 4–6 distinct 1:1 ads in parallel — every ad uses a different image model (OpenAI, xAI, Google, ByteDance, Recraft)
  • ⚡ Mark successful briefs and ads for shared-CDN caching to reduce duplicate generation while entries are fresh
  • 📥 Download each ad (or every finished ad) and share to X, with best-effort clipboard copying when the browser permits it

Examples

Real outputs, straight from Branda — one public domain in, 4–6 ads out:

Stripe ad generated by BrandaNotion ad generated by BrandaLinear ad generated by Branda
stripe.comnotion.comlinear.app
Vercel ad generated by BrandaOpenAI ad generated by BrandaWebflow ad generated by Branda
vercel.comopenai.comwebflow.com

Example outputs are illustrative. Product names, logos, and trademarks belong to their respective owners; their appearance here does not imply sponsorship or endorsement, and the MIT license does not grant rights to those third-party marks.


Table of contents


What you get

  • Domain → 4–6 ads, one input — no formats to pick, no messages to write, no style dropdowns. Paste a domain and the page morphs into a live gallery as each ad lands.
  • Grounded in the real brand — logo and industry come from the Brand API; colors and an eligible Google Font come from the site's extracted styleguide, not a generic palette.
  • Company plus products — every Ad Run starts with exactly three company ads, followed by one to three ads for distinct products extracted and fact-checked against the site with Context.dev.
  • 12 creative directions — an LLM picks one distinct direction per ad, then writes a tailored headline and subheadline for the company or specific product being advertised.
  • Up to 6 image models racinggpt-image-1, gpt-image-2, and grok-imagine-image take the three company slots; one to three of imagen-4.0, seedream-4.5, and recraft-v4.1 render the product slots. Every ad streams in the moment its model finishes.
  • Fact-grounded copy — company headlines draw from the real homepage, while Product headlines draw from structured extraction and prompts that require factual positioning.
  • CDN-cacheable — successful brief and ad responses include shared-cache headers, reducing duplicate generation work behind Vercel or another compatible CDN.
  • All downloadable — every ad individually, or every finished ad at once. Sharing opens the X composer and copies the first finished image when the browser supports clipboard images.

The 12 creative directions

Every generation picks 4–6 distinct directions from these:

KeyStyleBest for
product_heroEditorial product shot, dramatic studio lightingPhysical products, hardware
isometricSaaS-landing-page isometric diagramB2B SaaS, dev tools, APIs
typographicSwiss-design poster, massive typeStatement-driven or abstract products
macro_materialExtreme close-up of a material/surfaceBeauty, food, fashion, premium finishes
gradient_fieldPure atmospheric gradientAI products, fintech, abstract services
editorial_spreadMagazine spread (Kinfolk/Monocle vibe)Lifestyle, food/drink, travel
sculptural_objectAbstract 3D object in studio spaceTech/AI with no physical product
data_vizChart-as-artAnalytics, BI, observability
blueprintTechnical schematic drawingEngineering, hardware, infrastructure
retro_arcadeLate-80s neon/grid aestheticGaming, playful brands
monochrome_cropTight single-hue detail cropLuxury, watches, minimalist brands
collageCut-paper layered collageAgencies, education, media

All twelve prompt templates share a strict typography spec (the only text allowed is the headline, subheadline, and wordmark) and hard rules (no hex codes, no placeholder text, no people/faces/hands). Styleguide colors are converted to phrases like "vivid purple", because image models literally print strings like #543cfc onto the art when given raw codes. When the styleguide's primary typography references a verified Google Font, its family name is passed into every image prompt; otherwise the prompt uses a neutral sans-serif fallback.


How it works

┌──────────────┐ GET /api/brief?domain=…&v=3 ┌──────────────────┐
│ Paste domain │ ──────────────────────────▶ │ Context.dev API │
└──────────────┘ └──────────────────┘
│ brand + homepage md + styleguide palette/typography
│ + 1–3 fact-grounded products via web.extract + Zod JSON Schema
▼
┌────────────────────────────────────────────────────┐
│ one LLM call plans 3 company concepts followed by │ gpt-5.4-mini
│ 1–3 product concepts, with grounded copy for each; │
│ distinct models: 3 primary, then 1–3 secondary │
└────────────────────────────────────────────────────┘
│ { brief, concepts[4..6] } ← cached on Vercel CDN
▼
4–6 × GET /api/ad?domain=…&concept=…&model=…&headline=…
│ each returns one 1:1 image ← cached on Vercel CDN
▼
Ads stream into the gallery · Download · Share on X
  1. The briefGET /api/brief makes four Context.dev calls in parallel: Brand data, homepage Markdown, styleguide extraction, and structured web extraction. Product extraction uses a JSON Schema generated from Zod and Context.dev fact checking. The planner derives two describable colors from the styleguide's accent/background/text palette and carries a typography family only when the styleguide marks it as a Google Font. One LLM call then writes three company concepts followed by one concept for each of the one to three distinct Products. Successful responses are shared-cacheable per versioned domain key (s-maxage=3600, one-day stale-while-revalidate).
  2. The ads — the client fires 4–6 parallel GET /api/ad requests, one per Planned Concept. Everything the prompt needs — including whether the subject is the company or a specific Product — travels in the query string, so compatible CDNs can cache each finished image by its full URL (s-maxage=86400, seven-day stale-while-revalidate). The three primary models can receive a validated raster logo as an image reference; unsupported or rejected logo inputs fall back to text-only generation. Transient failures retry with backoff; failed slots expose a per-ad Retry button, and errors are never cached.
  3. Ship — each ad fades into the dynamically sized gallery as its model finishes. Download one, download every finished ad, or share to X.

Context.dev APIs used

Branda makes exactly four Context.dev calls, all isolated in src/lib/context.ts. These links are the canonical API pages listed in the Context.dev documentation sitemap.

SDK operationWhat Branda uses it forAPI reference
client.brand.retrieveBrand name, description, slogan, industry, and logoRetrieve Brand Data
client.web.webScrapeMdHomepage Markdown for grounded company copy and reachability checksScrape Markdown
client.web.extractStyleguideAccent/background/text colors, visual mood, and eligible Google Font metadataExtract Styleguide
client.web.extractOne to three Products against a Zod-derived JSON Schema, with fact checkingExtract Structured Data

Want to use the same APIs in your own app? Create a Context.dev API key.


Quick start

Prerequisites:

# 1. Clone
git clone https://github.com/context-dot-dev/ad-maker.git
cd ad-maker
# 2. Install
npm install
# 3. Configure
cp .env.example .env
# add CONTEXT_DEV_API_KEY and AI_GATEWAY_API_KEY to .env# 4. Run
npm run dev # http://localhost:3000

Open http://localhost:3000, paste a domain, and watch 4–6 ads roll in. That's it.

Note

A single Vercel AI Gateway key serves everything Branda uses — concept picking, copy, and up to six image models — from one credit balance, with no per-provider keys to manage.


Configuration

All configuration is environment variables (see .env.example).

VariableRequiredDescription
CONTEXT_DEV_API_KEYYesContext.dev key — powers all four Context.dev API calls
AI_GATEWAY_API_KEYYesVercel AI Gateway key — powers concept picking + copy (gpt-5.4-mini) and up to six image models

API keys are read only by server code. Never prefix either secret with NEXT_PUBLIC_, commit .env, or paste a key into an issue, log, or screenshot.


Customize or integrate

The UI and renderer are separable from Context.dev enrichment, so you can reuse the adapter without adopting the gallery or image-generation stack.


Deploy safely

npm run build && npm run start runs the production app. On Vercel, import the repo and set the two required environment variables; the route hints allow up to 120 seconds for brief planning and 300 seconds for image rendering, so other hosts need equivalent request limits.

The included /api/brief and /api/ad routes invoke billable services and are intentionally callable by the browser. Before exposing your own deployment, add authentication and/or rate limiting appropriate to your audience, set provider spend alerts, and understand the cost of up to four Context.dev calls, one text-model call, and six image-model calls per uncached Ad Run. Successful responses benefit from a compatible shared CDN cache; failures use no-store.

The app loads Plausible (privacy-friendly, cookieless analytics) via a script tag in src/app/layout.tsx; forks should swap in their own Plausible script URL or remove the tag. The default UI also requests a Google-hosted font and Google favicon service; privacy-sensitive forks can self-host or remove those requests.


Scripts

CommandWhat it does
npm run devStart the Next.js dev server
npm run build / npm run startProduction build / serve
npm run typecheckTypeScript checks
npm testRun the interface and policy test suite
npm run test:watchRun tests in watch mode while developing
npm run verifyRun type checks, tests, and the production build

Project structure

The canonical domain language and module relationships live in CONTEXT.md.

src/
app/
api/
brief/route.ts # domain → brand + products + 4–6 concepts w/ copy (CDN-cached)
ad/route.ts # one concept → one 1:1 ad image (CDN-cached by URL)
page.tsx # the single page — hero morphs into the gallery
components/
ad-maker.tsx # hero, brand bar, progress, dynamic 4–6-slot gallery
hooks/
use-ad-maker.ts # legal Gallery stages, parallel rendering, retries, URL ownership
lib/
ad-run-policy.ts # run composition, ordering, and shared field limits
ad-run.ts # shared Ad Run contract, invariants, and canonical GET codecs
brand-color.ts # canonical Brand color validation
font-family.ts # safe styleguide Google Font family validation
context.ts # Context.dev Brand, page, styleguide, and Product adapter
net.ts # canonical domain normalization
public-raster.ts # DNS-pinned, size-bounded public logo loading
public-url.ts # cross-runtime public URL syntax policy
generate/
directions.ts # cross-runtime Creative Direction catalog
models.ts # Image Model tiers, names, and capabilities
concepts.ts # server-only prompt implementations
brief.ts # homepage summary + concept copywriting
colors.ts # hex → describable color phrases
gateway.ts # internal Vercel AI Gateway adapter
planner.ts # domain → validated Brief + 4–6 Planned Concepts
renderer.ts # one Planned Concept → retried Rendered Ad
public/ # logo, cover, ad examples

Tech stack

  • Next.js 15 (App Router) + React 19 + TypeScript
  • Context.devBrand data, homepage Markdown, styleguide extraction, and structured Product extraction
  • 🤖 Vercel AI SDK + AI Gatewaygpt-5.4-mini for concept picking & copy; gpt-image-1, gpt-image-2, grok-imagine-image, imagen-4.0, seedream-4.5, and recraft-v4.1 for the ads (one per ad)
  • 🌍 Vercel CDN — briefs and finished ads cached at the edge via Cache-Control: s-maxage
  • 🎨 Tailwind CSS + Geist font

Contributing

Contributions are very welcome — new creative directions, better prompts, alternative image models, UI polish, you name it.

  1. Fork the repo and create a branch: git checkout -b feat/my-feature
  2. Make your change — keep it focused; small PRs get reviewed fast
  3. Check it passesnpm run verify
  4. Open a PR describing what changed and why (screenshots or generated ads are a huge plus)

Found a bug or have an idea? Open an issue — no contribution is too small.

See CONTRIBUTING.md for the full guide.


Built using Context.dev

Branda gets its Brand metadata, logos, colors, homepage content, visual styleguide, and fact-grounded Products from a single API. Want to build your own brand-aware tool or agent?

importContextDevfrom"context.dev";import{zodSchema}from"ai";import{z}from"zod";constclient=newContextDev({apiKey: process.env.CONTEXT_DEV_API_KEY});constproductExtraction=z.object({products: z.array(z.object({name: z.string(),description: z.string(),}),).min(1).max(3),});constschema=awaitzodSchema(productExtraction).jsonSchema;const[brand,homepage,styleguide,productData]=awaitPromise.all([client.brand.retrieve({type: "by_domain",domain: "notion.com"}),client.web.webScrapeMd({url: "https://notion.com",useMainContentOnly: true,}),client.web.extractStyleguide({domain: "notion.com"}),client.web.extract({url: "https://notion.com",
schema,factCheck: true,}),]);const{ products }=productExtraction.parse(productData.data);

👉 Get your free API key →


License

MIT © Context.dev

Built with 🥠 by the Context.dev team.


Make it yours

Fork Branda to launch your own version, or copy the Context.dev adapter into an app you already maintain. Sign up for Context.dev and get your API key to start building.

About

MIT license open source ad maker

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - context-dot-dev/ad-maker: MIT license open source ad maker · GitHub
Skip to content

Repository files navigation

Branda logo

Paste a public domain. Get scroll-stopping, on-brand ads in seconds.

MIT LicensePowered by Context.devPRs welcomeNext.js 15

Make it yours: fork Branda into your own ad maker, or integrate its brand-research pipeline into an existing repo. Sign up for Context.dev to get your API key, then follow the quick start.

Branda — generate on-brand ads from a public domain


Built by the Context.dev team 🥠

Branda is an open-source ad generator that turns a public website domain into four to six polished, on-brand marketing creatives. The hosted experience needs no login, brief, or settings — the domain is the only input. Branda pulls the brand's identity from the Context.dev Brand API, uses its extracted styleguide palette and Google Font when available, and grounds one to three distinct products with structured web extraction. It then morphs the page in place into a gallery: three company ads followed by one ad for each extracted product.

Paste notion.com and Branda will:

  • 🎨 Pull the brand's logo and industry plus its styleguide palette and eligible Google Font
  • 👀 Read the homepage as Markdown so the copy can reflect the brand's real voice
  • 📦 Extract one to three distinct, fact-checked products with Context.dev web.extract and a JSON Schema generated from Zod
  • 🧠 Have an LLM pick a distinct creative direction and write tailored copy for three company ads plus one ad per extracted product
  • 🖼️ Render 4–6 distinct 1:1 ads in parallel — every ad uses a different image model (OpenAI, xAI, Google, ByteDance, Recraft)
  • ⚡ Mark successful briefs and ads for shared-CDN caching to reduce duplicate generation while entries are fresh
  • 📥 Download each ad (or every finished ad) and share to X, with best-effort clipboard copying when the browser permits it

Examples

Real outputs, straight from Branda — one public domain in, 4–6 ads out:

Stripe ad generated by BrandaNotion ad generated by BrandaLinear ad generated by Branda
stripe.comnotion.comlinear.app
Vercel ad generated by BrandaOpenAI ad generated by BrandaWebflow ad generated by Branda
vercel.comopenai.comwebflow.com

Example outputs are illustrative. Product names, logos, and trademarks belong to their respective owners; their appearance here does not imply sponsorship or endorsement, and the MIT license does not grant rights to those third-party marks.


Table of contents


What you get

  • Domain → 4–6 ads, one input — no formats to pick, no messages to write, no style dropdowns. Paste a domain and the page morphs into a live gallery as each ad lands.
  • Grounded in the real brand — logo and industry come from the Brand API; colors and an eligible Google Font come from the site's extracted styleguide, not a generic palette.
  • Company plus products — every Ad Run starts with exactly three company ads, followed by one to three ads for distinct products extracted and fact-checked against the site with Context.dev.
  • 12 creative directions — an LLM picks one distinct direction per ad, then writes a tailored headline and subheadline for the company or specific product being advertised.
  • Up to 6 image models racinggpt-image-1, gpt-image-2, and grok-imagine-image take the three company slots; one to three of imagen-4.0, seedream-4.5, and recraft-v4.1 render the product slots. Every ad streams in the moment its model finishes.
  • Fact-grounded copy — company headlines draw from the real homepage, while Product headlines draw from structured extraction and prompts that require factual positioning.
  • CDN-cacheable — successful brief and ad responses include shared-cache headers, reducing duplicate generation work behind Vercel or another compatible CDN.
  • All downloadable — every ad individually, or every finished ad at once. Sharing opens the X composer and copies the first finished image when the browser supports clipboard images.

The 12 creative directions

Every generation picks 4–6 distinct directions from these:

KeyStyleBest for
product_heroEditorial product shot, dramatic studio lightingPhysical products, hardware
isometricSaaS-landing-page isometric diagramB2B SaaS, dev tools, APIs
typographicSwiss-design poster, massive typeStatement-driven or abstract products
macro_materialExtreme close-up of a material/surfaceBeauty, food, fashion, premium finishes
gradient_fieldPure atmospheric gradientAI products, fintech, abstract services
editorial_spreadMagazine spread (Kinfolk/Monocle vibe)Lifestyle, food/drink, travel
sculptural_objectAbstract 3D object in studio spaceTech/AI with no physical product
data_vizChart-as-artAnalytics, BI, observability
blueprintTechnical schematic drawingEngineering, hardware, infrastructure
retro_arcadeLate-80s neon/grid aestheticGaming, playful brands
monochrome_cropTight single-hue detail cropLuxury, watches, minimalist brands
collageCut-paper layered collageAgencies, education, media

All twelve prompt templates share a strict typography spec (the only text allowed is the headline, subheadline, and wordmark) and hard rules (no hex codes, no placeholder text, no people/faces/hands). Styleguide colors are converted to phrases like "vivid purple", because image models literally print strings like #543cfc onto the art when given raw codes. When the styleguide's primary typography references a verified Google Font, its family name is passed into every image prompt; otherwise the prompt uses a neutral sans-serif fallback.


How it works

┌──────────────┐ GET /api/brief?domain=…&v=3 ┌──────────────────┐
│ Paste domain │ ──────────────────────────▶ │ Context.dev API │
└──────────────┘ └──────────────────┘
│ brand + homepage md + styleguide palette/typography
│ + 1–3 fact-grounded products via web.extract + Zod JSON Schema
▼
┌────────────────────────────────────────────────────┐
│ one LLM call plans 3 company concepts followed by │ gpt-5.4-mini
│ 1–3 product concepts, with grounded copy for each; │
│ distinct models: 3 primary, then 1–3 secondary │
└────────────────────────────────────────────────────┘
│ { brief, concepts[4..6] } ← cached on Vercel CDN
▼
4–6 × GET /api/ad?domain=…&concept=…&model=…&headline=…
│ each returns one 1:1 image ← cached on Vercel CDN
▼
Ads stream into the gallery · Download · Share on X
  1. The briefGET /api/brief makes four Context.dev calls in parallel: Brand data, homepage Markdown, styleguide extraction, and structured web extraction. Product extraction uses a JSON Schema generated from Zod and Context.dev fact checking. The planner derives two describable colors from the styleguide's accent/background/text palette and carries a typography family only when the styleguide marks it as a Google Font. One LLM call then writes three company concepts followed by one concept for each of the one to three distinct Products. Successful responses are shared-cacheable per versioned domain key (s-maxage=3600, one-day stale-while-revalidate).
  2. The ads — the client fires 4–6 parallel GET /api/ad requests, one per Planned Concept. Everything the prompt needs — including whether the subject is the company or a specific Product — travels in the query string, so compatible CDNs can cache each finished image by its full URL (s-maxage=86400, seven-day stale-while-revalidate). The three primary models can receive a validated raster logo as an image reference; unsupported or rejected logo inputs fall back to text-only generation. Transient failures retry with backoff; failed slots expose a per-ad Retry button, and errors are never cached.
  3. Ship — each ad fades into the dynamically sized gallery as its model finishes. Download one, download every finished ad, or share to X.

Context.dev APIs used

Branda makes exactly four Context.dev calls, all isolated in src/lib/context.ts. These links are the canonical API pages listed in the Context.dev documentation sitemap.

SDK operationWhat Branda uses it forAPI reference
client.brand.retrieveBrand name, description, slogan, industry, and logoRetrieve Brand Data
client.web.webScrapeMdHomepage Markdown for grounded company copy and reachability checksScrape Markdown
client.web.extractStyleguideAccent/background/text colors, visual mood, and eligible Google Font metadataExtract Styleguide
client.web.extractOne to three Products against a Zod-derived JSON Schema, with fact checkingExtract Structured Data

Want to use the same APIs in your own app? Create a Context.dev API key.


Quick start

Prerequisites:

# 1. Clone
git clone https://github.com/context-dot-dev/ad-maker.git
cd ad-maker
# 2. Install
npm install
# 3. Configure
cp .env.example .env
# add CONTEXT_DEV_API_KEY and AI_GATEWAY_API_KEY to .env# 4. Run
npm run dev # http://localhost:3000

Open http://localhost:3000, paste a domain, and watch 4–6 ads roll in. That's it.

Note

A single Vercel AI Gateway key serves everything Branda uses — concept picking, copy, and up to six image models — from one credit balance, with no per-provider keys to manage.


Configuration

All configuration is environment variables (see .env.example).

VariableRequiredDescription
CONTEXT_DEV_API_KEYYesContext.dev key — powers all four Context.dev API calls
AI_GATEWAY_API_KEYYesVercel AI Gateway key — powers concept picking + copy (gpt-5.4-mini) and up to six image models

API keys are read only by server code. Never prefix either secret with NEXT_PUBLIC_, commit .env, or paste a key into an issue, log, or screenshot.


Customize or integrate

The UI and renderer are separable from Context.dev enrichment, so you can reuse the adapter without adopting the gallery or image-generation stack.


Deploy safely

npm run build && npm run start runs the production app. On Vercel, import the repo and set the two required environment variables; the route hints allow up to 120 seconds for brief planning and 300 seconds for image rendering, so other hosts need equivalent request limits.

The included /api/brief and /api/ad routes invoke billable services and are intentionally callable by the browser. Before exposing your own deployment, add authentication and/or rate limiting appropriate to your audience, set provider spend alerts, and understand the cost of up to four Context.dev calls, one text-model call, and six image-model calls per uncached Ad Run. Successful responses benefit from a compatible shared CDN cache; failures use no-store.

The app loads Plausible (privacy-friendly, cookieless analytics) via a script tag in src/app/layout.tsx; forks should swap in their own Plausible script URL or remove the tag. The default UI also requests a Google-hosted font and Google favicon service; privacy-sensitive forks can self-host or remove those requests.


Scripts

CommandWhat it does
npm run devStart the Next.js dev server
npm run build / npm run startProduction build / serve
npm run typecheckTypeScript checks
npm testRun the interface and policy test suite
npm run test:watchRun tests in watch mode while developing
npm run verifyRun type checks, tests, and the production build

Project structure

The canonical domain language and module relationships live in CONTEXT.md.

src/
app/
api/
brief/route.ts # domain → brand + products + 4–6 concepts w/ copy (CDN-cached)
ad/route.ts # one concept → one 1:1 ad image (CDN-cached by URL)
page.tsx # the single page — hero morphs into the gallery
components/
ad-maker.tsx # hero, brand bar, progress, dynamic 4–6-slot gallery
hooks/
use-ad-maker.ts # legal Gallery stages, parallel rendering, retries, URL ownership
lib/
ad-run-policy.ts # run composition, ordering, and shared field limits
ad-run.ts # shared Ad Run contract, invariants, and canonical GET codecs
brand-color.ts # canonical Brand color validation
font-family.ts # safe styleguide Google Font family validation
context.ts # Context.dev Brand, page, styleguide, and Product adapter
net.ts # canonical domain normalization
public-raster.ts # DNS-pinned, size-bounded public logo loading
public-url.ts # cross-runtime public URL syntax policy
generate/
directions.ts # cross-runtime Creative Direction catalog
models.ts # Image Model tiers, names, and capabilities
concepts.ts # server-only prompt implementations
brief.ts # homepage summary + concept copywriting
colors.ts # hex → describable color phrases
gateway.ts # internal Vercel AI Gateway adapter
planner.ts # domain → validated Brief + 4–6 Planned Concepts
renderer.ts # one Planned Concept → retried Rendered Ad
public/ # logo, cover, ad examples

Tech stack

  • Next.js 15 (App Router) + React 19 + TypeScript
  • Context.devBrand data, homepage Markdown, styleguide extraction, and structured Product extraction
  • 🤖 Vercel AI SDK + AI Gatewaygpt-5.4-mini for concept picking & copy; gpt-image-1, gpt-image-2, grok-imagine-image, imagen-4.0, seedream-4.5, and recraft-v4.1 for the ads (one per ad)
  • 🌍 Vercel CDN — briefs and finished ads cached at the edge via Cache-Control: s-maxage
  • 🎨 Tailwind CSS + Geist font

Contributing

Contributions are very welcome — new creative directions, better prompts, alternative image models, UI polish, you name it.

  1. Fork the repo and create a branch: git checkout -b feat/my-feature
  2. Make your change — keep it focused; small PRs get reviewed fast
  3. Check it passesnpm run verify
  4. Open a PR describing what changed and why (screenshots or generated ads are a huge plus)

Found a bug or have an idea? Open an issue — no contribution is too small.

See CONTRIBUTING.md for the full guide.


Built using Context.dev

Branda gets its Brand metadata, logos, colors, homepage content, visual styleguide, and fact-grounded Products from a single API. Want to build your own brand-aware tool or agent?

importContextDevfrom"context.dev";import{zodSchema}from"ai";import{z}from"zod";constclient=newContextDev({apiKey: process.env.CONTEXT_DEV_API_KEY});constproductExtraction=z.object({products: z.array(z.object({name: z.string(),description: z.string(),}),).min(1).max(3),});constschema=awaitzodSchema(productExtraction).jsonSchema;const[brand,homepage,styleguide,productData]=awaitPromise.all([client.brand.retrieve({type: "by_domain",domain: "notion.com"}),client.web.webScrapeMd({url: "https://notion.com",useMainContentOnly: true,}),client.web.extractStyleguide({domain: "notion.com"}),client.web.extract({url: "https://notion.com",
schema,factCheck: true,}),]);const{ products }=productExtraction.parse(productData.data);

👉 Get your free API key →


License

MIT © Context.dev

Built with 🥠 by the Context.dev team.


Make it yours

Fork Branda to launch your own version, or copy the Context.dev adapter into an app you already maintain. Sign up for Context.dev and get your API key to start building.

About

MIT license open source ad maker

Resources

Code of conduct

Contributing

Security policy

Stars

66 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages