The practices FlowKy checks

13 standards and 65 checks. Published in full, because a checklist nobody can read is a checklist nobody agreed to β€” and because you should be able to disagree with one before you install anything.

These are defaults, not rules

Run a skill once and its standard is written to .flowky/skills/<id>.md in your project. Edit that file and the report follows it β€” the copy in your repository wins, it is reviewed like any other change, and it travels with the project rather than living in someone’s editor settings. A check you disagree with can be turned off there too, and the report says which ones you disabled rather than quietly omitting them.

Advertising & tracking

4 checks

Pixels, consent gating, attribution and third-party script cost.

  • No tracking pixel fires before consent in any jurisdiction that requires it.

A pixel in the document head runs before your banner has rendered.

  • Third-party scripts load deferred or after interaction. Each one blocking

the head delays first paint for every visitor, including the ones who

blocked it.

  • Conversion events are named in one place. Two spellings of the same event

split every report that matters.

  • UTM parameters are captured at first touch and kept, or attribution

silently credits the last thing the visitor clicked.

  • A consent rejection is honoured for the whole session, not re-asked on the

next page.

API

5 checks

Validation, authorisation, limits and error shape on your endpoints.

  • Every endpoint validates its input against a schema. A handler that reads

body.x directly trusts whatever arrives.

  • Writes take an explicit ALLOW-LIST of fields. Spreading a request body into

an update lets a caller set columns you never meant to expose β€” role and

status among them.

  • Authorisation is in the query, not a check before it. `WHERE id = ? AND

owner = ?` has no window between deciding and acting.

  • Errors are the same shape everywhere, and never leak a stack trace or a SQL

string to the caller.

  • List endpoints paginate. An unbounded list is a denial of service you wrote

yourself.

  • Anything unauthenticated that costs money, sends email or writes rows is rate

limited.

Database

6 checks

Migrations, indexes, connection handling and query shape.

  • Schema changes are versioned files applied by the deploy, not a command

someone remembers to run. Without that, code ships and the table does not.

  • Migrations are expand-only when they run before the deploy: add columns and

tables, never drop, or the currently running version breaks mid-release.

  • Every foreign key has an index. Postgres does not create one for you, and the

join that seems fine at ten thousand rows is not fine at ten million.

  • Money is stored in integer minor units, never a float.
  • Check-then-write is a race. Put the condition in the WHERE clause and check

how many rows you actually changed.

  • Credentials come from the environment. A connection string in the repository

is a credential in every clone and every fork.

Design system

5 checks

Tokens, theming, responsiveness and accessibility basics.

  • Colour, spacing and radius come from tokens. A hex code typed into a

component is one the theme can never reach.

  • Dark mode is defined by redefining tokens, not by scattering dark:

overrides β€” and a component with a hardcoded white cannot be fixed centrally.

  • Every interactive element has a visible focus state. Removing the outline

without replacing it makes the product unusable by keyboard.

  • Nothing conveys meaning by colour alone: about one man in twelve cannot

separate red from green.

  • Layouts are responsive by default. A fixed pixel width wider than 360 makes

the page scroll sideways on a phone.

  • Images declare dimensions, so the page does not jump as they load.

DevOps

5 checks

CI, deploys, rollback, secrets and whether anyone would notice an outage.

  • One deploy definition. If CI and a shell script both know how to ship, they

will disagree on the day it matters.

  • CI runs lint, types and tests BEFORE the build, so a failure costs seconds

rather than a full compile.

  • A green pipeline that deploys nothing is worse than a red one. Any step that

can silently skip must say so loudly.

  • Rollback is a traffic switch, not a rebuild. Rebuilding to roll back means

the outage lasts as long as a build.

  • Secrets come from a secret manager, are never printed, and never reach the

build context.

  • There is a health endpoint that reports the running version, so "what is

live" is answerable without guessing.

Landing pages

4 checks

First paint, the offer above the fold, and mobile behaviour.

  • One clear action per page. A page with five equal buttons has no call to

action, it has a menu.

  • The headline says what the product does for the reader, not what category it

belongs to.

  • Nothing wider than the viewport. One overflowing element makes the whole page

scroll sideways, and on a phone that reads as broken.

  • The viewport meta tag exists and does not disable zoom. Blocking zoom fails

accessibility outright.

  • Fonts and hero images do not block first paint.
  • Social proof is specific and true. A logo wall of companies who never paid

you is a liability, not a conversion.

Login & auth

7 checks

Password handling, sessions, and the paths that lead to account takeover.

  • Passwords are hashed with bcrypt, scrypt or argon2 β€” never a general-purpose

hash like SHA-256, which a GPU tries by the billion.

  • Sign-in, registration and password reset are rate limited. These are the

three endpoints attackers hit hardest.

  • Session cookies are httpOnly, secure and sameSite. A token readable from

JavaScript is a token an XSS steals.

  • Failure messages never distinguish "no such account" from "wrong password".

The difference is an account enumeration oracle.

  • Password reset links are single-use and expire. A reset link in an inbox is a

standing credential otherwise.

  • A banned, suspended or deleted account is refused on every path β€” including

API tokens issued before the ban.

  • OAuth account linking is not automatic on matching email unless that email is

verified by the provider.

MCP

4 checks

Declared MCP servers, their transports, and the secrets they carry.

  • MCP server configuration is committed so the team shares one set of tools,

but the credentials in it come from the environment.

  • Every server declares an explicit command or URL. A server that resolves

through a package manager at run time is a supply chain you did not choose.

  • Tools that write β€” file edits, shell, deploys β€” are separated from tools that

only read, so a read-only session can be granted without the rest.

  • A server that cannot be reached fails loudly. Reporting a connection that

did not happen is worse than reporting none, because the caller then waits

for tool calls that can never arrive.

Referral & partners

4 checks

Attribution, self-referral, payout races and the reward ledger.

  • A payout is claimed in ONE statement whose WHERE clause carries the

condition, and the code acts on the rows it actually changed. Read, check,

then write lets two concurrent requests both pass β€” and that is a double

payment.

  • Nobody can refer themselves. Check both the account and the email, because

the second account is free to create.

  • A reward is 'approved' and 'paid' separately. Marking money paid before it

moved makes the ledger lie.

  • Referral codes are unique and not guessable in sequence.
  • The attribution window is written down and enforced in one place.
  • Every reward row records what earned it, so a dispute has an answer.

SEO

7 checks

What a search engine can reach, read and represent.

  • Every indexable page has a unique <title> and meta description. Duplicates

across pages are worse than missing ones: they tell a crawler the pages are

the same.

  • robots.txt and a sitemap exist and agree with each other.
  • One <h1> per page, describing that page rather than the product.
  • Canonical URLs on anything reachable by more than one path β€” pagination,

query parameters, trailing slashes.

  • Open Graph and Twitter card tags, because a link shared without them renders

as a bare URL and loses most of its clicks.

  • Images carry meaningful alt text. "image" and "photo" are not meaningful.
  • Structured data where the content has a type search engines understand

(Article, Product, FAQ, Organisation).

Silent failures

5 checks

Fallbacks that hide breakage instead of reporting it.

  • A catch block either handles the error, logs it, or rethrows. An empty

catch is a decision to never find out.

  • A data loader that returns an empty array on failure must distinguish "there

is nothing" from "I could not read it". They look identical on the page and

mean opposite things.

  • A health or status check calls the dependency. Confirming that a key, a token

or an environment variable EXISTS proves the configuration, not the service β€”

and the two come apart for the most ordinary reasons, like an unpaid invoice.

  • A degraded state is visible. If the product silently serves something worse,

a human has to be able to tell from the outside that it is doing so.

  • Fallback content is distinguishable from real content, in the logs if not on

the screen. Canned answers that look like generated ones hide an outage.

  • Anything with a graceful fallback deserves a test that exercises the FAILURE

path, because the success path is the one that gets exercised by accident.

  • If a module has no callers, delete it or wire it up. Dead code that a page

reads from is a promise the page cannot keep.

Social media

4 checks

Share previews, profile links and what a pasted URL looks like.

  • Every shareable page has an Open Graph title, description and image. A link

pasted without them is a bare URL, and a bare URL is scrolled past.

  • The share image is 1200x630 and readable at thumbnail size. Text smaller

than a headline disappears in a feed.

  • Social profile links are correct and current. A dead link in a footer is a

small, permanent embarrassment.

  • Share images can be generated per page. One image for the whole site means

every article looks identical in a timeline.

  • Handles are consistent across platforms and match what the product is called.

Texts & wording

5 checks

Product copy: tone, consistency, placeholders and untranslated strings.

  • Error messages say what happened and what to do next. "Something went wrong"

tells the reader only that you also do not know.

  • No "simply", "just" or "obviously". If it were simple the reader would not be

stuck; the word only suggests the difficulty is their fault.

  • The product name is spelled one way, everywhere.
  • User-facing strings live in the translation layer, not inline in components,

or a second language becomes a rewrite.

  • No placeholder text in shipped surfaces. Lorem ipsum in production is a

visible sign nobody looked.

  • Buttons say what they do. "Send the quote" beats "Submit".