docs · flair.js 0.1.0
Start

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.
Start

Quick start

Three steps for a wearer, one for a brand.

  1. Open My vest and type your X handle.
  2. Set a daily price per cell and write your rules.
  3. 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:

NOTEIn Node, save the file with a .mjs extension so it loads as an ES module.
Start

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

  1. Selected. A brand picks cells. check() says whether they make one patch.
  2. Reserved. The brand pays cells × days × price. Rent starts on payment.
  3. Sewn. The patch shows on the vest and in the pinned post preview.
  4. Unpicked. At 00:00 UTC after the last full day the patch comes off and the cells go back on sale.
Wearers

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:

ParamMeaning
uYour X handle. Letters, digits and _, up to 15 characters.
pPrice per cell per day, in SOL. Defaults to 0.01.
rYour rules, up to 160 characters, URL-encoded.
rentOpens the vest straight in rent mode.
WARNINGUntil you connect X, a vest shows as an Unverified X profile. Anyone can make a link with your handle, so brands are told to look for the check mark.
Wearers

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.

Wearers

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.

Brands

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.

NOTEUntil payments open with the launch, Reserve holds your cells in your own browser for 24 hours and shows the quote. Nothing is charged.
Brands

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.

Iconsmoon bolt wave star eye cherry flame heart spool button
Threadscream rust ink teal rose moss butter lilac

Each thread is a triple of background, merrow edge and ink colour, exported as Flair.THREADS.

Brands

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.

Reference

flair.js API

All functions are pure and synchronous. Import the whole module or the parts you need.

FunctionReturns
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.
Reference

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.


    
Reference

Constants

NameValueMeaning
COLS · ROWS5 · 6Grid size of every vest.
CELLS30Cells per vest.
PRICE0.01Default SOL per cell per day.
MIN_DAYS · MAX_DAYS1 · 90Shortest and longest rent.
MAX_CELLS12Largest patch.
GEOW 600, H 660, X0 150, Y0 172, S 60SVG geometry: canvas, grid origin and cell size.
Reference

Patch format

A vest is a plain object. Patches are stored in grid units, never in pixels.

Reference

Error codes

CodeWhen
E_EMPTYNo cells selected.
E_BOUNDSA cell index is outside 0–29.
E_TAKENPart of the selection already has a patch.
E_TOO_BIGMore than 12 cells.
E_SHAPEThe cells are not one filled rectangle.
E_DAYS · E_PRICEThrown by quote() for days outside 1–90 or a price of zero or less.
Project

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.
Project

$FLAIR

$FLAIR is the coin of the workshop, on Solana. The contract is shown here as soon as it exists.

Project

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.