Skip to the list

Rounds · a free guide

Slovenščina

What a finished website has

This is the list we go through on the websites we look after. For each item it says what a finished site has, why it matters, and how you can check it yourself – most checks need nothing more than a browser. It is written for the people who run the websites of small organisations – non-profits, institutes, event organisers, small businesses – and for the developers they call when something breaks.

Checked against its sources in September 2026; the sections on AI assistants and on screens in October 2026. This is not legal advice. The legal items say what the rules generally require, for the EU, Slovenia and, where it differs, Serbia, and link to the source; for your own situation, ask a lawyer.

How to read the badges

How much it matters

Must
required by law, or without it you lose visitors or data.
Should
a real, measurable cost if it is missing.
Nice to have
polish, or insurance.

Who can check it

From outside
anyone with a browser, no access needed.
Needs the code
someone has to read the site’s code.
Needs your accounts
the hosting, domain, email or database dashboards.
Needs a person
judgement: legal wording, content, a screen reader, real phones.

About the checklists that go around

Short lists – “20 things your website is missing” – circulate on social media, and some of their points are on this page too. We checked each one against the sources behind the rest of the page. Most hold. Several are true only in some cases. And the problems that most often cost a site its visitors, its data or its money are not on them at all.

These hold, as they are usually stated

True only in some cases

What those lists leave out

The five at the top are about how a site feels, and each has an edge worth knowing. A skeleton that is not the size of the real content causes the very jump it is meant to prevent. Caching must never keep one person’s data for another. Tooltips do not exist on a touch screen. An instant response must never be used where a false success would mislead. And a notification that disappears after four seconds cannot be the only place an error is shown.

Almost nothing on this page stays done. An update, a new page or a new tool can undo it without anyone noticing – checking a site once gives you a list; keeping it true is upkeep, and upkeep is what Rounds does. Kept in rounds →

Back to contents

When something goes wrong

What a finished site does when a link is wrong, a list is empty, a form fails, the network drops, the site is being moved, time passes, or someone sends it nonsense.

See also: Skeletons while content loads, Short notifications that confirm an action, Instant response, where it is safe

  1. Error pages in the site’s language: 404 and 500Priority: Should. Who can check: From outside, Needs the code
    Why
    People arrive through old links, mistyped addresses and last year’s posters. A finished site answers them in the page’s own language with a way back, and with the status code 404, so that search engines do not index “not found” as a real page. When something breaks inside the site, an error page shows a friendly message and a way to try again instead of a blank screen, and the error is recorded.
    Check it yourself
    Open a made-up address such as /abc123 on your site, and the same under each language (/en/abc123). You should see a page in that language with a link home, not the framework’s English “This page could not be found.” In DevTools → Network the page’s row should show status 404. Try a made-up event or article too (/events/abc123): “not found” text with status 200 is a “soft 404”. The 500 page cannot be triggered from outside; ask your developer to show it to you.
    For your developer
    Next.js: app/not-found.tsx; with next-intl also a not-found.tsx and a catch-all route under [locale], or unknown paths fall through to the root 404. Data lookups in server components call notFound(). error.tsx and global-error.tsx exist and report to logging; forms, maps and games get their own error boundary, so one crash does not take down the page.
    Sources
  2. Empty lists that say soPriority: Should. Who can check: Needs a person, Needs the code
    Why
    Lists edited in a CMS are sometimes empty: no sponsors yet, programme not published, no news this month. A finished site then says so in a sentence, or hides the section, instead of showing a heading over nothing – or crashing because a field it expected is missing.
    Check it yourself
    On a preview or a copy of the site, empty a list or clear an optional field in the CMS and look at the page. Go through every page that shows a list – news, events, partners, gallery – and ask what it would look like with nothing in it.
    For your developer
    List components handle [], and optional CMS fields are checked before they are read.
  3. Forms that tell the truthPriority: Must. Who can check: From outside, Needs the code
    Why
    The worst thing a form can do is say “Thank you!” when nothing was saved or sent: people who hear nothing back register twice, or give up. A finished form reports success only after the server has confirmed it, says what is wrong next to the field and in the page’s language, and never says “try again” about a problem that trying again cannot fix.
    Check it yourself
    Send the form with a mistake in it – an email address without @, a required field left empty. The message should appear beside the field that is wrong, in the page’s language, before anything is sent. Then, on a test copy, switch DevTools → Network to “Offline” and send a correct form: you should see an honest error and another way to reach you, not “Thank you”. After a real test entry, check that it arrived where it should, and that the confirmation email came if the form promised one.
    For your developer
    Set the success state only after awaiting the server’s answer; no .then() whose result is ignored. Server-side validation mirrors the client’s, and a server refusal is shown as the same message at the same field. Errors are announced with role="alert" or aria-live.
    Source
    See also
    A thank-you page that says what happens next, Forms everyone can fill in
  4. Flaky networks and no networkPriority: Nice to have. Who can check: From outside, Needs the code
    Why
    A form sent on a train should say “you’re offline, try again” rather than spin forever. A site whose web manifest says display: standalone invites visitors to add it to their home screen; without a service worker, that installed “app” opens on the browser’s offline dinosaur.
    Check it yourself
    In DevTools → Network, choose “Offline” and send a form: you should get a clear message within seconds. If your phone’s browser offers to install the site or add it to the home screen, do it, switch on airplane mode and open it.
    For your developer
    Every fetch has a timeout and a catch, and the interface has an explicit error state. Either ship a service worker with an offline page, or drop display: standalone from the manifest.
  5. A maintenance page, ready before you need itPriority: Nice to have. Who can check: Needs the code, Needs your accounts
    Why
    For a migration, a DNS move or a CMS outage you want one switch that shows “we’ll be back soon” with the status 503 and a Retry-After header. A normal page, or a 404, during that window tells search engines the site is gone.
    Check it yourself
    Ask your developer: “If we had to take the site down for an hour tonight, what would we switch on?” A finished site has an answer that is already prepared, not one built on the night.
    For your developer
    An environment flag read by middleware, or a Vercel or Cloudflare rule set up in advance.
  6. Pages that change with timePriority: Should. Who can check: From outside, Needs the code, Needs a person
    Why
    Registration closes, the event passes, the places fill up, the campaign ends. A week after the event a finished site no longer says “Register now”, and if plans change, the event data search engines read says so too (eventStatus, for example postponed or cancelled).
    Check it yourself
    Look at the site the day after an event or a deadline, or ask your developer for a preview with the date moved. Buttons and texts should have changed by themselves. In the page source, search for endDate and compare it with today.
    For your developer
    Dates live in data, and the interface decides by the current time in the event’s time zone (Europe/Ljubljana, Europe/Belgrade).
  7. Nonsense in, a clear “no” outPriority: Should. Who can check: From outside, Needs the code
    Why
    When a malformed address or ID makes the server answer with a 500 error, an unchecked value has usually reached the database. A finished site answers bad input with a 4xx status and a message, which also keeps its error log free of noise.
    Check it yourself
    Take an address that contains an ID or a name – of an event, an article – and replace that part with junk such as %%% or a very long string. You should get a 404 or 400 page, never a 500 “Internal Server Error”. Do this only with pages you can open; do not send forms.

Back to contents

Turning visitors into action

Most sites exist so that someone does something: registers, buys a ticket, books, writes. These are what make that easy.

See also: Forms that tell the truth, Short notifications that confirm an action

  1. A clear call to action without scrollingPriority: Should. Who can check: Needs a person, From outside
    Why
    On the pages that matter – the home page, an event, a service – the one thing you want visitors to do is visible on the first screen, on a phone as well as on a computer. It is worded as the action itself, “Register for 3 October” rather than “Learn more”, and it does not compete with four other buttons of the same weight. If people have to look for it, some of them will not.
    Check it yourself
    Open your key pages on a phone and, without scrolling, say out loud the one thing the page asks you to do. If you cannot, or there are several equal buttons, the page needs one clear action.
  2. A sticky button for the main action on phonesPriority: Nice to have. Who can check: From outside, Needs a person
    Why
    On a long page read on a phone, a small bar at the bottom of the screen with the main action – Register, Buy tickets – saves visitors scrolling back up to find it. It never covers text, form fields, the cookie banner or the site’s own messages, and it steps aside where it would only repeat itself, such as on the form it leads to.
    Check it yourself
    On a phone, scroll a long page to the very end: the last lines and buttons should still be readable above the bar. Open the cookie banner and the form, and tap into a field so the keyboard opens: nothing should overlap.
    For your developer
    Reserve room for it: padding-bottom on the page equal to the bar’s height plus env(safe-area-inset-bottom). Hide it while an input has focus.
    See also
    A consent banner – only when something non-essential runs
  3. A thank-you page that says what happens nextPriority: Should. Who can check: From outside
    Why
    After a form is sent, a finished site shows a confirmation – a page or a clear state – that says what was received, what happens next and when, and whom to contact, in the page’s language. It appears only once the server has confirmed the submission, and it matches what the confirmation email says.
    Check it yourself
    Send a test entry through each form and read what comes back: would a first-time visitor know that it worked and what to expect? Reload the thank-you page: it should not send the form a second time.
    See also
    Forms that tell the truth, A confirmation in the visitor’s language
  4. Real contact details, not only a formPriority: Should. Who can check: From outside, Needs a person
    Why
    People trust an organisation they can reach: its name, an email address, a phone number and a postal address, on a contact page and in the footer. A form alone leaves them unsure whether anyone reads it, and leaves no way in when the form itself fails.
    Check it yourself
    From any page, find the organisation’s name, an email address, a phone number and an address within one click. Write to the address and call the number once: someone should answer.
    See also
    Provider details (imprint)

Back to contents

Privacy and consent

What the law asks of a site that collects anything personal, and the details that decide whether a privacy notice and a consent banner actually hold.

  1. A privacy noticePriority: Must. Who can check: From outside, Needs a person
    Why
    As soon as a site collects anything personal – a form, IP addresses in logs, analytics – it needs a notice that says who is responsible and how to reach them, what is collected and why, on what legal basis, which services process it, whether it leaves the EU, how long it is kept, what rights people have, and where they can complain (in Slovenia to the Information Commissioner, in Serbia to the Poverenik). Public bodies also name their data protection officer. It describes what the site actually does, not a template.
    Check it yourself
    Find the privacy link in the footer of every page and next to every form, in every language. Read the notice with DevTools → Network open on another page: every outside service you see there should be named in the notice, and nothing in the notice should be untrue.
    Sources
  2. Scripts added on the way to the visitorPriority: Must. Who can check: From outside, Needs your accounts
    Why
    A service in front of your site, such as Cloudflare, can add its own analytics beacon to every page (Cloudflare Web Analytics with “automatic setup”) or rewrite email addresses in the HTML. Your consent banner cannot stop a script it never sees; it has to be switched off in the provider’s dashboard.
    Check it yourself
    Compare the HTML a browser actually receives (View source) with what your developer says the site contains. A script neither of you added came from the service in front of the site.
  3. Fonts and scripts from your own serverPriority: Must. Who can check: From outside
    Why
    Loading Google Fonts from Google’s servers sends each visitor’s IP address to Google. In January 2022 a Munich court (LG München, 3 O 17493/20) awarded a visitor €100 for exactly that, and mass claim letters followed. A banner is the wrong fix: host the fonts yourself.
    Check it yourself
    In DevTools → Network, reload the page and type fonts.g into the filter: nothing from fonts.googleapis.com or fonts.gstatic.com should appear. More generally, every request should go to your own domain or to a service the visitor has agreed to.
    For your developer
    Next.js next/font downloads the font at build time and serves it from your own domain, which is fine. Bundle libraries rather than adding CDN script tags.
    Source
  4. No recording of what visitors typePriority: Must. Who can check: From outside, Needs the code
    Why
    Session-replay and heatmap tools (Hotjar, Microsoft Clarity, FullStory, LogRocket, PostHog recordings, Sentry Replay) and some chat widgets capture what people type, often into forms. In the EU that is processing without a legal basis, often of sensitive data; in California, courts have let such cases go ahead as wiretapping claims.
    Check it yourself
    In DevTools → Network, look for requests to those vendors on every kind of page. Ask your developer to check the defaults of every analytics tool on the site – some record sessions unless told not to.
    For your developer
    If one is ever truly needed: consent first, every input masked, never on forms, payments or accounts, and named in the notice.
  5. ChildrenPriority: Must. Who can check: Needs a person, From outside
    Why
    In Slovenia a child can consent to an online service alone from the age of 15; below that a parent or guardian gives or approves consent (ZVOP-2, art. 8), and Serbia also draws the line at 15. For school games and competitions it is better not to rely on minors’ consent at all where another basis fits, such as a public task, or to collect no email address. In the United States, a site directed at children under 13 falls under COPPA: verifiable parental consent before anything is collected.
    Check it yourself
    Read the consent text on the form: does it say who may send it (“I am at least 15, or I am a parent or guardian submitting this”)? Then fill in the form, send it, and open it again in the same browser as if you were someone else: nothing of the first person’s should be filled in.
    Sources
  6. No personal data in addressesPriority: Should. Who can check: From outside
    Why
    An address with a name or an email in it ends up in browser history, server logs and analytics. It usually happens when a form falls back to sending with GET, for example when JavaScript fails.
    Check it yourself
    Send a test entry through each form, with JavaScript on and off, and look at the address bar afterwards: no name, email or phone number should appear after a ?.
    See also
    The page can be read without JavaScript
  7. Visitors from SerbiaPriority: Should. Who can check: Needs a person
    Why
    Serbia’s data protection law (ZZPL) mirrors the GDPR’s notice requirements (art. 23) and applies to organisations outside Serbia that offer services to people there (art. 3(4)). Such an organisation must also appoint a representative in Serbia in writing (art. 44), unless its processing is occasional and low-risk. Complaints in Serbia go to the Poverenik.
    Check it yourself
    If the site has a Serbian version, or sends visitors from Serbia to one, decide consciously whether the exception for occasional processing applies, write the decision down, and name the Poverenik in the Serbian notice.
    Source
  8. Records and processor agreementsPriority: Must. Who can check: Needs a person, Needs your accounts
    Why
    The GDPR asks for a record of processing activities (art. 30) and an agreement with every service that processes personal data for you (art. 28): hosting, email, database, analytics, maps. When an agency runs the site, the client is usually the controller and the agency the processor, which needs an agreement of its own and a list of the services the agency uses.
    Check it yourself
    Write down every service that touches visitors’ data and, next to each, where its processing agreement is – most providers offer one in their dashboard or terms. If someone else maintains the site, check that you have an agreement with them too, and their list of sub-processors.
    Source

Back to contents

Email

A finished site’s email arrives, says who sent it, and replies reach a person.

  1. SPF, DKIM and DMARC on the sending domainPriority: Must. Who can check: From outside, Needs your accounts
    Why
    These three DNS records tell mail providers that a message from your domain really comes from you. Since February 2024 Gmail and Yahoo have required all three from senders of more than 5,000 messages a day, and smaller senders run into the same filters in practice. Without them, confirmations land in spam or never arrive.
    Check it yourself
    Send yourself a message through the site’s form to a Gmail address, open it and choose ⋮ → “Show original”: SPF, DKIM and DMARC should all say PASS. Ask whoever manages your DNS for the DMARC record: it should contain rua=, so that the reports reach someone.
    For your developer
    One v=spf1 record with at most 10 DNS lookups, naming every sender (the mailbox host and the transactional provider); -all only once you are sure it is complete. DKIM for each sender (Resend, for example, uses resend._domainkey and a send. return-path subdomain). DMARC starts at p=none with rua= reporting; read the reports, then move to quarantine and reject.
    Sources
  2. Every email says who sent itPriority: Must. Who can check: Needs a person, From outside
    Why
    A message from a finished site carries the organisation’s name and postal address, a reply address that works, why the person is receiving it, and a link to the privacy notice. In the United States, CAN-SPAM also requires an opt-out and a valid postal address in every commercial email.
    Check it yourself
    Read your own confirmation email as a stranger would: who is this from, why did I get it, where can I reply, and where is the privacy notice?
  3. A confirmation in the visitor’s languagePriority: Should. Who can check: From outside
    Why
    Whoever sends a form gets an email in their language that says what was received, what happens next and whom to contact. It comes from your own domain, not a Gmail address, is sent once even if the button is pressed twice, and carries no advertising.
    Check it yourself
    Send the form yourself in each language the site has. Check the language, the sender’s address, and that pressing the button twice does not bring two emails.
  4. Replies reach a personPriority: Should. Who can check: From outside, Needs a person
    Why
    A confirmation from noreply@ with nowhere to reply turns every question into a lost email. In a finished setup, replies to a confirmation land in an inbox someone reads, and the organiser’s notification has the visitor as its Reply-To, so that “Reply” answers them directly.
    Check it yourself
    Reply to your own confirmation: did it reach someone? Press “Reply” on the notification the organiser receives: is it addressed to the person who filled in the form?
  5. Newsletters and announcementsPriority: Must. Who can check: From outside, Needs the code
    Why
    Marketing email goes only to people who agreed to that particular thing – consent given with an event registration is not consent to a newsletter. Every message has an unsubscribe link that works in one click without logging in, and the postal address; bulk senders also send the List-Unsubscribe and List-Unsubscribe-Post headers that Gmail and Yahoo have required since 2024.
    Check it yourself
    Sign up with a test address: you should get an email with a link to confirm before you are added (double opt-in). Open a newsletter and click “unsubscribe”: it should work at once, without a password.
    Source
    See also
    Consent you can prove
  6. Sending limits and bouncesPriority: Should. Who can check: Needs your accounts
    Why
    Free email plans have daily caps (100 messages a day on Resend’s free plan, for example), and a rush of sign-ups after a social media post can go over them. Bounces and spam complaints should reach someone who can act on them.
    Check it yourself
    In your email provider’s dashboard, find the plan’s daily limit and compare it with your busiest day – usually the day registration opens. Check where bounce and complaint notices go.

Back to contents

Selling online

When the site takes money – tickets, memberships, subscriptions. The items follow the buyer: before the button, the button, after the purchase, and later.

  1. Renewal terms beside the pay buttonPriority: Must. Who can check: From outside
    Why
    Right before the button, in the same view, the buyer sees the price, how often it renews, that it renews automatically until cancelled, and how to cancel. The EU Consumer Rights Directive (art. 8(2); in Slovenia ZVPot-1) asks for the key terms at exactly this point; under California’s Automatic Renewal Law, without them whatever was delivered counts as a gift and the renewals can be claimed back.
    Check it yourself
    Go through your own checkout and stop before paying. Next to the button, can you read the price, how often you will be charged, that it renews automatically until you cancel, and how to cancel?
    For your developer
    Stripe Checkout’s own summary does not say that the subscription renews automatically until cancelled; custom_text.submit.message sits directly above the button.
  2. The button says it costs moneyPriority: Must. Who can check: From outside
    Why
    The last button makes clear that clicking it places an order you have to pay for: “Pay”, “Subscribe” (in Slovene, “Naroči s plačilom”) – not “Continue” or “Next”. The EU Consumer Rights Directive (art. 8(2)) requires it.
    Check it yourself
    Read the last button before payment out loud. If it could also mean “go to the next step”, it needs different words.
  3. A confirmation the buyer keepsPriority: Must. Who can check: From outside
    Why
    After the purchase, the buyer receives an email they can keep, with the renewal terms and how to cancel, and the thank-you page repeats them. California’s Automatic Renewal Law requires this acknowledgment.
    Check it yourself
    Make a test purchase (in test mode, if your payment provider has one) and read the email and the thank-you page: are the renewal terms and the way to cancel on both?
  4. Cancelling online, as easily as signing upPriority: Must. Who can check: From outside, Needs your accounts
    Why
    A subscription can be cancelled online in about as many steps as it took to start – through Stripe’s customer portal, for example – and yearly subscribers get a reminder before it renews.
    Check it yourself
    Play a customer who wants out: starting from the purchase email alone, can you cancel without writing to anyone? Count the steps and compare them with signing up.
  5. Terms, 14 days to withdraw, and the withdrawal buttonPriority: Must. Who can check: From outside, Needs a person
    Why
    Terms of service and a withdrawal and refund policy are published and linked before live payments begin. Consumers in the EU have 14 days to withdraw from a contract made online, and since 19 June 2026 every online contract with consumers needs a clearly labelled withdrawal function – a “withdraw from contract here” button (Directive (EU) 2023/2673, Consumer Rights Directive art. 11a).
    Check it yourself
    From the checkout page, can you reach the terms and the withdrawal policy in one click? Is there a clearly labelled way to withdraw from a contract online that a buyer can find without asking anyone?
    See also
    Terms and conditions, when you need them
  6. Prices with VAT and deliveryPriority: Must. Who can check: From outside
    Why
    Slovenia’s ZEPT (art. 5) asks for prices that make clear whether VAT and delivery costs are included, and Serbia’s law on electronic commerce asks for clear prices too.
    Check it yourself
    Look at every price on the site: is it clear whether VAT is included, and are delivery or booking fees shown before the last step?
    Sources
  7. Slovene for consumers in SloveniaPriority: Must. Who can check: From outside
    Why
    A business dealing with consumers in Slovenia must do so in Slovene; other languages can be offered alongside it (the Public Use of Slovene Act, as amended in 2024).
    Check it yourself
    Go through the whole purchase in Slovene: product pages, checkout, terms, the confirmation email and the thank-you page. None of it should fall back to English.
    Source

Back to contents

Being found and shared

How search engines, chat apps and people with a poster in their hand find the site.

  1. A title and description on every pagePriority: Should. Who can check: From outside
    Why
    Search results show a page’s title and description, and so do many shared links. A finished site gives each page its own title (about 50–60 characters) and a description written for people (about 150), in that page’s language. Identical titles make every result look the same, and a Slovene description on the English page is shown to English searchers.
    Check it yourself
    Look at the browser tab of a few pages: each title should be different and say what the page is. In the page source (Ctrl+U), search for <title> and description on an inner page and on each language version.
  2. A share image on every pagePriority: Should. Who can check: From outside
    Why
    WhatsApp, Viber, Instagram messages, Facebook, LinkedIn, Slack and Telegram all read a page’s Open Graph tags, and without an og:image a shared link is a grey box. A finished site has an image of 1200 × 630 pixels for each page, or a good default, with a title and description to go with it.
    Check it yourself
    Paste a link to one of your pages into a chat with yourself: you should see an image, a title and a line of description. Do the same for an inner page and for each language: the preview should fit the page.
    For your developer
    Set og:title, og:description, og:url, og:type, og:site_name, og:locale with og:locale:alternate, og:image as an absolute URL (1200×630, under 5 MB) with og:image:alt, and twitter:card=summary_large_image. In Next.js a nested metadata.openGraph replaces the parent’s object rather than merging with it: a layout that sets only openGraph: { locale } silently removes the image.
  3. Favicon, touch icon and web manifestPriority: Should. Who can check: From outside
    Why
    Browsers, phones and chat apps look for icons in fixed places and show a blank square when they find none. A finished set has favicon.ico at /favicon.ico, an SVG icon, a 180 × 180 apple-touch-icon (also at /apple-touch-icon.png), and a web manifest with 192 and 512 pixel icons, a name, a short name and colours.
    Check it yourself
    Open /favicon.ico and /apple-touch-icon.png on your site, and the manifest (search the page source for manifest): each should load. Add the site to your phone’s home screen and look at the icon.
  4. A sitemap with every page in every languagePriority: Should. Who can check: From outside
    Why
    The sitemap tells search engines which pages exist. A finished one lists every page you want found, in every language, on the site’s one real address, with real last-modified dates; on a multilingual site each entry also names its other language versions. Google uses lastmod only when it is consistently accurate, and ignores priority and changefreq altogether.
    Check it yourself
    Open /sitemap.xml. Pick a few addresses from it and open them: each should load directly, without a redirect. Pages in your menu that are missing from it are worth asking about. Compare a lastmod date with the last time that page really changed.
    Sources
    See also
    Dates that are true, facts that are current
  5. A robots.txt that says what you meanPriority: Should. Who can check: From outside, Needs your accounts
    Why
    robots.txt names the sitemap and does not block CSS, JavaScript or pages you want found; pages you want kept out of search results need a noindex tag instead, because a page blocked in robots.txt is never crawled and its noindex never seen. If the site sits behind Cloudflare, its managed robots.txt is added on the way and silently replaces the file in your code.
    Check it yourself
    Open /robots.txt on the live site and read it. If your developer has the file in the code, compare the two; if they differ, check Cloudflare’s managed robots.txt setting. Which AI crawlers it lets in is a decision of its own.
    Sources
    See also
    AI crawlers: answering and training are separate choices
  6. One canonical address per pagePriority: Should. Who can check: From outside
    Why
    Each page names its own full address as the canonical one, on the host that actually serves it. A canonical that points every page at the home page tells Google they are all copies of the home page, and one that points at an address which redirects sends a mixed signal.
    Check it yourself
    Open a few pages, view the source and search for canonical. The address should be that page’s own, and opening it should load the page directly, without a redirect.
    For your developer
    A full https:// address, one per page, in the HTML the server sends. Google advises against changing it with JavaScript afterwards, and many other crawlers never run the script at all.
    Sources
  7. Language versions that point at each otherPriority: Should. Who can check: From outside
    Why
    On a multilingual site each page lists all of its language versions – itself included – plus an x-default, and every version lists the others back. Serbian in Latin script is sr-Latn: much software takes a bare sr to mean Cyrillic.
    Check it yourself
    In the page source, search for hreflang. You should find one line per language and one for x-default, pointing at the language versions of this page, not of the home page. Open one of them: its source should list the same set.
    For your developer
    Use one channel – HTML <link>, the HTTP Link header or the sitemap – or make sure every channel says the same thing, on the same host.
    Source
  8. Each language has its own addressPriority: Should. Who can check: From outside
    Why
    A language switch that only changes something in the browser is invisible to search engines, cannot be shared, and cannot be linked from a newsletter in that language. A finished site gives each language its own address, such as /en/… and /sr/….
    Check it yourself
    Switch the language, copy the address and open it in a private window: it should open in the language you chose.
  9. The page says which language it is inPriority: Must. Who can check: From outside
    Why
    <html lang> tells screen readers how to pronounce the text and browsers whether to offer a translation, and search engines read it too. It is right for each language version and set on the server, not changed afterwards by JavaScript; a passage in another language gets its own lang.
    Check it yourself
    View the page source (not the inspector, which shows the page after scripts have run) and look at the <html line: lang="sl" on Slovene pages, lang="en" on English ones, lang="sr-Latn" on Serbian pages in Latin script.
    Source
  10. Structured data for events and organisationsPriority: Should. Who can check: From outside
    Why
    JSON-LD tells search engines what a page is about in a form they can read without guessing: Organization with its logo, Event with the start time and time zone, place, tickets and status, LocalBusiness with opening hours and address, BreadcrumbList. It is what richer search results for events and local businesses are built from. It describes only what the page itself shows: Google’s rules forbid marking up anything readers cannot see, and a date or price that differs from the visible one is a fault, not a detail. Google also says plainly that its AI features need no special markup.
    Check it yourself
    In the page source, search for application/ld+json. For an event, check that the date, time and place are right, and that the status changes if the event is postponed or cancelled. Paste the address into Google’s Rich Results Test or the Schema Markup Validator (validator.schema.org): it should read without errors, and every fact in it should also be on the page.
    Sources
    See also
    Pages that change with time, Who wrote it, and who stands behind it, Dates that are true, facts that are current
  11. Short addresses and old links redirectPriority: Should. Who can check: From outside
    Why
    People type what they saw on a poster or in a story – /prijava, /registracija, /kontakt, /en/contact – and links to the previous site live on in bookmarks and on other sites. Each of them arrives somewhere: through a permanent redirect (301 or 308) where you are sure, and a temporary one (302 or 307) for aliases whose target may change.
    Check it yourself
    Type the words you have used on posters and in posts after your domain, and try a few addresses from your old site (the Wayback Machine at web.archive.org lists them). None should end on a 404.
  12. One address for the whole sitePriority: Should. Who can check: From outside
    Why
    http:// and https://, with and without www, with and without a trailing slash: every variant reaches the one real address in a single permanent redirect. The canonical tags, the sitemap and the language links all use that same address, and a temporary redirect tells search engines it may change back.
    Check it yourself
    Type your domain four ways – http://example.si, http://www.example.si, https://example.si, https://www.example.si – and see that all four end on the same address. DevTools → Network with “Preserve log” ticked shows how many hops it took, and whether they were 301 or 308.
  13. Search Console, and no stray noindexPriority: Nice to have. Who can check: Needs your accounts, From outside
    Why
    Google Search Console and Bing Webmaster Tools show which pages are indexed and which of your canonical choices were rejected; Search Console’s Generative AI performance report also shows how pages do in Google’s AI features. Preview deployments should carry noindex (Vercel adds it); the live site must not.
    Check it yourself
    Verify the site in Search Console and read the page indexing report. On the live site, search the page source for noindex, and check the page’s response headers in DevTools → Network for X-Robots-Tag: neither should be there on pages you want found.
    Source

Back to contents

Found and quoted by AI assistants

ChatGPT, Claude, Perplexity, Gemini and Google’s AI Overviews answer questions by reading pages and citing some of them. There is no trick to being chosen: Google says its AI features need nothing beyond ordinary good search practice, and the others read the same public pages. What helps is text a machine can read, facts that are true and dated, a clear name behind them – and a deliberate choice about which AI crawlers may read the site at all.

See also: A title and description on every page, One canonical address per page, A sitemap with every page in every language, Structured data for events and organisations, A robots.txt that says what you mean, Search Console, and no stray noindex

  1. Answers in the HTML, under clear headingsPriority: Should. Who can check: From outside, Needs the code
    Why
    Most AI crawlers read only the HTML the server sends. When Vercel watched the crawlers of OpenAI, Anthropic, Meta, ByteDance and Perplexity in December 2024, none of them ran JavaScript, so text that appears only after a script runs, or sits inside an image or a PDF, was invisible to them; Google’s crawler does run scripts, and Google still recommends rendering on the server. What makes a page easy to quote correctly also helps a hurried reader: one main heading, headings that name the topic or the question, the direct answer in the first sentence or two beneath them, and facts – dates, prices, places, opening hours – written as text rather than shown in a picture.
    Check it yourself
    View the page source (Ctrl+U, or ⌘⌥U on a Mac) and search it (Ctrl+F) for the sentences that matter most: the date of the next event, a price, the opening hours, what the organisation does. If they are not in the source, a crawler that does not run scripts never sees them. Then read the page as a stranger with one question – “when is it?”, “how much?” – and see whether a single sentence answers it.
    For your developer
    Render content on the server (in Next.js, server components and static or server rendering are the default; keep "use client" for the interactive parts). One <h1>, headings in order, <main> around the content; tabs and accordions as <details>, or with all their text in the HTML; text, not pictures of text; key documents as HTML pages, not only PDFs.
    Sources
    See also
    The page can be read without JavaScript, A title and description on every page
  2. AI crawlers: answering and training are separate choicesPriority: Should. Who can check: From outside, Needs your accounts
    Why
    AI companies send different crawlers for different jobs, and robots.txt can treat each one separately. Some collect pages to train models: OpenAI’s GPTBot, Anthropic’s ClaudeBot, and Common Crawl’s CCBot, whose public archive is widely used for training. Google and Apple use the names Google-Extended and Applebot-Extended, which crawl nothing themselves: they decide whether the pages their search crawlers fetch may train Gemini and ground its answers, or train Apple’s models, and neither changes how the site appears in their search. Others fetch pages to answer with them and cite them: OAI-SearchBot for ChatGPT’s search, Claude-SearchBot and PerplexityBot. A third kind – ChatGPT-User, Claude-User, Perplexity-User – opens a page when a person asks about it: Anthropic says Claude-User can be blocked in robots.txt, OpenAI says robots.txt rules may not apply to ChatGPT-User, and Perplexity says Perplexity-User generally ignores them. So blocking everything with “AI” in its name also hides the site from AI answers, and blocking nothing lets it be used for training. In the EU you may reserve your content from text and data mining in a machine-readable way (Directive (EU) 2019/790, art. 4(3)); a robots.txt rule is the usual way, and Cloudflare’s Content-Signal line says the same in words.
    Check it yourself
    Open /robots.txt and look for the names above. For each kind, the site should have made a choice – allowed, to be found and quoted, or blocked, to stay out of training – rather than kept whatever a template or a plugin wrote. If the site is behind Cloudflare, ask whoever manages it how its AI crawler settings are set (AI Crawl Control, “Block AI bots”, the managed robots.txt): they can block crawlers or rewrite robots.txt without the code saying so. Since July 2025 Cloudflare has asked every new domain at sign-up whether to allow AI crawlers.
    For your developer
    A crawler obeys only the group that names it, and falls back to User-agent: * only when none does (RFC 9309), so a named group must repeat any rules for private paths. One way to allow answering and refuse training: a group listing GPTBot, ClaudeBot, CCBot, Google-Extended and Applebot-Extended with Disallow: /, then User-agent: * with the site’s usual rules and the Sitemap: line. OpenAI says its search picks up a change in about a day.
    Sources
    See also
    A robots.txt that says what you mean
  3. llms.txt: optional, and no substitute for the pagePriority: Nice to have. Who can check: From outside, Needs the code
    Why
    /llms.txt is a Markdown file that sums a site up for AI tools and links to its most useful pages, proposed by Jeremy Howard in September 2024. It is an emerging convention, not a standard, and support is uneven: Google says its Search, AI features included, needs no such file, while Chrome’s Lighthouse has looked for one since 2026 and marks a missing file as not applicable rather than as a fault. It is meant for AI tools that read a site at the moment someone asks about it, and so far it is most common on developer documentation. If you have one, it must be true and current – a stale summary is worse than none – and it changes nothing about what crawlers may read: that is robots.txt’s job.
    Check it yourself
    Open /llms.txt on your site. If it is there, read it: a heading with the site’s name, a one-paragraph summary, and lists of links that work and point at the current pages. If it is not there, nothing is broken.
    For your developer
    Generate it from the same source as the sitemap, so it cannot drift from the site. Plain Markdown, served as text/plain or text/markdown; the proposal also suggests Markdown copies of pages at the same address with .md added.
    Sources
    See also
    A sitemap with every page in every language, Answers in the HTML, under clear headings
  4. Who wrote it, and who stands behind itPriority: Should. Who can check: From outside, Needs a person
    Why
    Search engines and AI assistants try to cite sources a reader can trust, and so do people. Google’s guidance asks whether it is self-evident who created the content: a byline where readers would expect one – on articles, guides, research – leading to more about the author, and an About page with the organisation’s full name, its address and a way to reach it. Organization structured data on the home or About page says the same for machines: name, url, logo, sameAs links to the official profiles, and for a company legalName and vatID. Made-up names, stock-photo “experts” and invented credentials count against a site.
    Check it yourself
    Open an article or a guide and ask: who wrote this, and where would I find out more about them? From the home page, find in one click who runs the site and how to reach them. In the home page source, search for "Organization": the name, address and profiles there should match the About page.
    Sources
    See also
    Provider details (imprint), Real contact details, not only a form, Structured data for events and organisations
  5. Dates that are true, facts that are currentPriority: Should. Who can check: Needs a person, From outside
    Why
    An assistant that quotes last year’s price, or a past event as upcoming, quotes your site wrongly – under your name. Pages whose facts change – prices, opening hours, programmes, the team, contacts – show when they were last updated, and the date is true: Google asks for a visible “Published” or “Last updated” date that matches datePublished and dateModified in the structured data, and uses a sitemap’s lastmod only when it is consistently accurate. Moving a date forward without changing the content earns nothing.
    Check it yourself
    Write down the five facts people ask about most – price, date, place, opening hours, contact – and check each one on the live site today. On articles and guides, find the date and compare it with dateModified in the page source and with lastmod in /sitemap.xml.
    For your developer
    Take lastmod and dateModified from the content’s real modification time (the CMS entry or the Git commit), never from the build time.
    Sources
    See also
    Pages that change with time, A sitemap with every page in every language, Structured data for events and organisations

Back to contents

Accessibility

The target is WCAG 2.2, level AA. Automated scanners find roughly a third of the problems; the rest needs a keyboard and a screen reader, which is why most of these checks are done by hand.

See also: Tooltips on buttons that are only an icon, Works on a phone, from 320 pixels wide, The page says which language it is in

  1. Text you can readPriority: Should. Who can check: From outside
    Why
    Text needs a contrast of at least 4.5:1 against its background, and 3:1 for large text and for the edges of buttons and fields. Light grey on white is the usual failure, followed by text on photographs.
    Check it yourself
    Use a contrast checker; Chrome’s DevTools shows the ratio when you inspect a piece of text and click its colour. Start with the lightest text on the page: hints inside fields, captions, the footer, text over pictures.
    Source
  2. Everything works with a keyboard, and you can see where you arePriority: Should. Who can check: From outside, Needs a person
    Why
    Some people cannot use a mouse. Every link, button and field can be reached with Tab and used with Enter or Space, the focus outline is clearly visible and not hidden under a sticky header (WCAG 2.2, 2.4.11), and a “Skip to content” link lets people jump past the menu (2.4.1).
    Check it yourself
    Put the mouse aside and go through the page from the top with Tab. You should always see where you are, reach every menu, open and close every dialog, and send every form. The first Tab should reveal a “Skip to content” link.
    Sources
  3. Alt text on every image, and a clear structurePriority: Should. Who can check: From outside, Needs a person
    Why
    Images that carry information have alternative text that says what they show, and decorative ones have an empty alt="" so screen readers skip them. Screen reader users also move through a page by its headings and regions, so headings go in order and the page has header, nav, main and footer.
    Check it yourself
    In the page source, every <img should have an alt. Switch on your phone’s screen reader (VoiceOver on iPhone, TalkBack on Android) and listen to a page: images should be described or skipped, never read out as file names, and the headings should sound like a table of contents.
    Source
  4. Forms everyone can fill inPriority: Should. Who can check: From outside, Needs a person
    Why
    Every field has a visible label, errors are read out to screen readers as well as shown, people are not asked for the same information twice (WCAG 2.2, 3.3.7), and signing in never depends on a puzzle CAPTCHA or on blocking paste into the password field (3.3.8). Help – a contact link, a phone number – sits in the same place on every page (3.2.6).
    Check it yourself
    Click each field’s label: the cursor should jump into the field. Paste a password from a password manager. With a screen reader on, send a form with a mistake and listen: the error should be read out.
    Source
    See also
    Forms that tell the truth
  5. Targets big enough to tapPriority: Should. Who can check: From outside, Needs a person
    Why
    Buttons and links are at least 24 × 24 pixels, or spaced so that a finger does not hit the neighbour (WCAG 2.2, 2.5.8), and anything done by dragging – a slider, a map, reordering – also works with a single tap or click (2.5.7). On phones, 44 × 44, WCAG’s stricter level (2.5.5), is the safer aim for the controls people use most.
    Check it yourself
    On your phone, try every small control: close buttons, arrows in galleries, links in the footer, the language switch. If you hit the wrong one, it is too small or too close.
    Source
  6. Less motion for those who ask for itPriority: Should. Who can check: From outside
    Why
    Large animations, parallax and moving backgrounds can make some people dizzy or sick. Phones and computers have a “reduce motion” setting, and a finished site respects it.
    Check it yourself
    Switch on Reduce motion (iPhone: Settings → Accessibility → Motion; Mac: System Settings → Accessibility → Display; Windows: Settings → Accessibility → Visual effects, Animation effects off) and reload the site: large animations should stop or become simple fades.
    Source
  7. Does the European Accessibility Act apply to you?Priority: Must. Who can check: Needs a person
    Why
    Since 28 June 2025 the European Accessibility Act has covered services offered to consumers, among them any online sale of goods or services (tickets too), consumer banking, e-books and passenger transport. Microenterprises providing services – fewer than 10 people and no more than €2 million in annual turnover or balance sheet – are exempt, and so are business-to-business services; in Slovenia the Act is transposed as ZDPSI. An NGO or event site that sells nothing is not a service under the Act; a shop with twelve staff is.
    Check it yourself
    Answer two questions: do we sell anything to consumers online, and are we a microenterprise? If you sell to consumers and are not a microenterprise, accessibility is a legal requirement for the shop, not only good practice. Selling from Serbia to consumers in the EU counts too.
    Sources
  8. Public bodies: an accessibility statementPriority: Must. Who can check: From outside, Needs a person
    Why
    In Slovenia, state bodies, municipalities and bodies governed by public law – public institutes included – fall under ZDSMA. Their sites must meet EN 301 549 (WCAG 2.1 AA), publish an accessibility statement (izjava o dostopnosti) and offer a way to report problems.
    Check it yourself
    If your organisation is a public body or public institute, look for an accessibility statement link, usually in the footer, and check that it says how to report a problem, and that someone answers.
    Sources

Back to contents

Every screen: phone, tablet, laptop, foldable

Visitors arrive on screens from about 320 to more than 2,500 pixels wide, hold them upright or sideways, and some phones fold in the middle while the page is open. A finished layout is not three fixed designs for three devices but one that adapts to the space it has – and has been tried at the widths in between.

See also: Targets big enough to tap, A sticky button for the main action on phones, A clear call to action without scrolling

  1. Works on a phone, from 320 pixels widePriority: Should. Who can check: From outside
    Why
    Most phones show pages 360 to 440 pixels wide, and some are narrower: the outer screen of Samsung’s Galaxy Z Fold 5 is 344. A finished layout fits all of them, with nothing sticking out and no sideways scrolling, down to 320 pixels – which is also what a 1,280-pixel window shows at 400 % zoom, the width at which WCAG 2.2 asks content to reflow into one column (1.4.10). The page tells phones to use their real width (the viewport tag), and never stops people from zooming in. Buttons stay big enough to tap.
    Check it yourself
    Open every kind of page on your phone – home, a list, an article, a form – and scroll from top to bottom: if the page moves sideways, something is too wide. On a computer, DevTools’ device toolbar (Ctrl+Shift+M) set to 320 px does the same; then zoom a normal window to 400 % (Ctrl or ⌘ and +) and read a page. On the phone, spread two fingers to zoom: it should work on every page.
    For your developer
    <meta name="viewport" content="width=device-width, initial-scale=1">, without user-scalable=no or maximum-scale=1. The usual culprits for sideways scrolling: fixed widths, long words and URLs without overflow-wrap, tables and code blocks without their own scroll container, and 100vw next to a scrollbar.
    Sources
    See also
    Targets big enough to tap, Foldable phones: closed, open and half-open, Tried at real widths, on real devices
  2. Tablets and the widths in betweenPriority: Should. Who can check: From outside, Needs a person
    Why
    Between a phone and a laptop – roughly 600 to 1,100 pixels – is where layouts break most often: a phone layout stretched into lines of 150 characters, or a desktop layout squeezed until the menu wraps under the logo. An iPad usually asks for the desktop site (Safari on iPadOS presents itself as a Mac), so a site that picks its layout by the kind of device instead of by the space available sends iPads menus that open only when a mouse hovers over them, which a finger cannot do. A finished layout changes where its content needs it to, not at the widths of three particular devices, and everything that works with a mouse also works with a tap.
    Check it yourself
    On a computer, open DevTools’ device toolbar, choose “Responsive” and drag the width slowly from 600 to 1,300 pixels on the home page and on a long page: watch for a menu that wraps, parts that overlap, text that is cut off and very long lines. On a real tablet, try the menu and every dropdown with a finger, upright and sideways.
    For your developer
    Choose the layout by width (@media (min-width: …)), never by user agent. Container queries (@container, in every major browser since February 2023) let a card adapt to the column it sits in rather than to the whole screen. Put hover effects inside @media (hover: hover), and never hide a menu or information behind hover alone.
    Sources
    See also
    Tooltips on buttons that are only an icon, Laptops and big monitors, Targets big enough to tap
  3. Laptops and big monitorsPriority: Should. Who can check: From outside
    Why
    A laptop is often shorter than people think: a 1920 × 1080 screen at Windows’ usual 125 or 150 % scaling gives the browser 1,536 or 1,280 pixels of width and, after the taskbar and the browser’s own bars, often less than 700 of height – so a full-screen picture at the top pushes everything else out of view, and a tall sticky header takes a fifth of the screen. On a big monitor the opposite happens: text that runs across the whole width is tiring to read. A finished layout keeps lines of text to about 80 characters (WCAG’s advice at its highest level, 1.4.8), lets pictures and backgrounds grow but not the text column, and serves images sharp enough for high-density screens.
    Check it yourself
    Make the browser window 1,280 × 720 (DevTools’ device toolbar can set it exactly) and look at the home page and your main page: is the main action visible without scrolling? Then open the site full-screen on the biggest monitor you can find: are lines of text still comfortable to read, and are the images sharp?
    For your developer
    max-width on text columns (about 70ch), layouts that spend extra width on columns or margins rather than longer lines, srcset with 2× images, and heights in svh rather than fixed pixels for anything meant to fit on the first screen.
    Source
    See also
    A clear call to action without scrolling, Images, video and icons in light formats, Tablets and the widths in between
  4. Upright and sidewaysPriority: Should. Who can check: From outside
    Why
    Some people hold their phone or tablet sideways and cannot easily turn it – it is mounted on a wheelchair or a stand – so WCAG 2.2 asks that a page work in both orientations unless one is essential (1.3.4). Sideways, a phone has barely 300 to 400 pixels of height, and a fixed header, a cookie banner and a sticky button can leave almost nothing for the content, or for a form field once the keyboard is open. Turning the device keeps the visitor’s place and everything already typed.
    Check it yourself
    Turn your phone sideways on the home page, a long article and a form. With the cookie banner showing, can you still read and close it? Tap into a form field so the keyboard opens: can you see what you are typing? Type something, then turn the phone back and forth: it should still be there.
    For your developer
    No orientation lock and no “please rotate your device” screens. Shrink or release sticky elements in short viewports (@media (max-height: 500px)), and use dvh or svh rather than 100vh.
    Source
    See also
    A sticky button for the main action on phones, A consent banner – only when something non-essential runs, Notches, rounded corners and the browser’s bars
  5. Foldable phones: closed, open and half-openPriority: Nice to have. Who can check: From outside, Needs a person
    Why
    A foldable changes size while the page is open. Closed, its outer screen is a narrow phone (344 pixels wide on the Galaxy Z Fold 5); open, the inner screen is almost square, close to a small tablet (about 690 × 830). Opening or closing it resizes the page without reloading it, so a finished site keeps the visitor’s place, an open menu or dialog, and whatever was typed into a form. Half-open – held like a book, or standing like a small laptop – some devices tell the browser that the screen has two segments with a fold between them. The CSS media features horizontal-viewport-segments and vertical-viewport-segments, and window.viewport.segments in JavaScript (the Viewport Segments API), let a layout put a list on one side of the fold and the detail on the other instead of across it. They work in Chrome and Edge from version 138 and in Samsung Internet 30, and not in Safari or Firefox, so they are an addition, never a requirement: fully open, a foldable is simply one screen.
    Check it yourself
    On a foldable, open a form, type a few words, then open and close the phone: the words, your place on the page and any open menu should survive. Without one: DevTools’ device toolbar has foldable presets (Galaxy Z Fold 5, Asus Zenbook Fold, Surface Duo) with a button that switches between closed and open, or between one screen and two.
    For your developer
    React to resize (or a ResizeObserver), never to orientationchange alone, and do not reset state or fetch data again on resize. For two panes: @media (horizontal-viewport-segments: 2) with widths from env(viewport-segment-width 0 0) and env(viewport-segment-width 1 0), and the same with vertical- when the fold runs across; where it is not supported, the ordinary layout stays.
    Sources
    See also
    Works on a phone, from 320 pixels wide, Tablets and the widths in between, Upright and sideways
  6. Notches, rounded corners and the browser’s barsPriority: Nice to have. Who can check: From outside, Needs the code
    Why
    Phones have camera cut-outs, rounded corners and a home bar along the bottom, and the browser’s own toolbars slide in and out as people scroll. A page that asks to fill the whole screen (viewport-fit=cover) has to keep text and buttons out of those areas itself; otherwise, sideways, text slides under the cut-out, and a button fixed to the bottom sits under the home bar. Full-height sections measured in 100vh are taller than the screen while the toolbars show, so their bottom – often the button – is cut off.
    Check it yourself
    On an iPhone with a notch or a Dynamic Island, turn the phone sideways and read along the edges of the page: no text should be under the cut-out. Look at everything fixed to the bottom – a cookie banner, a sticky button, a chat bubble – with the browser’s toolbar shown and hidden: nothing should sit under the home bar or be cut off.
    For your developer
    With viewport-fit=cover, pad fixed and edge-to-edge elements with env(safe-area-inset-*), for example padding-bottom: calc(1rem + env(safe-area-inset-bottom)). Use svh for what must fit on the first screen and dvh for full-height panels, not 100vh.
    Sources
    See also
    A sticky button for the main action on phones, Upright and sideways
  7. Tried at real widths, on real devicesPriority: Should. Who can check: Needs a person, From outside
    Why
    A layout designed at three widths breaks at the fourth. Emulators help, but in Google’s own words they are a first-order approximation: they do not show the real browser bars, the on-screen keyboard covering a field, larger text or a slow processor. A finished site has been checked by dragging through every width from 320 pixels to a wide monitor, and on a handful of real devices: a small Android phone, an iPhone, a tablet both ways up, a laptop and a big screen – and a foldable, if your visitors use them.
    Check it yourself
    Ask your developer which real devices the site was tried on before launch, and when it was last done. Try it yourself on the devices you have, with the browser’s text size or page zoom at 200 % (in Safari the aA button, in Chrome Settings → Accessibility): nothing should be cut off or overlap (WCAG 1.4.4).
    For your developer
    Use DevTools’ responsive mode by dragging rather than by picking presets, and remote debugging on real phones (Chrome for Android, Safari for iOS) for what only happens there. Screenshots at 320, 768, 1024, 1280 and 1920 pixels taken by the test suite catch a layout that breaks between rounds.
    Sources
    See also
    Works on a phone, from 320 pixels wide, Slow and old phones, In-app browsers: Instagram, Facebook, TikTok

Back to contents

Security

Most of these can be seen from outside in a few minutes; fixing them usually needs the code or the hosting account.

  1. HTTPS everywhere, and HSTSPriority: Must. Who can check: From outside
    Why
    Every page is served over HTTPS with a valid certificate, and every http:// address redirects to it. The Strict-Transport-Security header, set for a year or more, tells browsers never to try plain HTTP again.
    Check it yourself
    Type your address with http:// in front: you should land on https:// at once. In DevTools → Network, click the page and look among the response headers for strict-transport-security with max-age=31536000 or more.
    For your developer
    Add includeSubDomains; preload only after confirming that every subdomain – mail, webmail, old services – supports HTTPS.
    Source
  2. Security headersPriority: Should. Who can check: From outside, Needs the code
    Why
    A handful of response headers stop whole classes of attack: a Content Security Policy (with frame-ancestors, so no one can frame your site), X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and a Permissions-Policy that denies the camera, microphone and location unless the site uses them. X-Powered-By is removed.
    Check it yourself
    In DevTools → Network, click the page and read its response headers, or paste the address into a header-grading service. Look for the headers above on ordinary pages, and on the admin and API addresses too.
    For your developer
    Start with Content-Security-Policy-Report-Only, read the reports for a week, then enforce. In Next.js a nonce-based policy makes every page dynamic; on a static site use a hash- or allowlist-based one.
    Sources
  3. No secrets or private files in publicPriority: Must. Who can check: From outside, Needs the code
    Why
    Files such as /.env, /.git/config, source maps or /backup.zip sometimes end up served to anyone, and keys end up in the JavaScript every visitor downloads. Anything named NEXT_PUBLIC_ is public by definition: a Supabase anon key in the browser is expected, a service_role key there is a breach.
    Check it yourself
    Open /.env, /.git/config and /.git/HEAD on your site: each should be a 404. Ask your developer to run a secret scanner (gitleaks or trufflehog, for example) over the whole history of the repository, and to show you what the NEXT_PUBLIC_ variables contain.
    For your developer
    Scan the built bundles for sk_live_, Resend re_ keys, JWTs whose payload says "role":"service_role", AWS keys and private keys. On Vercel, marking a NEXT_PUBLIC_ variable Sensitive makes the build inline the literal text [SENSITIVE].
  4. Database access rulesPriority: Must. Who can check: Needs your accounts, Needs the code
    Why
    If the site uses Supabase or Firebase, the key in the browser is public, so tables holding personal data must not be readable with it: Row Level Security is on, and only narrow, deliberate functions are exposed.
    Check it yourself
    In the Supabase dashboard, open the security advisor and read what it reports. Your developer can also confirm it from outside with a request that uses the public key and only counts rows, so no personal data is fetched.
  5. Admin and CMS pagesPriority: Should. Who can check: From outside, Needs the code
    Why
    The sign-in and editing pages carry noindex (as a meta tag, not a robots.txt block), cannot be shown inside another site’s frame, and limit sign-in attempts. Third-party CMS scripts, which hold write access, are pinned with Subresource Integrity, and sign-in cookies are Secure and HttpOnly with an explicit SameSite.
    Check it yourself
    Search Google for your admin address (/admin, /wp-admin and so on): it should not show up. Sign in with a wrong password several times: you should be slowed down, not allowed to guess forever. Ask your developer whether the admin credentials are used anywhere public.
  6. Spam protection that does not punish peoplePriority: Should. Who can check: From outside, Needs the code
    Why
    Layered protection, cheapest first: a hidden honeypot field checked on the server, a time trap that rejects forms sent less than two seconds after the page loaded, server-side validation, and each submission accepted only once. Only then an invisible challenge such as Turnstile; puzzle CAPTCHAs shut out people with disabilities (WCAG 3.3.8).
    Check it yourself
    View the form’s source: is there a hidden field that people never see? Send the form the way a person would: it should go through without a puzzle.
    For your developer
    Check the honeypot on the server for every content type – JSON and form posts alike – or bots simply use the other one.
  7. Rate limits that do not lock out mobile usersPriority: Must. Who can check: Needs the code
    Why
    Mobile operators put thousands of phones behind one public IP address (carrier-grade NAT), so a limit like “one request per IP every 20 seconds” blocks the second person who taps your Instagram story. A finished site uses a generous ceiling per IP, limits per email address or account, and for password gates slows down repeated attempts on that target and alerts someone, rather than banning IP addresses.
    Check it yourself
    Ask your developer what happens when 30 people on the same mobile network send the form within a minute. The answer should not be “the IP gets blocked”.
    For your developer
    In-memory limits in serverless functions apply per instance, so treat them as a soft guard only, and add global circuit breakers.
    Sources
  8. Dependencies kept up to datePriority: Must. Who can check: Needs the code
    Why
    Security fixes arrive as new versions of the framework and its libraries, so a site a version or more behind is open to weaknesses that are already public. A finished project has automated update pull requests (Dependabot or Renovate), grouped monthly, and applies security fixes within days.
    Check it yourself
    Ask your developer to run pnpm audit --prod (or npm audit) and show you the result, and whether Dependabot or Renovate is switched on for the repository.
  9. security.txtPriority: Nice to have. Who can check: From outside
    Why
    /.well-known/security.txt tells someone who has found a vulnerability where to report it. It needs a Contact: line and an Expires: date less than a year away (RFC 9116).
    Check it yourself
    Open /.well-known/security.txt on your site. If it exists, check that the contact works and that the expiry date has not passed.
    Source
  10. Tidy DNSPriority: Nice to have. Who can check: Needs your accounts
    Why
    A CAA record names the certificate authorities allowed to issue certificates for your domain; no subdomain still points (by CNAME) at a deleted Vercel, Netlify or Heroku app that someone else could claim; and DNSSEC is on where the registrar supports it.
    Check it yourself
    Ask whoever manages your DNS for the list of records, and for each subdomain ask what it is for. One that points at a service you no longer use should go.

Back to contents

Speed

Speed is measured on real visitors’ phones, not on the developer’s laptop.

See also: Caching, so it feels instant, Skeletons while content loads

  1. Core Web Vitals in the greenPriority: Should. Who can check: From outside, Needs your accounts
    Why
    Google’s three measures of how a page feels: the main content appears quickly (LCP at most 2.5 s), the page responds to taps quickly (INP at most 200 ms), and it does not jump around (CLS at most 0.1) – measured for three in four real visitors (the 75th percentile).
    Check it yourself
    Paste your address into PageSpeed Insights (pagespeed.web.dev) and read the mobile result. Small sites often have no real-visitor data there; then use the lab result, or Vercel Speed Insights if it is switched on.
    Sources
  2. Images, video and icons in light formatsPriority: Should. Who can check: From outside
    Why
    Photos are served at the size they are shown, as AVIF or WebP, with their width and height set so the page does not jump; images below the first screen load later and the main image loads first. Video is WebM with an MP4 fallback and a poster image, and a short looping clip replaces any animated GIF at a fraction of its size; icons and logos are SVG, sharp at every size and right in light and dark mode. On a content page nothing weighs more than about 300 KB – certainly not a 4000-pixel, 5 MB photo straight from a phone.
    Check it yourself
    In DevTools → Network, reload and sort by size. Under the Img filter, anything over 300 KB, or much larger than it appears on screen, is worth fixing, and so is any animated .gif; icons and logos should be .svg files, or not listed at all when they are drawn inside the page. Under the Media filter, videos should be .webm or .mp4, with a still picture showing before they play.
    For your developer
    width and height or aspect-ratio, a sizes attribute, loading=lazy below the fold, and the LCP image loaded eagerly with fetchpriority=high. Video: <video muted playsinline loop autoplay poster> with a WebM (VP9 or AV1) <source> first and an MP4 (H.264) fallback, and preload=metadata. Icons and logos as SVG, inline or as files, with fill=currentColor so they follow the theme; no PNG sprites, no icon fonts.
  3. Fonts that load fast and have every letterPriority: Should. Who can check: From outside, Needs the code
    Why
    Fonts are served from your own domain, cut down to the characters you need – with latin-ext for č, š, ž, ć and đ – with one or two preloaded at most, font-display: swap, and fallback metrics so the text does not jump when the font arrives.
    Check it yourself
    Type a name with č, š, ž, ć and đ into a field and look at headings containing those letters: every letter should be in the same font. In DevTools → Network, the Font filter should show a handful of files, all from your own domain.
    See also
    Fonts and scripts from your own server
  4. Few third-party scripts, loaded latePriority: Should. Who can check: From outside
    Why
    Every chat widget, embed and tracker adds weight and competes with your own content. A finished site knows how much JavaScript it loads on the first visit, keeps third-party scripts to the ones it needs, and loads the non-essential ones once the page is usable.
    Check it yourself
    In DevTools → Network, choose the JS filter and reload: read the total at the bottom, and see which domains the scripts come from.
  5. Hosting quotas that quietly degrade thingsPriority: Should. Who can check: Needs your accounts
    Why
    Free and small plans have limits that fail without a sound. Vercel’s Hobby plan, for example, includes 5,000 image transformations a month and pauses Web Analytics when its quota runs out; a gallery of a few hundred photos in several widths can use up the transformations.
    Check it yourself
    In your hosting dashboard, open the usage page and compare each quota with a busy month.
    Source

Back to contents

Keeping it running

What keeps a finished site finished after launch day.

  1. Uptime monitoring that checks the contentPriority: Must. Who can check: Needs your accounts, Needs a person
    Why
    An outside monitor checks the home page and one deeper page per language every 1–5 minutes, from more than one region, looks for a word that should be on the page rather than just a 200 status, and sends alerts to a phone. A health endpoint reports whether the database, email and required settings actually work, without revealing any of their values.
    Check it yourself
    Ask who gets the alert when the site goes down, and how. Then ask when it last happened and how long it took before anyone noticed.
    For your developer
    /api/health checks real dependencies, answers 503 when a required one is down, and echoes no values.
  2. Error logs you can still read next weekPriority: Should. Who can check: Needs your accounts, Needs the code
    Why
    Errors from the browser and the server go somewhere searchable, with alerts. Hosting logs are short-lived – Vercel keeps runtime logs for 1 hour on Hobby and 1 day on Pro – so a console.error is not an incident record. Logs hold no personal data they do not need: logging whole form entries puts personal data in a third party’s store.
    Check it yourself
    Ask your developer: “Show me the errors from last Tuesday.” If they are gone, errors are not being kept.
    For your developer
    A log drain (Vercel Pro), Sentry, or an email-on-error hook.
    Source
  3. Form entries kept somewhere durablePriority: Must. Who can check: Needs the code, Needs your accounts
    Why
    An inbox is not a database. Entries go into a store – a database, file storage, a spreadsheet through a webhook – together with their consent records, so nothing is lost when an email bounces or a mailbox is cleaned out.
    Check it yourself
    Ask where last month’s entries are, apart from email. You should be able to open them without searching an inbox.
    See also
    Consent you can prove
  4. Backups and content historyPriority: Should. Who can check: Needs your accounts
    Why
    For a site whose content lives in files, Git is the history. A database needs backups – check what the plan keeps and whether it can restore to a point in time – and form data is exported regularly.
    Check it yourself
    In the database provider’s dashboard, find the backup settings and read how far back you can restore. Ask when a restore was last tried.
  5. Domain and certificate expiryPriority: Must. Who can check: Needs your accounts
    Why
    A domain that lapses takes the site and its email down with it. A finished setup renews the domain automatically, on a card that will not expire first, registers it in the organisation’s own name, and alerts someone when a certificate has fewer than 14 days left.
    Check it yourself
    Sign in to your registrar and check auto-renewal, the card and the registrant’s name. For .si domains the public record (WHOIS) is at register.si, for .rs at RNIDS.
  6. Changes that actually go livePriority: Should. Who can check: Needs the code, Needs your accounts
    Why
    An automatic deploy can be skipped without a word – we have seen it happen. A finished site has a second way to trigger a deploy and reports which version it is running, so “is the fix live?” is not a guess.
    Check it yourself
    After the next change, check on the live site that it is there. Ask your developer where you can see which version the site is running.
    For your developer
    Report the commit SHA in /api/health.
  7. A hosting plan that allows what the site doesPriority: Should. Who can check: Needs your accounts
    Why
    Vercel’s Hobby plan is for non-commercial, personal use only, so company and client sites belong on a paid plan or on the client’s own account. Free tiers elsewhere have their own limits: daily email caps, databases that pause when idle, analytics event limits.
    Check it yourself
    Look up which plan the site is on, and whose account it is under.
    Source
  8. Who holds the keysPriority: Should. Who can check: Needs a person, Needs your accounts
    Why
    Someone knows who can get into the domain registrar, DNS, hosting, email provider and CMS, and the accounts belong to the organisation, not to a freelancer’s personal email. There is a way to remove someone’s access when they leave, and a short handbook for editors.
    Check it yourself
    Make a list: for each service, whose email is the account under, and who else can sign in? Anything registered to a person who might leave is worth moving.

Back to contents

Real-world failure modes

Things that do not show up while a site is built and demonstrated on a laptop, and do show up for real visitors.

  1. In-app browsers: Instagram, Facebook, TikTokPriority: Should. Who can check: From outside, Needs a person
    Why
    A link tapped inside Instagram, Facebook, Messenger or TikTok opens in the app’s own browser, not in Safari or Chrome. These browsers inject their own JavaScript, often cannot download files (so .ics calendar buttons do nothing), block Google sign-in, and do not share cookies with the phone’s browser.
    Check it yourself
    Put a link to your site in an Instagram story or message and open it there. Try the main form, any download, “Add to calendar”, and signing in if the site has it.
    For your developer
    Detect the in-app user agents (Instagram, FBAN/FBAV, FB_IAB, musical_ly/BytedanceWebview, Line/), show a small “Open in browser” hint next to downloads and sign-in, offer a Google Calendar link before .ics, and keep forms on the same page, without pop-ups.
    Sources
  2. Automatic translation does not break the pagePriority: Should. Who can check: From outside
    Why
    When Chrome or Google Translate translates a page, it wraps the text in elements of its own; a React site that later updates that text can crash with “Failed to execute ‘removeChild’ on ‘Node’”, leaving a blank page or form. It hits exactly the visitors who do not read the site’s language.
    Check it yourself
    Open the site in Chrome, right-click and choose “Translate to …”, then use it: open the menu, switch tabs, send a form. Nothing should go blank.
    For your developer
    Offer the language natively; put error boundaries around forms that remember a submission in progress; wrap conditionally rendered text in its own <span>; add translate="no" to brand names, codes and live counters.
    Sources
    See also
    Each language has its own address
  3. The page can be read without JavaScriptPriority: Should. Who can check: From outside
    Why
    JavaScript fails more often than it seems: in in-app browsers, on old phones, behind blockers, on a flaky network, or in a crash while the page starts up. Content that starts invisible and waits for a script to fade it in stays invisible, and a form that only sends through JavaScript does nothing.
    Check it yourself
    In Chrome DevTools, press Ctrl+Shift+P (⌘⇧P on a Mac), type “Disable JavaScript” and reload. The main text should be there and readable, and the form should still send.
    For your developer
    Scope reveal animations to html.js or @media (scripting: enabled). Give forms a real action and method that the server also accepts as application/x-www-form-urlencoded, answering with a page.
  4. Forced dark modePriority: Nice to have. Who can check: From outside
    Why
    Samsung Internet and Chrome’s automatic dark mode invert pages that do not say which colour schemes they support, sometimes leaving dark text on a dark background. A finished site declares color-scheme: light only, or real support for dark.
    Check it yourself
    Open the site in Samsung Internet with dark mode on, or in Chrome with the “Auto Dark Mode for Web Contents” flag. Everything should stay readable.
    For your developer
    <meta name="color-scheme" content="light">, or proper dark styles.
  5. Slovene, Serbian and their detailsPriority: Should. Who can check: From outside, Needs the code
    Why
    Slovene has four forms for counting, the dual among them (1 dan, 2 dneva, 3 dnevi, 5 dni), so “one or many” logic is wrong for three of them, and Serbian is written in both Latin and Cyrillic script (sr-Latn, sr-Cyrl). Names, addresses and email subjects keep their č, š, ž, ć and đ, phone fields accept +386, +381 and spaces, and times show the event’s time zone.
    Check it yourself
    Fill in a form as “Đurđa Šćepanović” with a phone number like +381 64 123 4567, and check that it is accepted, stored and shown correctly, including in the confirmation email. Look for counts on the site and check them for 1, 2, 3 and 5 (“2 dni” where it should say “2 dneva”?).
    For your developer
    Intl.PluralRules for every count; never n === 1 ? a : b.
  6. Ad blockers and privacy browsersPriority: Nice to have. Who can check: From outside
    Why
    Ad blockers stop addresses with words like analytics, track or ads in them, and third-party embeds such as Google Forms can show up as empty boxes. On a finished site nothing essential depends on a third-party frame.
    Check it yourself
    Install a common ad blocker (uBlock Origin, for example) or open the site in Brave, and go through the main tasks: reading, registering, paying, getting in touch.
  7. Slow and old phonesPriority: Nice to have. Who can check: From outside, Needs a person
    Why
    Not everyone has a new phone. Content pages that are drawn mostly in the browser feel slow on old devices, even on a good connection.
    Check it yourself
    Open the site on the oldest phone you can find, or in DevTools → Performance with the CPU slowed down 4 or 6 times, and scroll and tap through it.

Back to contents

Content from visitors

This applies when anyone other than the site’s own editors can upload or publish something others see: comments, profile pictures, galleries, listings. An editor uploading through the CMS into the site’s own repository is not this case.

  1. A way to report illegal contentPriority: Must. Who can check: From outside, Needs a person
    Why
    Terms of use are published, and there is an easy way – a form or a dedicated address – to report illegal or infringing content. Reports are acted on promptly and the person who reported gets an answer (EU Digital Services Act, art. 14 and 16).
    Check it yourself
    Pick any piece of visitor content and try to report it as a stranger would. Could you find how, and would anyone see the report?
    See also
    Terms and conditions, when you need them
  2. A single point of contactPriority: Must. Who can check: From outside
    Why
    The Digital Services Act asks for a published single point of contact, for the authorities and for users (art. 11 and 12).
    Check it yourself
    Is there one clearly named contact for such matters on the site, and does someone read it?
  3. A DMCA agent, if you are in the US or aim at itPriority: Must. Who can check: Needs a person
    Why
    If the company is in the United States or targets users there, it registers a designated DMCA agent with the US Copyright Office ($6, renewed every three years) and publishes it. Without one, there is no safe harbour for what users upload.
    Check it yourself
    Search the US Copyright Office’s directory of DMCA agents for your company’s name, and check that the registration has not lapsed.

Back to contents

Who runs this site

Who is behind the site, on what terms, and who – or what – is answering.

  1. Provider details (imprint)Priority: Must. Who can check: From outside, Needs a person
    Why
    Visitors, customers and authorities need to know whom they are dealing with. In Slovenia, ZEPT (art. 5) asks information society services, which are normally paid ones, for the name and seat, a working email, the registration and tax numbers, any supervisory authority, and prices with VAT; a free NGO site is arguably outside it, but the GDPR still requires the controller’s identity and contact, and companies also follow ZGD-1 on business documents. In Serbia the law on electronic commerce (art. 6) and the companies act (art. 25) ask for the same details, on electronic documents too.
    Check it yourself
    From any page, can you reach – in one click, usually from the footer – the organisation’s full legal name, its address, an email that works, and for a company the registration number (matična številka, matični broj) and tax number (SI and eight digits in Slovenia, a nine-digit PIB in Serbia)?
    Sources
    See also
    Real contact details, not only a form
  2. Terms and conditions, when you need themPriority: Must. Who can check: Needs a person, From outside
    Why
    Terms set out the rules of the deal between a site and its visitors. A finished site has them, published and linked before the point of commitment, when it sells something – together with the withdrawal and refund policy – and when visitors can open accounts or publish content others see, where the terms of use also say what is not allowed and how to report it.
    Check it yourself
    If the site sells or has accounts: can you reach the terms from the checkout or the sign-up form in one click, in the page’s language, and do they describe what the site actually does?
    See also
    Terms, 14 days to withdraw, and the withdrawal button, A way to report illegal content
  3. Say when visitors are talking to an AIPriority: Must. Who can check: From outside
    Why
    If the site has an AI chatbot or assistant, people are told that they are interacting with AI. This transparency duty in the EU AI Act (art. 50) applies from 2 August 2026.
    Check it yourself
    Open the chat as a visitor would: before you start, or as you do, does it say plainly that the answers come from an AI?
    Sources
  4. EU funding shown the way the programme asksPriority: Nice to have. Who can check: Needs a person
    Why
    Projects funded by the EU, through Interreg and other programmes, show the EU emblem and the funding statement according to their programme’s visibility rules.
    Check it yourself
    If the site or the project is EU-funded, compare its footer or project page with the programme’s visibility guide.

Back to contents