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
- Deepens
- Compile the demand kit
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' } })
{
"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"
}
}
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.
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.
| Step | Verb | Returns | Price | Approval |
|---|---|---|---|---|
| 1. Read the offer, the brand and the pages | Collection.query | Every field your records hold for the kit | Free | Runs on its own |
| 2. Read each site’s current field limits | Page.audit | Field lengths, link formats and image sizes, read fresh when the stored ones are older than 90 days | About 0.16¢ | Runs on its own |
| 3. Render screenshots at each site’s sizes | File.generate | Screenshots, the logo and the social image as Files | Free | Runs on its own |
| 4. Fill and check each site’s fields | Collection.query | Each field filled, checked against its rule, or listed under missing | Free | Runs on its own |
| 5. Set the slot for each site | Collection.query | The post time per site from the declared table | Free | Runs 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
| When | Then |
|---|---|
| A site’s stored field limits are older than 90 days and its page cannot be read | The site compiles with the stored limits and is flagged limits-unverified. |
| A field fails its rule | The check names the rule and the length; it never trims or rewrites your words. |
| You call it again for the same offer version | It 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
| Ask | Compiles 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 |
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: 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
| Fact | Value |
|---|---|
| Guide | Content.compile |
| Guide approval | limits |
| 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. 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. |
| Trigger | on.Offer.published((offer, |
| Retry | Three times with backoff, then the next route; the same idempotency key never charges, sends or posts twice |
| Idempotency key | leaseline-content-compile-1 |
| Lookups | A 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
| Step | Function | Doer | Checker | Assurance | Inputs |
|---|---|---|---|---|---|
| 1. Read the offer, the brand and the pages | code | Code | Code checks each result against its declared type | measured | $0.offer |
| 2. Read each site’s current field limits | code | Code | Code checks each result against its declared type | measured | $0.venues |
| 3. Render screenshots at each site’s sizes | code | Code | Code reads the result back from where it landed | measured | $1.pages, |
| 4. Fill and check each site’s fields | code | Code | Code checks each result against its declared type | measured | $1, |
| 5. Set the slot for each site | code | Code | Code checks each result against its declared type | measured | $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
| Kind | What it touches |
|---|---|
| Systems | Media |
| Nouns | Collection, Page, File |
| Events | Collection.queried, File.generated |
Reference
Inputs, outputs, its Event and its errors
| Name | Type | Default | Meaning |
|---|---|---|---|
offer | Offer | Required | The offer the kit describes. |
venues | VenueId[] | ['product-hunt', | The launch sites to compile for. |
kind | 'launch-kit' | 'launch-kit' | The kit to compile. A listing kit for directories uses the same fields. |
maxCost | number | 0.25 | The 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).