Reading a website well enough to build a deck from it

"Paste your URL" is one sentence covering two unrelated jobs. The second — writing the slides, painting the pictures — is the one that gets advertised. The first is reading your site, and it is where a generated deck either becomes yours or becomes a template with your name typed into it.

What follows is what our reader does with an address, and what it refuses to guess. Most of these rules exist because an earlier version got something wrong on a real website, and those wrong answers are here too.

What reading your site costs
Pages fetched

1

The home page carries the palette, the logo, the navigation and the claims. A second page carries more of the same.

Stylesheets read

3, up to 1.6 MB

A budget across all three as well as a 1 MB cap on each: the per-file cap stops one enormous sheet stalling the read, the budget stops three of them.

Whole-read budget

20 seconds

Redirects included. Past it we stop and say so, rather than holding a spinner open.

Reading is not generating, so it is not billed

Fetching one page and parsing three stylesheets costs bandwidth and a few seconds. Writing fourteen slides and painting the eight pictures one timed deck asked for costs real money at a provider. Charging one credit for both would spend your budget before you had seen a slide.

The rule, as written in the code

The extraction endpoint never starts a generation, and the route says so in its own source: reading a website is not a generation and must not be counted as one. A deck is 25 credits; the read before it is zero.

The result is cached for an hour, keyed on the address and the kind of document asked for. What you typed in the box beside it is not part of the key — a shared link would otherwise hand the second visitor the first visitor's subject line. A refusal is never cached: a site down for a minute would otherwise be down for an hour.

The address, before it is a website

An endpoint that fetches whatever a stranger types is the textbook shape of server-side request forgery, so the unglamorous half of "paste your URL" is a guard in front of the fetch, carrying 36 tests of its own. The scheme must be http or https. The port must be 80 or 443, because a public host is still a route to that host's own admin panel. A literal address is decoded properly, so 2130706433, 0177.0.0.1, 0x7f.1 and ::ffff:10.0.0.1 are recognised as what they are. And every hop of a redirect chain gets the same treatment, not just the address you typed — five hops, eight seconds each, twenty for the chain, two megabytes maximum.

What the guard does not do

It does not close the DNS rebinding window. The runtime has no DNS API, so a name is checked by asking a public resolver over HTTPS. Between our lookup and the runtime's own, the record can change — a small, real gap that needs a connect-time hook the platform does not offer. And it does not read robots.txt. A half-parsed robots file is worse than an honest gap, so it is stated as one.

A palette that is theirs, not the first five hex codes in the CSS

The naive version takes the most frequent colours on the page. It always works and is almost always wrong, because every site has an ink and a paper and only some have a colour they would call theirs. Filling a brand slot with #111111 because it was the most common value is exactly the templated look the exercise exists to avoid.

Two real failures shaped the rule. A popular utility CSS framework emits its whole default scale onto :root — twenty-two hues at eleven steps — on every site built with it, whether or not one element uses one. On a well-known deployment platform's home page the first candidate we found was a near-white pink, handed back as that company's primary brand colour. It was the framework's colour, not theirs.

The second failure was the first fix, which listed that framework's hue names. The framework's own site then returned a near-white "olive", because olive was not on the list. Chasing names is endless. What every design system shares is the shape: a swatch in a scale is written name-step, and a colour a company calls theirs rarely carries a number unless the name already says which role it plays. So the test became the numbered step, which keeps --brand-600 working while rejecting the inventory. The cost is stated rather than hidden — a company whose only brand colour is --blue-600 gets an unset palette. That is the survivable error.

The five slots, and what is refused from each
SlotFilled fromRefused
paperA background declared on :root, html or body. A rule beats a theme-color, which only paints the browser's chrome.Anything declared inside a component, however full-bleed it looks.
inkA text colour on the same ground.The same.
primaryThe strongest surviving candidate: a custom property whose name claims a brand role, then a coloured theme-color, then a declared style on a link, button or heading, then any other custom property.Greys — saturation under 0.15, or luminance above 0.93 or below 0.02. The page's own ink and paper. Any variable whose name says ink or paper.
secondary, accentThe next two survivors. Additionally, any colour within 0.10 of one already taken.
Nothing foundThe slot stays empty and the deck is built unbranded.A house blue. Under no circumstances.

Both refusals earn their place. A palette of three shades of one blue is a single colour written down three times, and it produces a deck that looks like a gradient rather than a brand. And on one real site the variable --ink-2 is a dark navy, saturated just enough to pass the grey test, and it came back as that company's primary ahead of their actual cyan. Filtering on the resolved hex could not see that; filtering on the declared role could.

Light or dark, and why a media query does not decide it

The requirement is easy to state — a deck must not arrive white for a company whose site is black — and the subtle half is the inverse. A site that is white by default and black under prefers-color-scheme: dark is a white site. Merging that dark block in, the obvious way to write the parser, produces a black deck for a white company.

A measured wrong answer sits behind the selector rule too. A national government's site — one of the plainest white pages on the internet — declares its ground on :root, then declares a #383f43 background on :root followed by a class, for one dark component. A pattern that checked only how a selector started matched the second rule, the later declaration won, and the page came back dark. A selector must now be the root element and nothing after it.

Evidence for light or dark, by weight
SourceWeightWhy it ranks there
Background colour on the page's own ground100The page stating what it is. Luminance below 0.45 is dark.
color-scheme in CSS80The author naming the page's resting scheme in the one place that is not a guess. Only from an unconditional rule, and only a single word: in CSS, dark light is read as no evidence either way.
dark or light on an html or body attribute70Deliberate, but usually toggled by script we never run.
meta name="color-scheme"65The same statement, one step further from the pixels — and here dark light does count, because the order is the opinion and the first token is read rather than the presence of the word "dark".
Paper via theme-color, then a class token containing "dark"55, 40The weakest things that are still evidence.
Nothing saidReturns nothing. That is not "light" — it means use your own default rather than a scheme we invented.

Picking a logo, or picking nothing

The order is by how deliberate the statement is, and every rung is the company saying something rather than us inferring it.

01 The organisation block they publish themselves

Structured data is the one place most sites state their own name, logo and line of work in a form they wrote deliberately. It is not scraped inference, so it outranks everything else.

02 An image they labelled as a mark

An <img> whose source, alt text, class or id contains "logo", "wordmark", "brandmark" or "lockup". Where a srcset exists the widest candidate is taken: a mark scaled up from a thumbnail looks worse than none.

03 Their site icon, largest declared size first

Offered and labelled as an icon rather than returned as the mark, because an icon is a logo cropped to a square, which is not the same thing.

04 Nothing, and the deck is built unbranded

Deliberately absent from this ladder: "the first image in the header". A header's first image is a hero photograph about as often as it is a mark, and a deck carrying a stranger's stock photo where the logo should be is worse than one carrying neither.

Only PNG and JPEG are accepted: nothing in the runtime rasterises an SVG, and fetching a file we cannot place is a fetch we should not make. The logo also comes back through the same guarded fetch as everything else — a bare request "just for the image", aimed at an address taken out of a stranger's HTML, is the same security hole one hop further away.

Tone, and how a company frames its own pictures

Tone is measured from the page's prose and refuses to answer more often than it answers. Under 120 words there is nothing to measure. Above that it counts words per sentence, first- and second-person density per thousand words, formal markers and contractions, and reports "formal" or "warm" only when one side scores at least two of its three signals and the other scores none. That is correct rather than timid: falling back to a house default is legitimate — a measured tone that is wrong is not, because it reaches the writer as something the client stated.

Framing is read the same way. Up to 24 content images are sampled — logo and icons dropped first, since the furniture of a page is styled nothing like its photographs — and a treatment is reported only when at least two agree and they are at least 40 per cent of the sample. A single rotated logo does not make them a slanted-frame company.

What we will not guess

In an earlier version, a preference nobody had ever been asked about sat in the intake with a default and reached the writer as a client position on eleven of twelve delivered decks, measured in the database. A crawler is a machine for producing that fault at scale. So every answer the reader fills carries a provenance entry naming the element it came from, and anything without one is left out. Three fields where the temptation is strongest:

Where a required question is unanswered it comes back marked missing, carrying the form's own wording for the question rather than an answer, and the screen puts it to you once. No answer is a question on a screen. A wrong answer is a deck built around a stranger's logo wall.

What it costs after the reading

Ten credits are granted on signup, a credit is one US dollar during the alpha, and the catalogue is a slide deck at 25 credits, a branded document at 10, a data report at 15 and a single image at 1. Every price here is an indicative estimate, not a quote. The free grant is deliberately smaller than a deck: enough to read your site, see what it filled and where each field came from, and make an image or a document first.

What happens after you press generate is measured separately — 58 delivered decks, mean 340 seconds, fastest 139, slowest 1,432, and 69 of 79 jobs delivered across every kind. The distribution is in the timing note.

What we could not determine

Limits of this reader

Whether the palette is right. We can tell you which stylesheet, which rule and which property every hex came from. We cannot tell you it is the colour the company's designer would have named. Provenance is checkable; correctness is a judgement, and the screen is editable for that reason.

One page only. A crawl that follows links is a crawl whose cost a stranger chooses. A brand colour that appears only on an interior page is invisible to us, and so is a fourth stylesheet.

Declared styles, not computed ones. There is no layout engine and no viewport, so specificity is applied crudely — ids beat classes beat tags, later beats earlier at a tie — and cascade layers, colour mixing and per-element variable resolution are not modelled. A selector is read by its last compound only, so .card > img.thumb can match an image outside the card it was written for. An ancestor test needs a tree; the parser is a stream.

A hit rate. We have not published what share of sites come back with a full palette, a logo and a measured tone versus how many come back mostly unset. It is the number a buyer would most want from this page. When we have it, it goes here whatever it says.

Where every number on this page comes from

Provenance
Figure or ruleSource
One page · 3 stylesheets · 1.6 MB budget · 20 s total · 24 images sampledThe declared limits in the extraction module. The per-sheet cap was raised to 1 MB from 700 KB after a real site's 762 KB stylesheet — the one holding its palette — was refused for sitting 62 KB over it.
Reading a site costs 0 credits · one-hour cache keyed on the address, not on what you typedThe extraction route, which generates nothing and is not metered, and the cached wrapper around the crawl.
Schemes, ports, decoded literal addresses, per-hop redirect checks, 5 hops, 8 s each, 20 s, 2 MBThe URL guard module, which carries 36 tests of its own.
Grey test at saturation 0.15 and luminance 0.93 / 0.02 · near-duplicate rejection at 0.10 · the scale-entry rule and the two wrong answers behind itThe colour utilities, the palette resolver and the candidate filter, which records both measured cases in its comments.
Light-or-dark weights: 100 / 80 / 70 / 65 / 55 / 40The scheme decision function. The root-selector rule beside it records the government site reported as dark.
Tone floor of 120 words · framing consensus of 2 images and 40% · PNG and JPEG onlyThe tone reader, the framing function's defaults, and the accepted image types in the guard.
A default reached the writer as a client position on 11 of 12 delivered decksRecorded in the intake module and measured in the portal's database. It is why every crawled answer now carries provenance.
58 decks, mean 340 s, fastest 139 s, slowest 1,432 s · 69 of 79 jobs deliveredThe studio_jobs table in the portal's production database, 23 August 2026.
25 / 10 / 15 / 1 credits, $1 per credit, 10 free on signupThe published catalogue on the product page. Indicative estimates during the alpha, not quotes.

If you are comparing tools, the question that separates them is not how fast the deck appears. It is what the tool did when your site did not answer something — left the field empty and asked you, or filled it with something reasonable and never mentioned it. The second is invisible until the deck is in front of a client.