Skip to content

Launch kit

Your offer in, every launch site’s fields filled and checked against its limits, with screenshots at its sizes and the best slot to post.

Kind
Workflow
Price
0.16¢ per 8 sites
Your time
15 minutes
Approval
Runs on its own
Content.compile
You, to your agent

Get Leaseline’s launch kit ready for Product Hunt, Hacker News and Reddit next Tuesday, spend up to $1, and show me the plan first.

curl -X POST "https://api.sb/leaseline.app/content/compile?mode=try" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"goal":"Get Leaseline’s launch kit ready for Product Hunt, Hacker News and Reddit next Tuesday, spend up to $1, and show me the plan first.","budget":{"amount":1,"currency":"USD"}}'
npx startup-builder do Content.compile --try --data '{"goal":"Get Leaseline’s launch kit ready for Product Hunt, Hacker News and Reddit next Tuesday, spend up to $1, and show me the plan first.","budget":{"amount":1,"currency":"USD"}}'
{
  "name": "do",
  "arguments": {
    "mode": "try",
    "code": "return await $.Content.compile({ goal: 'Get Leaseline’s launch kit ready for Product Hunt, Hacker News and Reddit next Tuesday, spend up to $1, and show me the plan first.', budget: { amount: 1, currency: 'USD' } })"
  }
}
import { $ } from 'startup-builder'

const result = await $.try.Content.compile({ goal: 'Get Leaseline’s launch kit ready for Product Hunt, Hacker News and Reddit next Tuesday, spend up to $1, and show me the plan first.', budget: { amount: 1, currency: 'USD' } })
Response
{
  "mode": "try",
  "stored": false,
  "estimate": "About 0.16¢ per 8 Venues",
  "sample": {
    "venue": "Product Hunt",
    "tagline": "Rent and renewals, off the spreadsheet",
    "check": "41 of 60 characters",
    "missing": "first comment",
    "slot": "Tue 12:01 PT"
  }
}
Try mode reads, stores nothing and spends nothingAPI referenceIts Nouns

What you get

  • 8 sites · Your offer in, every launch site’s fields filled and checked against its limits, with screenshots at its sizes and the best slot to post. · Content
  • venues[].fields · Each field the site asks for, filled from your records: name, tagline, topics, description, first comment.
  • venues[].checks · Each field against the site’s rule, such as a Product Hunt tagline of 60 characters or fewer, and pass or fail.
  • venues[].missing · Fields your records cannot fill, such as the maker’s first comment; Launch day writes these.
  • assets · Screenshots, the logo and the social image, rendered at each site’s sizes.
  • calendar · The slot for each site from a declared table: Product Hunt at 12:01 PT on a Tuesday to Thursday, Show HN at 8 to 10 ET on a weekday.

How long: About 20 seconds.

Trigger

It runs when you call it, and each time the offer is published again.

TypeScript
on.Offer.published((offer, $) => $.Content.compile({ kind: 'launch-kit', offer: offer.$id }))

Steps

Your agent does these steps, one row per step; each step’s check is part of its row and its price.

StepVerbReturnsPriceApproval
1. Read the offer, the brand and the pagesCollection.queryEvery field your records hold for the kitFreeRuns on its own
2. Read each site’s current field limitsPage.auditField lengths, link formats and image sizes, read fresh when the stored ones are older than 90 daysAbout 0.16¢Runs on its own
3. Render screenshots at each site’s sizesFile.generateScreenshots, the logo and the social image as FilesFreeRuns on its own
4. Fill and check each site’s fieldsCollection.queryEach field filled, checked against its rule, or listed under missingFreeRuns on its own
5. Set the slot for each siteCollection.queryThe post time per site from the declared tableFreeRuns on its own

Calls: Collection.query, then Page.audit, then File.generate, then Collection.query.

About 0.16¢ per 8 sites, each time it runs, capped at 25¢.

Example: give it a goal

Get Leaseline’s launch kit ready for Product Hunt, Hacker News and Reddit next Tuesday, spend up to $1, and show me the plan first.

The plan it shows runs 5 steps, priced before it spends anything; Run it above shows the result it returns.

When something fails

Each failure, and what happens next
WhenThen
A site’s stored field limits are older than 90 days and its page cannot be readThe site compiles with the stored limits and is flagged limits-unverified.
A field fails its ruleThe check names the rule and the length; it never trims or rewrites your words.
You call it again for the same offer versionIt returns the same kit at $0: it is keyed on offer, sites and offer version.

Each step retries three times, then falls through to the next route; one item's failure lands in skipped with its reason, never failing the call. Before a step would cross maxCost it stops and returns what it has, with a resume link. Each step's idempotency key is the call's key plus the step and the item: leaseline-content-compile-1-<step>-<item>.

Change it

AskCompiles to
Write the missing fields in my voice.Post.launch
Add Hacker News and Indie Hackers to the sites.Content.compile
Make a listing kit for directories from the same fields.Post.submit
TypeScript
import { $, workflow } from 'startup-builder'

export default workflow({
  name: 'compile-demand-kit',
  verb: 'Content.compile',
  input: { kind: "'launch-kit'", offer: 'string', venues: 'string[]' },
  maxCost: 0.25,
  execute: async (ctx, { offer, venues = defaultLaunchVenues }) => {
    const src = await ctx.step('read', () => $.Collection.query({ from: ['offer', 'brand', 'page'], where: `offer = '${offer}'` }))
    const limits = await ctx.step('limits', () => $.Page.audit({ urls: venueLimitUrls(venues, { olderThan: '90d' }), fields: ['content'], maxCost: 0.01 }))
    const assets = await ctx.step('render', () => $.File.generate({ kind: 'screenshots', sizes: venueSizes(venues), from: src.pages }))
    return venues.map((v) => ({ venue: v, ...fillAndCheck(v, src, limits), assets, at: bestSlot(v) }))   // declared tables
  },
})

Extend it with extends: 'Content.compile' and base(), or compose your own from these steps.

Works with

Plays that order it: Reuse what you already published, Category kit, Data stories, Guest on podcasts and newsletters, Launch sites, Launch week, Deposits before you build.

It serves Make content, and runs in Launch and search, Borrowed. It deepens Compile the demand kit.

For agents

For agents: the guide, its approvals, retries and lookups
FactValue
GuideContent.compile
Guide approvallimits
GoalGet Leaseline’s launch kit ready for Product Hunt, Hacker News and Reddit next Tuesday, spend up to $1, and show me the plan first. It may change counts, the order of steps, soft filters and the route a read takes, and it stops early when the goal is met. It never relaxes your words, raises its own budget, answers its own approval, calls a Play or acts outside your standing approval.
Triggeron.Offer.published((offer, $) => $.Content.compile({ kind: 'launch-kit', offer: offer.$id }))
RetryThree times with backoff, then the next route; the same idempotency key never charges, sends or posts twice
Idempotency keyleaseline-content-compile-1
LookupsA find: input asks unless exactly one record fits
Step
1. Read the offer, the brand and the pages
2. Read each site’s current field limits
3. Render screenshots at each site’s sizes
4. Fill and check each site’s fields
5. Set the slot for each site

The amounts live once, on the hub (approvals).

Who does each step, and how it is checked
StepFunctionDoerCheckerAssuranceInputs
1. Read the offer, the brand and the pagescodeCodeCode checks each result against its declared typemeasured$0.offer
2. Read each site’s current field limitscodeCodeCode checks each result against its declared typemeasured$0.venues
3. Render screenshots at each site’s sizescodeCodeCode reads the result back from where it landedmeasured$1.pages, $2.sizes
4. Fill and check each site’s fieldscodeCodeCode checks each result against its declared typemeasured$1, $2
5. Set the slot for each sitecodeCodeCode checks each result against its declared typemeasured$2.venues

The doer is never the checker, and the weakest assurance on the path is the whole call’s.

Under the hood

Under the hood: the Systems, Nouns and Events it touches
KindWhat it touches
SystemsMedia
NounsCollection, Page, File
EventsCollection.queried, File.generated

Reference

Inputs, outputs, its Event and its errors
NameTypeDefaultMeaning
offerOfferRequiredThe offer the kit describes.
venuesVenueId[]['product-hunt', 'hacker-news', 'reddit', 'x', 'linkedin', 'betalist', 'indie-hackers', 'peerlist-launchpad']The launch sites to compile for.
kind'launch-kit''launch-kit'The kit to compile. A listing kit for directories uses the same fields.
maxCostnumber0.25The most this call spends each time it runs, in USD. It stops before a step would cross it and returns what it has, with a resume link.

Emits Content.compiled. Refuses with max-cost before it spends, and with the Data calls and Accounts groups (refusals).

Contents