Advertising Config
Pricing for sponsors and paid placements.
File: config/advertising.config.ts
Controls pricing and limits for the three paid placements and for sponsor subscriptions. Each placement needs a matching Stripe Price ID.
What this controls
Sponsors
Monthly subscription for logos in the sidebar / partners section.
sponsors: {
maxSponsors: 8,
priceId: process.env.STRIPE_PRICE_ID_PARTNER_SUBSCRIPTION || null,
},| Field | Meaning |
|---|---|
maxSponsors | How many sponsor slots are active at any time. Extra buyers go on a waitlist. |
priceId | Recurring Stripe price — created in Stripe Dashboard. |
Promotions (three placement types)
promotions: {
ctaMaxLength: 20,
ctaDefault: 'Visit {name}',
allThreeDiscountPercent: 0.3,
allThreeDiscountCouponId: process.env.STRIPE_COUPON_ID_PROMO_ALL_THREE || null,
minPricePerMonth: 19,
placements: {
banner: {
id: 'banner',
name: 'Top Banner Ad',
description: 'Horizontal banner below the header',
pricePerMonth: 69,
priceId: process.env.STRIPE_PRICE_ID_PROMO_BANNER || null,
maxActive: 1,
},
catalog: {
id: 'catalog',
name: 'Catalog Ad Card',
description: 'Promoted card in the project grid',
pricePerMonth: 39,
priceId: process.env.STRIPE_PRICE_ID_PROMO_CATALOG || null,
maxActive: 2,
},
detailPage: {
id: 'detail_page',
name: 'Project Page Ad Card',
description: 'Sidebar card on project detail pages',
pricePerMonth: 19,
priceId: process.env.STRIPE_PRICE_ID_PROMO_DETAIL || null,
maxActive: 2,
},
},
},Fields explained
| Field | Meaning |
|---|---|
ctaMaxLength | Max characters in the custom button text on a promo card. |
ctaDefault | Fallback CTA if user didn't set one. {name} is replaced with the project name. |
allThreeDiscountPercent | Discount when buyer picks all three placements at checkout. |
allThreeDiscountCouponId | Stripe coupon ID used to apply that discount. |
minPricePerMonth | Cheapest placement price — used as "starts at" on the /promote page. |
maxActive | How many of that placement type can run simultaneously. |
Stripe setup
For each placement, create a recurring (monthly) Price in Stripe and paste the ID into .env.local:
STRIPE_PRICE_ID_PROMO_BANNER=price_...
STRIPE_PRICE_ID_PROMO_CATALOG=price_...
STRIPE_PRICE_ID_PROMO_DETAIL=price_...
STRIPE_PRICE_ID_PARTNER_SUBSCRIPTION=price_...For the "buy all three = 30% off" coupon:
- Stripe Dashboard → Coupons → Create
- Percentage off:
30, Duration:forever - Copy the coupon ID →
STRIPE_COUPON_ID_PROMO_ALL_THREE
Turning promotions off entirely
Disable the promotions flag in features.config.ts. The /promote page returns 404, the API routes return 404, the admin section disappears.
With AI
Update config/advertising.config.ts for my directory about {your niche}.
My monetization plan:
- Banner (top of every page) — {price}/month, {number} slot
- Catalog ad card (mixed into project grid) — {price}/month, {number} slots
- Project-page ad card (sidebar) — {price}/month, {number} slots
- Bundle discount if buying all three: {percentage}% off
- Sponsors (logos in sidebar / partners section) — {price}/month recurring, {max} active
Default CTA fallback when buyer doesn't set one: "Visit {name}" Max chars for custom CTA: 20
Set pricePerMonth, maxActive, and helper fields accordingly. Reference env vars (STRIPE_PRICE_ID_PROMO_*, STRIPE_PRICE_ID_PARTNER_SUBSCRIPTION, STRIPE_COUPON_ID_PROMO_ALL_THREE) on the priceId / couponId fields — don't hardcode. List the env vars I need to add.
See also: Promotions & Sponsors