Your back is ad space.
Flair turns an X profile into a denim vest with 30 cells on the back. Brands rent patches on those cells by the day, the wearer sets the price and the rules, and the vest gets pinned so the timeline sees it.
Everything on a vest is plain geometry: a 5×6 grid, rectangles of cells, a price per cell per day. The rules that decide whether a patch fits, what it costs and when it comes off live in one dependency-free file, /lib/flair.js. The site uses it, the docs use it, and you can import it from this address.
Who it is for
- Wearers who have an audience and would like it to pay rent.
- Brands who want to be seen on one specific timeline instead of everywhere at once.
- Builders who want to draw vests, check selections or quote prices in their own pages.
Quick start
Three steps for a wearer, one for a brand.
- Open My vest and type your X handle.
- Set a daily price per cell and write your rules.
- Copy your vest link, post it and pin the post.
A brand opens any vest, presses Rent patches, selects a rectangle of free cells and chooses the number of days. To draw a vest in your own page, import the library:
.mjs extension so it loads as an ES module.How a vest works
A vest is a grid of 5 columns and 6 rows. Cells are numbered left to right, top to bottom, from 0 to 29. Cell i sits at column i % 5 and row floor(i / 5).
Cells and patches
A patch covers a filled rectangle of cells, from 1×1 up to 12 cells in total. Two patches never overlap, and an L-shape is never a patch. Cells with no patch on them are for sale at the wearer's price.
Life of a patch
- Selected. A brand picks cells.
check()says whether they make one patch. - Reserved. The brand pays
cells × days × price. Rent starts on payment. - Sewn. The patch shows on the vest and in the pinned post preview.
- Unpicked. At 00:00 UTC after the last full day the patch comes off and the cells go back on sale.
Make a vest
Go to My vest, type your handle without the @, choose a price and write your rules. You get a link like this:
| Param | Meaning |
|---|---|
u | Your X handle. Letters, digits and _, up to 15 characters. |
p | Price per cell per day, in SOL. Defaults to 0.01. |
r | Your rules, up to 160 characters, URL-encoded. |
rent | Opens the vest straight in rent mode. |
Price and rules
One number sets the price: SOL per cell per day. Bigger patches and longer rentals cost more, linearly. There is no auction and no surge pricing, because nobody wants a bidding war over their shoulder blade.
Rules are free text shown on the rent form, and a brand has to tick "I agree to the vest rules" before reserving. Short and specific works best. "No casinos, no wallet drainers" is the house favourite.
Pin it on X
Post your vest link with a line of your own and pin the post to your profile. The link preview shows the vest, so people see the patches without leaving the timeline. When patches change, post again and re-pin; X caches previews for a while.
Renting a patch
Open a vest, press Rent patches and tap free cells. The form tells you straight away if the selection is a valid patch, shows the end date in UTC and the total in SOL. Agree to the rules, press Reserve cells.
When it ends
Rent is counted in whole UTC days. A 7-day patch paid on 5 November comes off at 00:00 UTC on 13 November.
Patch art
On the site a patch is embroidered from three things: a label of up to 14 characters, one of ten icons and a thread colour. The renderer picks the font size so the label fits, and drops the label on patches that are too narrow for it.
| Icons | moon bolt wave star eye cherry flame heart spool button |
|---|---|
| Threads | cream rust ink teal rose moss butter lilac |
Each thread is a triple of background, merrow edge and ink colour, exported as Flair.THREADS.
Impressions
Every view of a vest is split between the patches on it in proportion to their size. A patch that covers 4 of 30 cells is credited with 4/30 of the views, rounded down. Empty cells credit nobody, so the wearer has a reason to sell them.
Clicks on a patch are counted separately from impressions. A click is a bonus, like a stranger complimenting your jacket.
flair.js API
All functions are pure and synchronous. Import the whole module or the parts you need.
| Function | Returns |
|---|---|
vestFor(handle, opts?) | A vest object. Featured handles come with their patches, any other handle gets a blank vest with opts.price and opts.rules. |
check(vest, cells) | { ok, rect, code, message }. rect is { x, y, w, h } when the cells make one free patch. |
quote({ cells, days, price }) | { cells, days, price, perDay, total } in SOL, rounded to 0.0001. Throws RangeError on bad days or price. |
endDate(days, from?) | A Date at 00:00 UTC after the last full day. |
impressions(views, cells) | Views credited to a patch of that size. |
occupied(vest) · free(vest) | A Set of taken cell indexes · the number of free cells. |
patchAt(vest, i) | The patch covering cell i, or null. |
rectOf(cells) | The rectangle the cells fill exactly, or null. |
renderVest(vest, opts?) | An SVG string. Options: id, selected, cells, empty. |
patchSVG(patch, id?) | One patch as SVG in vest coordinates. |
cellFromPoint(svg, x, y) | The cell under a pointer on a rendered vest, or -1. |
Try it
This box runs the real /lib/flair.js in your browser. Pick a vest, list some cells and see what check and quote say.
Constants
| Name | Value | Meaning |
|---|---|---|
COLS · ROWS | 5 · 6 | Grid size of every vest. |
CELLS | 30 | Cells per vest. |
PRICE | 0.01 | Default SOL per cell per day. |
MIN_DAYS · MAX_DAYS | 1 · 90 | Shortest and longest rent. |
MAX_CELLS | 12 | Largest patch. |
GEO | W 600, H 660, X0 150, Y0 172, S 60 | SVG geometry: canvas, grid origin and cell size. |
Patch format
A vest is a plain object. Patches are stored in grid units, never in pixels.
Error codes
| Code | When |
|---|---|
E_EMPTY | No cells selected. |
E_BOUNDS | A cell index is outside 0–29. |
E_TAKEN | Part of the selection already has a patch. |
E_TOO_BIG | More than 12 cells. |
E_SHAPE | The cells are not one filled rectangle. |
E_DAYS · E_PRICE | Thrown by quote() for days outside 1–90 or a price of zero or less. |
Limits and threat model
- Fake vests. A link can carry any handle. Only a connected X account gets the check mark; unverified vests say so at the top.
- Bad patches. The wearer's rules are part of every rental, and a wearer can refuse a patch before it is sewn.
- Stale previews. X caches link previews. A pinned post may show yesterday's patches for a while.
- Held cells. Before launch, held cells live only in your browser. Another browser sees them as free.
$FLAIR
$FLAIR is the coin of the workshop, on Solana. The contract is shown here as soon as it exists.
FAQ
Do people need to click a patch?
No. Rent is paid up front and impressions are credited for views. Clicks are counted separately.
Can a patch be any shape?
Any rectangle from 1×1 up to 12 cells. No L-shapes, no donuts.
What if two brands want the same cells?
Whoever pays first gets them. The other one sees "Part of that area already has a patch on it."
Can I change my price later?
Yes. New rentals use the new price, running patches keep the price they paid.