---
title: "Checklist From Code to Production: production readiness | WIP"
description: "The checklist WIP uses to tell whether software is ready for production: deployment, security, data, monitoring, costs, DNS and AI agents."
url: https://workinprogress.company/checklist
updated: 2026-10-27
lang: en
---

Open resource · version 2026.11

# Checklist From Code to Production

Software is ready for production when it passes the essential items of this checklist. There are 55 items across 7 pillars, the same ones WIP checks in a technical diagnosis. 24 of them can be verified from the outside, without access to the system.

Updated on October 27, 2026

 ![A magnifying glass examines a system with an application, a server and a database: almost everything is checked and one component is highlighted as the first to fix.](https://workinprogress.company/_astro/servico-check.CIbYcF16_Z16KH3a.png)

## How should you use this checklist?

Start with the items marked as essential: without them, the system works until its first serious incident. Then move on to the recommended ones and, if the business depends on the system all the time, to the advanced ones. Each item explains why it matters, how to check it and which standard or official documentation supports it.

If you would rather have someone check it for you, [WIP Check](https://workinprogress.company/services/technical-diagnosis) goes through every pillar and delivers a prioritized action plan.

## Deployment and environments

Releasing a new version is a repeatable, documented process with a way back.

1. ### Deploying to production is automated and repeatable
   
   Essential
   
   **Why it matters:** Manual deploys depend on the memory of whoever runs them and fail on the details. An automated process runs the same steps, in the same order, every time.
   
   **How to check:** Ask: if the person who usually deploys becomes unavailable, can someone else deploy using only what is in the repository? Look for the pipeline (for example, in .github/workflows) or a version-controlled deploy script.
   
2. ### There is a tested way to roll back to the previous version
   
   Essential
   
   **Why it matters:** Any change can go wrong. Being able to roll back quickly turns a long incident into a brief scare.
   
   **How to check:** Have someone perform a rollback in a test environment and time it. Check that database migrations can also be rolled back or are compatible with the previous version of the code.
   
3. ### Production is separate from development and testing, with its own data and credentials
   
   Essential
   
   **Why it matters:** Testing in production puts real customer data at risk, and shared credentials let a mistake in testing hit the real system.
   
   **How to check:** Compare the environment variables across environments: the database, API keys, and email service used in production must not appear in development or testing.
   
4. ### Code, configuration, and dependencies are version-controlled, and the version running in production is identifiable
   
   Essential
   
   **Why it matters:** Without version history, you cannot tell what changed before a problem or get back to a version that worked. Without a lockfile, the same code can install different dependencies on every deploy.
   
   **How to check:** Check that the Git repository contains the code, the configuration (without secrets), the deploy scripts, and the dependency lockfile (package-lock.json, bun.lock, poetry.lock, or equivalent), and that the live version matches a known commit or tag.
   
5. ### Automated tests run before every deploy and block it if they fail
   
   Recommended
   
   **Why it matters:** Tests catch regressions before users do. If a failure does not stop the deploy, the test is just decoration.
   
   **How to check:** Open the pipeline configuration and confirm that the test stage runs before the deploy step and that a failure stops the process. Make a test fail on purpose on a branch and watch the deploy get blocked.
   
6. ### Operations are documented: how to deploy, how to roll back, where the logs are, and who to call
   
   Recommended
   
   **Why it matters:** In the middle of an incident, nobody has time to read the code to find out where the logs are. A short document keeps you from depending on a single person.
   
   **How to check:** Look for a README or runbook with the steps for deploying, rolling back, accessing the logs, and restoring a backup, plus a contact list. Ask someone who did not set up the environment to follow the document.
   
7. ### The environment can be recreated from version-controlled files (infrastructure as code)
   
   Advanced
   
   **Why it matters:** Servers configured by hand accumulate tweaks nobody remembers. With infrastructure as code, recreating the environment after a loss is a procedure, not an investigation.
   
   **How to check:** Ask: if the server or the account disappeared today, how much of the environment could be recreated from the repository, with Terraform, OpenTofu, Ansible, Docker Compose, or an equivalent tool?
   
   Reference: [OWASP: Infrastructure as Code Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Infrastructure_as_Code_Security_Cheat_Sheet.html)
   

## Security and access

Only those who need access have it, secrets stay out of the code, and traffic is always encrypted.

1. ### The entire site uses HTTPS: HTTP requests are redirected, and the HSTS header is in place
   
   Essential Verifiable from outside
   
   **Why it matters:** Without HTTPS, passwords, cookies, and form data travel in plain text, readable by anyone along the network path. HSTS makes the browser use HTTPS even when someone types http:// or follows an old link.
   
   **How to check:** Run curl -I http://example.com and check for a permanent redirect (301 or 308) to https://. Then run curl -sI https://example.com and look for strict-transport-security with a long max-age, such as 31536000 (one year).
   
   Reference: [RFC 6797: HTTP Strict Transport Security (HSTS)](https://www.rfc-editor.org/rfc/rfc6797)
   
2. ### HTTP responses include the basic security headers
   
   Recommended Verifiable from outside
   
   **Why it matters:** These headers stop the browser from misinterpreting files, limit what leaks to other sites, and keep the page from being embedded in third-party sites to trick users.
   
   **How to check:** Run curl -sI https://example.com and check for x-content-type-options: nosniff, a referrer-policy (such as strict-origin-when-cross-origin), and framing protection, using frame-ancestors in the CSP or x-frame-options.
   
   Reference: [OWASP: HTTP Security Response Headers Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html)
   
3. ### The page sets a Content-Security-Policy that restricts where scripts can load from
   
   Advanced Verifiable from outside
   
   **Why it matters:** A strict CSP limits the damage of a script injection (XSS), because the browser refuses code that did not come from authorized origins.
   
   **How to check:** Run curl -sI https://example.com and check the content-security-policy header. The script-src directive should not rely on 'unsafe-inline'; prefer nonces or hashes.
   
   Reference: [MDN: Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP)
   
4. ### No secrets are stored in the code or in the repository history
   
   Essential
   
   **Why it matters:** A secret committed to Git stays in the history even after it is deleted, and anyone with access to the repository, or to a leaked copy of it, now has the key.
   
   **How to check:** Run a secret scanner, such as gitleaks or trufflehog, on the entire repository, including its history. Any secret you find must be rotated and revoked, not just deleted.
   
   Reference: [OWASP: Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)
   
5. ### No secret keys appear in the code sent to the browser
   
   Essential Verifiable from outside
   
   **Why it matters:** Anything sent to the browser can be read by any visitor. A secret key there gives direct access to the database, the payment provider, or a paid API.
   
   **How to check:** Download the site's JavaScript files (from the Network tab in the browser's developer tools) and run a secret scanner on them. Every key you find should be a public one, such as a publishable or anon key, never a secret or service key.
   
6. ### Admin accounts use two-factor authentication
   
   Essential
   
   **Why it matters:** A leaked password must not be enough to take over the domain, delete the server, or publish code in your name.
   
   **How to check:** List the accounts with admin rights (cloud, domain registrar, repository, email, payment provider) and check that each one has a second factor enabled, preferably an authenticator app or a security key.
   
   Reference: [OWASP: Multifactor Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Multifactor_Authentication_Cheat_Sheet.html)
   
7. ### People and systems have only the access they need
   
   Essential
   
   **Why it matters:** Excess access is risk with no benefit: it widens the damage from a compromised account or a mistake, and access held by people who have already left stays open.
   
   **How to check:** Export the list of users and keys with access to the cloud, the database, the repository, and the admin panel, and compare it with who actually works on the system today. Remove anything without an owner.
   
8. ### Data access rules are enforced on the server or in the database, not just in the UI
   
   Essential
   
   **Why it matters:** Hiding a button protects nothing, because anyone can call the API directly. If the browser talks to the database directly, row-level security rules must be enabled.
   
   **How to check:** Using a regular account, try to open another user's record through the API or by its direct URL. For databases accessed from the browser, confirm that every table has row-level security policies enabled.
   
   Reference: [OWASP: Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html)
   
9. ### Dependencies with known vulnerabilities are identified and updated
   
   Recommended
   
   **Why it matters:** Third-party libraries have flaws too. Once a vulnerability is published, anyone who has not updated is exposed to an attack that is already documented.
   
   **How to check:** Run npm audit, pip-audit, composer audit, or the equivalent tool for your ecosystem, and turn on automated dependency alerts in the repository.
   
   Reference: [OWASP: Vulnerable Dependency Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Vulnerable_Dependency_Management_Cheat_Sheet.html)
   
10. ### The site publishes /.well-known/security.txt with a contact for reporting vulnerabilities
    
    Recommended Verifiable from outside
    
    **Why it matters:** Someone who finds a vulnerability needs to know who to tell. Without a channel, the report gets lost or goes public.
    
    **How to check:** Open https://example.com/.well-known/security.txt and check for a valid Contact field and an Expires field with a future date.
    
    Reference: [RFC 9116: A File Format to Aid in Security Vulnerability Disclosure](https://www.rfc-editor.org/rfc/rfc9116)
    

## Data, backup, and recovery

Data is backed up outside the primary environment, and restoring it has been tested, not just assumed to work.

1. ### The database is backed up automatically, as often as the acceptable data loss requires
   
   Essential
   
   **Why it matters:** Manual backups get forgotten precisely when they are needed. The frequency determines how much work is lost in the worst case.
   
   **How to check:** Check the schedule (in the provider or in cron), the date of the last completed backup, and whether the frequency meets the acceptable data loss (RPO) that was agreed on.
   
2. ### A copy of the backups is kept outside the primary account and server
   
   Essential
   
   **Why it matters:** If the backup lives on the same server or in the same account, a failure, a human error, or a compromised account wipes out the data and the copies at once.
   
   **How to check:** Find where the backups are stored and confirm that at least one copy is in another account, another provider, or another region, with different credentials and, ideally, protected against deletion during the retention period.
   
3. ### Restoring from backup has been tested recently and timed
   
   Essential
   
   **Why it matters:** A backup that has never been restored is a hypothesis. Testing reveals incomplete copies, lost passwords, and forgotten steps before an emergency.
   
   **How to check:** Restore the most recent backup into a separate environment, check that the application works with the restored data, and record the test date and the total time.
   
4. ### The RPO (acceptable data loss) and RTO (time to get back online) are defined
   
   Recommended
   
   **Why it matters:** Without these two targets, you cannot choose the backup frequency or the recovery architecture, and every incident turns into a negotiation on the spot.
   
   **How to check:** Ask the person accountable for the business: how much data can we afford to lose? How long can we be offline? Compare the answers with what the backups and the last restore test deliver today.
   
5. ### Files uploaded by users are also backed up or versioned
   
   Recommended
   
   **Why it matters:** Images, documents, and attachments usually live outside the database. A restored database without those files is still a broken system.
   
   **How to check:** Find out where uploads are stored (on the server's disk or in object storage) and confirm that this location is included in the backup routine or has versioning enabled.
   
6. ### The database does not accept direct connections from the internet
   
   Essential
   
   **Why it matters:** A database exposed to the internet can be found by automated scans, and from then on a weak password or an unpatched flaw is all it takes.
   
   **How to check:** Check the firewall or security group rules: the database port (for example, 5432 for PostgreSQL or 3306 for MySQL) should accept connections only from the application or a private network.
   
   Reference: [OWASP: Database Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Database_Security_Cheat_Sheet.html)
   
7. ### Personal data is mapped: what it is, where it lives, how long it is kept, and who can access it
   
   Recommended
   
   **Why it matters:** Brazil's data protection law (LGPD) requires you to know what you do with personal data. Without this map, there is no way to respond to a data subject's request or to assess the scope of a data breach.
   
   **How to check:** List the tables, spreadsheets, and services that store names, email addresses, phone numbers, ID numbers, or location data, and note, for each one, the purpose, the retention period, and who has access.
   
   Reference: [Brazilian Law No. 13,709/2018 (LGPD), in Portuguese](https://www.planalto.gov.br/ccivil_03/_ato2015-2018/2018/lei/l13709.htm)
   

## Monitoring and incident response

You find out about problems before your customers do, and you know what to do when one happens.

1. ### An external monitor checks the site and the API and alerts you when they stop responding
   
   Essential
   
   **Why it matters:** Without monitoring, your customers are the ones who report the outage, and sometimes they simply give up instead of telling you.
   
   **How to check:** Confirm that the main pages and endpoints are checked periodically from outside your infrastructure. Take down a monitored test environment and see whether the alert arrives.
   
2. ### Alerts reach the person responsible through a channel they monitor
   
   Essential
   
   **Why it matters:** An alert that lands in an inbox nobody owns is the same as no alert at all.
   
   **How to check:** Trigger a test alert and see who receives it, through which channel (email, chat, phone), and how long it takes someone to respond. Also check who covers vacations and weekends, if the business requires it.
   
3. ### The TLS certificate renews automatically, and its expiration date is monitored
   
   Essential Verifiable from outside
   
   **Why it matters:** An expired certificate makes the browser block the site with a security warning, and it is an entirely avoidable failure.
   
   **How to check:** Run echo | openssl s\_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate and check the date. Renewal should be automatic, with an alert when the expiration date gets close.
   
   Reference: [OWASP: Transport Layer Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html)
   
4. ### Logs are stored off the server, searchable, and kept for a defined retention period
   
   Recommended
   
   **Why it matters:** Investigating yesterday's error is impossible if the logs stayed on a server that has since been recreated, or only exist on the screen of whoever ran the command.
   
   **How to check:** Try to find the errors from a specific day last week and see how long it takes. Also check that the logs do not store passwords, tokens, or unnecessary personal data.
   
   Reference: [OWASP: Logging Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)
   
5. ### Application errors are captured with context: route, version, and message
   
   Recommended
   
   **Why it matters:** An error without context turns into guesswork. With the route, the version, and the stack trace, the fix starts in the right place.
   
   **How to check:** Trigger an error on purpose in a test environment and check that it shows up in the error tracking tool with the route, version, and timestamp.
   
6. ### Response time, error rate, and resource usage are measured and tracked over time
   
   Recommended
   
   **Why it matters:** Without history, you cannot tell whether the system got worse, since when, or whether the last change helped or hurt.
   
   **How to check:** Open the metrics dashboard and try to answer: what was the response time last week? How many requests failed yesterday? How much disk and memory is left today?
   
7. ### There is an incident playbook: who to call, how to communicate, and how to record it
   
   Recommended
   
   **Why it matters:** In the middle of an outage, deciding who does what costs time. A short playbook organizes the response, communication with customers, and the write-up that keeps the problem from happening again.
   
   **How to check:** Find the incident response document and check that it has up-to-date contacts, a communication channel, and a template for recording incidents. See whether recent incidents led to preventive actions and whether those actions were completed.
   

## Performance and costs

The system is fast for the people who use it and costs what it should, with numbers to prove it.

1. ### The main pages pass Core Web Vitals (LCP, INP, and CLS)
   
   Recommended Verifiable from outside
   
   **Why it matters:** These metrics measure what users experience: how long the main content takes to appear, whether the page responds quickly to interactions, and whether the layout jumps around while loading.
   
   **How to check:** Test the main pages in PageSpeed Insights (pagespeed.web.dev) and look at the field data, when available, in addition to the lab test.
   
   Reference: [web.dev: Web Vitals](https://web.dev/articles/vitals)
   
2. ### Text responses (HTML, CSS, JavaScript, and JSON) are sent compressed
   
   Recommended Verifiable from outside
   
   **Why it matters:** Compression reduces the volume of data transferred without changing the content, which speeds up loading and lowers bandwidth costs.
   
   **How to check:** Run curl -s -o /dev/null -D - -H "Accept-Encoding: br, gzip" https://example.com and check that the response includes content-encoding: br or content-encoding: gzip.
   
   Reference: [MDN: Content-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Encoding)
   
3. ### Static assets have long cache lifetimes and versioned file names, and HTML has an explicit cache policy
   
   Recommended Verifiable from outside
   
   **Why it matters:** A well-configured cache keeps the browser and the CDN from re-downloading what has not changed, and takes load off the server at peak times.
   
   **How to check:** Run curl -sI on the URL of a CSS or JavaScript file and check for cache-control with a long max-age (plus immutable when the file name includes a hash). Then check that the HTML page has a deliberately chosen cache-control header.
   
   Reference: [web.dev: Prevent unnecessary network requests with the HTTP Cache](https://web.dev/articles/http-cache)
   
4. ### Slow database queries are logged and reviewed
   
   Recommended
   
   **Why it matters:** A single query without an index can slow down the entire system as the data grows.
   
   **How to check:** Turn on slow query logging (in PostgreSQL, log\_min\_duration\_statement or the pg\_stat\_statements extension; in MySQL, the slow query log) and review the most frequent and the slowest queries.
   
5. ### Monthly cost is known for each service, and a budget alert is set up
   
   Essential
   
   **Why it matters:** A cloud bill nobody watches grows quietly: forgotten resources, unbounded logs, and unexpected traffic only show up on the invoice.
   
   **How to check:** Open the billing dashboard, look at spending per service over the last few months, and confirm that a budget alert exists. Also list resources without an owner, such as forgotten servers, disks, IP addresses, and test environments.
   
6. ### Paid APIs, such as AI services, have spending caps, and the system rate-limits requests per user
   
   Essential
   
   **Why it matters:** Without limits, a bot, an abusive user, or a bug stuck in a loop burns through the paid API in your name and runs up an unexpected bill.
   
   **How to check:** Check each paid API's dashboard for a spending or usage cap. In a test environment, send many requests in a row and see whether, past a certain point, the response becomes 429 (Too Many Requests).
   
   Reference: [MDN: 429 Too Many Requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429)
   
7. ### The system has been tested under higher-than-expected load before launches and campaigns
   
   Advanced
   
   **Why it matters:** Finding the system's limit during a campaign is the most expensive way to find it.
   
   **How to check:** Ask when the last load test was run, at what level of concurrent traffic, and which part gave out first. Tools such as k6 or Locust simulate traffic in a controlled environment.
   

## Domain, DNS, and email

The domain is protected against loss and spoofing, and company email reaches its intended recipients.

1. ### The domain renews automatically, and its expiration date is monitored
   
   Essential Verifiable from outside
   
   **Why it matters:** An expired domain takes down the site and email at the same time, and once it is released, someone else can register it.
   
   **How to check:** Check the expiration date with whois example.com (for .br domains, also on the Registro.br website), confirm auto-renewal in the registrar's dashboard, and verify that the domain's contact email belongs to someone who is still responsible for it.
   
2. ### The registrar account has two-factor authentication, and the domain has a transfer lock
   
   Essential
   
   **Why it matters:** Whoever controls the registrar account controls the domain, and with it the site and email.
   
   **How to check:** In the registrar's dashboard, check the second factor, who has access, and the transfer lock. For generic top-level domains, whois shows the clientTransferProhibited status when the lock is on.
   
3. ### The domain publishes a single SPF record listing the services that send email on its behalf
   
   Essential Verifiable from outside
   
   **Why it matters:** SPF tells receiving servers which servers are allowed to send email for your domain. Without it, deliverability suffers and spoofing the sender gets easier.
   
   **How to check:** Run dig +short TXT example.com and look for a single record starting with v=spf1 that lists the services you use and ends in ~all or -all.
   
   Reference: [RFC 7208: Sender Policy Framework (SPF)](https://www.rfc-editor.org/rfc/rfc7208)
   
4. ### Email sent from the domain is signed with DKIM
   
   Essential
   
   **Why it matters:** A DKIM signature proves that the message came from an authorized server and was not altered in transit.
   
   **How to check:** Send a message from each service that uses the domain (mailbox, application, newsletter) to an external account, open the message source, and check for dkim=pass with your domain in the Authentication-Results header.
   
   Reference: [RFC 6376: DomainKeys Identified Mail (DKIM) Signatures](https://www.rfc-editor.org/rfc/rfc6376)
   
5. ### The domain publishes a DMARC policy and receives the reports
   
   Essential Verifiable from outside
   
   **Why it matters:** DMARC tells receiving servers what to do with messages that fail SPF and DKIM, and asks them to send you reports on who is using your domain. Without it, impersonating your brand gets easier.
   
   **How to check:** Run dig +short TXT \_dmarc.example.com and check for v=DMARC1, a p=quarantine or p=reject policy (p=none is only for the initial observation phase), and a rua= address to receive the reports.
   
   Reference: [RFC 7489: Domain-based Message Authentication, Reporting, and Conformance (DMARC)](https://www.rfc-editor.org/rfc/rfc7489)
   
6. ### MX records point to the email service in use, or declare that the domain does not receive email
   
   Recommended Verifiable from outside
   
   **Why it matters:** An outdated or wrong MX record makes messages disappear. A domain that does not receive email can publish a null MX so senders do not keep trying to deliver to it.
   
   **How to check:** Run dig +short MX example.com and check that the listed servers belong to your current email provider. For domains that do not receive email, the null MX is a record with priority 0 and target “.” (a single dot).
   
   Reference: [RFC 7505: A "Null MX" No Service Resource Record](https://www.rfc-editor.org/rfc/rfc7505)
   
7. ### The domain has a CAA record listing the authorized certificate authorities
   
   Recommended Verifiable from outside
   
   **Why it matters:** CAA prevents an unauthorized certificate authority from issuing a valid certificate for your domain.
   
   **How to check:** Run dig +short CAA example.com and check that only the authorities you actually use appear, including the ones your CDN provider uses, if you have one.
   
   Reference: [RFC 8659: DNS Certification Authority Authorization (CAA)](https://www.rfc-editor.org/rfc/rfc8659)
   
8. ### The domain has DNSSEC enabled, with a valid chain of trust
   
   Advanced Verifiable from outside
   
   **Why it matters:** DNSSEC signs DNS responses and makes it harder for someone to redirect traffic for your domain with forged responses.
   
   **How to check:** Run dig +short DS example.com: if it returns a DS record, DNSSEC is published in the parent zone. To check the entire chain, use an analyzer such as DNSViz (dnsviz.net).
   
   Reference: [RFC 9364: DNS Security Extensions (DNSSEC)](https://www.rfc-editor.org/rfc/rfc9364)
   

## Search engine and AI agent readiness

Search engines and AI assistants can find, read, and cite your content, on the terms you set.

1. ### The site publishes a valid robots.txt that does not accidentally block public content
   
   Essential Verifiable from outside
   
   **Why it matters:** The robots.txt file is the first thing search engines and AI crawlers check. One forgotten line, such as a Disallow: / carried over from the test environment, takes the entire site out of search results.
   
   **How to check:** Open https://example.com/robots.txt and check that it returns 200 as plain text, that the rules allow the public pages, and that there is a Sitemap: line with the full sitemap URL.
   
   Reference: [RFC 9309: Robots Exclusion Protocol](https://www.rfc-editor.org/rfc/rfc9309)
   
2. ### The robots.txt file has explicit rules for AI crawlers, separating search from training
   
   Recommended Verifiable from outside
   
   **Why it matters:** Crawlers that fetch pages for AI assistants to use in their answers are different from crawlers that collect data to train models. Blocking one does not have to block the other, and the choice should be your decision, not an accident.
   
   **How to check:** Look in robots.txt for User-agent entries for AI search crawlers (such as OAI-SearchBot and Claude-SearchBot) and for training crawlers (such as GPTBot, ClaudeBot, and Google-Extended), with rules that reflect your decision.
   
   Reference: [Is Your Site Agent-Ready?](https://isitagentready.com/)
   
3. ### The robots.txt file declares content usage preferences with Content-Signal
   
   Recommended Verifiable from outside
   
   **Why it matters:** The Content-Signal directive states whether the content may be used for search, as input for AI answers, and to train models. Not every crawler honors it, but your preference is explicitly on record.
   
   **How to check:** Look in robots.txt for a line such as Content-Signal: search=yes, ai-input=yes, ai-train=no, with all three values set according to your decision.
   
   Reference: [Content Signals](https://contentsignals.org/)
   
4. ### The site publishes an up-to-date XML sitemap with canonical URLs only
   
   Essential Verifiable from outside
   
   **Why it matters:** The sitemap lists the pages you want found and when they changed, which helps search engines and agents discover new or updated content.
   
   **How to check:** Open https://example.com/sitemap.xml (or the URL given in robots.txt) and check that the URLs return 200, are the canonical versions, and have a lastmod that matches the last real change to each page.
   
   Reference: [Google Search Central: Learn about sitemaps](https://developers.google.com/search/docs/crawling-indexing/sitemaps/overview)
   
5. ### The main content is in the HTML sent by the server, without relying on JavaScript
   
   Essential Verifiable from outside
   
   **Why it matters:** Not every crawler runs JavaScript. If the text only appears after the script runs, some search engines and AI agents see an empty page.
   
   **How to check:** Run curl -s https://example.com/page and look in the returned HTML for the title and the first paragraphs of the page. If they are not there, the content depends on JavaScript to appear.
   
   Reference: [Google Search Central: Understand the JavaScript SEO basics](https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics)
   
6. ### Public pages allow snippets: no noindex, nosnippet, or max-snippet:0
   
   Recommended Verifiable from outside
   
   **Why it matters:** Search engines and AI features need a snippet of the text to show and cite the page. In Google Search, nosnippet also keeps the content from being used as direct input for AI Overviews and AI Mode.
   
   **How to check:** Check the robots meta tag in the HTML and the x-robots-tag header (with curl -sI): public pages should not have noindex, nosnippet, or max-snippet:0. The max-snippet:-1 rule allows snippets with no length limit.
   
   Reference: [Google Search Central: Robots meta tag, data-nosnippet, and X-Robots-Tag specifications](https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag)
   
7. ### The main pages have structured data (JSON-LD) consistent with the visible content
   
   Recommended Verifiable from outside
   
   **Why it matters:** Structured data states explicitly who the organization is, what each page offers, and which questions it answers, without relying on interpretation.
   
   **How to check:** Test the pages in Google's Rich Results Test or the Schema Markup Validator (validator.schema.org), and check that there are no errors and that the data matches what is written on the page.
   
   Reference: [Google Search Central: Introduction to structured data markup in Google Search](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data)
   
8. ### Every page has a Markdown version, through content negotiation or an alternate link
   
   Advanced Verifiable from outside
   
   **Why it matters:** Markdown gives agents the text of the page without menus, scripts, or visual markup, which makes it easier to read and cite correctly.
   
   **How to check:** Run curl -s -H "Accept: text/markdown" https://example.com/page and check that the response comes back with content-type: text/markdown, or look in the HTML for a <link rel="alternate" type="text/markdown"> pointing to the Markdown version.
   
   Reference: [MDN: Content negotiation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Content_negotiation)
   
9. ### The site publishes /llms.txt with a summary and links to the most important pages
   
   Advanced Verifiable from outside
   
   **Why it matters:** The llms.txt proposal defines a Markdown file that introduces the site to language models and points them to its most useful content. It is not universally adopted yet, but it costs little to publish.
   
   **How to check:** Open https://example.com/llms.txt and check that the file starts with a title (#) and a short summary, followed by lists of links to the main pages.
   
   Reference: [llms.txt](https://llmstxt.org/)
   

## Start with a diagnosis

Before investing in changes, understand the risks, bottlenecks and waste in your system. WIP Check delivers an executive report and a prioritized action plan.

[Request a technical diagnosis](https://workinprogress.company/diagnosis)
