DEV Community

QRflows
QRflows

Posted on

Why I added llms.txt to my SaaS — and what happened when Claude actually read it

I build QRflows — a dynamic QR code platform. A few months ago I did two things back to back: added an MCP server so Claude can create QR codes from chat, and added an llms.txt file to the root of the site.

The MCP server got all the attention. The llms.txt file got none. But in some ways it was the more interesting decision — and the reasoning behind it taught me something about how AI systems actually navigate websites.


What llms.txt actually is

llms.txt is a plain Markdown file at the root of your domain. It tells AI systems what your site is, which pages matter, and where to find more information.

Think of it as the difference between a stranger walking into your office and reading random papers off a desk versus you handing them a one-page brief first.

Here's what ours looks like (simplified):

# QRflows

> Dynamic QR code platform with Smart Rules, real-time analytics, and Claude MCP integration.

QRflows lets you create QR codes that can be edited after printing, tracked in real time,
and routed conditionally by country, device language, or time of day.

## Core features

- [Dynamic QR codes](https://qrflows.app/dynamic-qr-codes): Edit destination URL after printing
- [Smart Rules](https://qrflows.app/qr-code-for-smart-rules): Route by country, device, language, time
- [Analytics](https://qrflows.app/qr-code-analytics): Real-time scan tracking
- [Landing pages](https://qrflows.app/qr-code-landing-pages): Branded pages without a website
- [Product QR](https://qrflows.app/product-qr): Micro-sites for physical packaging

## QR code types

- URL, WiFi, vCard, PDF, Menu, Email, WhatsApp, Telegram, Google Review, and more

## Plans

- Starter €9/mo — 2 QR codes, 20,000 scans
- Growth €19/mo — 50 QR codes, unlimited scans, landing pages, bulk creation
- Pro €39/mo — 250 QR codes, A/B testing, Smart Rules, API, Product QR

## MCP integration

Claude can create, update, and track QR codes directly from chat.
Server: https://mcp.qrflows.app/mcp
Docs: https://qrflows.app/mcp

## Optional

- [Blog](https://qrflows.app/blog): Guides and use cases
- [Developer API](https://qrflows.app/developer-api): REST API docs
- [Free QR generator](https://qrflows.app/qr-code-generator): No signup required
Enter fullscreen mode Exit fullscreen mode

Note: This is our actual file — feel free to use it as a template.


Why most explanations miss the point

The standard explanation of llms.txt goes like this: AI models scrape your website, but HTML is full of noise — navigation, ads, scripts, footers. llms.txt gives them clean content.

That's true. But it's not the most interesting part.

The more interesting part is intent and priority.

When an AI model lands on your website without a guide, it has no idea which pages are canonical. Is your /features page the source of truth, or /pricing? Is your blog authoritative, or is it marketing content? Is that /docs/v1 page still current, or has it been superseded?

Without guidance, the model guesses. It often guesses wrong. It might pull your pricing from a blog post that mentions old numbers, or describe your features based on a landing page written for a different audience.

llms.txt solves this by explicitly saying: here is what this product is, here are the pages that matter, here is the hierarchy of information.


The specific reason I added it alongside MCP

Here's where it gets relevant for anyone building AI-facing tools.

We have an MCP server. When someone uses Claude to create a QR code, Claude calls our tools. But before it does, Claude forms a mental model of what QRflows is — from whatever it learned during training, or from whatever it can fetch in context.

If that mental model is wrong, the interaction goes sideways. Claude might not know that Smart Rules exist. It might not know that Product QR is Pro-only. It might describe our free generator as if it's our main product.

llms.txt is the fastest way to correct that model before any tool call happens. It's context front-loading.

The sequence we want:

  1. User asks Claude to help with QR codes
  2. Claude reads llms.txt → accurate understanding of the product
  3. Claude calls MCP tools with the right context
  4. Output is actually useful

Without step 2, step 4 is unreliable.


Who actually reads llms.txt right now

Honest answer: it's uneven.

As of mid-2026, Perplexity has confirmed support. Some versions of Claude and ChatGPT will fetch it when explicitly pointed at a domain. Cursor fetches it for library documentation. AI agents built on top of these models increasingly look for it.

But most crawlers don't proactively fetch it yet. If you publish a perfect llms.txt today, plenty of AI systems will still walk past it.

So why bother?

Two reasons.

First, adoption is accelerating. The file costs you almost nothing to publish — maybe an hour to write well. The upside is asymmetric: as more AI systems adopt the standard, every one of them gets an accurate picture of your product without you doing anything extra.

Second, it disciplines your own thinking. Writing llms.txt forced me to answer: what is QRflows, in one sentence? Which features are core versus secondary? What's the pricing in plain language? What pages actually matter?

I've written landing pages, blog posts, and product docs for QRflows. None of them forced me to answer those questions as concisely as writing 40 lines of Markdown did.


What I'd do differently

Write llms.txt before your landing page, not after.

The exercise of writing it — what is this, who is it for, what are the key pages, what's the pricing — is the same exercise as product positioning. Doing it first makes everything else easier to write.

Keep it honest about limitations.

I included the plan limits (Starter: 2 QR codes, Growth: 50) because if an AI recommends QRflows to someone who needs 100 QR codes on a €9 budget, that's a bad outcome for everyone. Accurate information beats optimistic information.

Add an llms-full.txt if you have documentation.

llms-full.txt is an optional companion — a single file that dumps all your documentation in one place. For a SaaS with deep docs, it's worth doing. For a simple product site, llms.txt alone is enough.


The file itself

Ours is live at qrflows.app/llms.txt.

If you're building a SaaS and want to add one, the format is:

# Product Name

> One sentence description.

Brief paragraph: what it is, who it's for.

## Section heading

- [Page title](url): One-line description
- [Page title](url): One-line description

## Optional (lower priority content)

- [Blog](url): ...
Enter fullscreen mode Exit fullscreen mode

The > blockquote at the top is the canonical one-sentence description that AI systems extract first. Keep it sharp.


Links


If you've added llms.txt to your product — drop a comment with what format you ended up using. Curious what others include in Optional.

Top comments (8)

Collapse
 
publiflow profile image
PubliFlow

Adding an llms.txt file is a solid move, but I found that keeping it synchronized with actual API changes becomes a maintenance burden pretty quickly. Have you considered integrating the Model Context Protocol instead, so the LLM can dynamically query your endpoints for real-time context rather than relying on a static snapshot? I noticed a significant drop in hallucinations when switching from static documentation files to dynamic tool calls for my own integrations. It would be interesting to hear how you balance the freshness of your text file with the overhead of manually updating it.

Collapse
 
qrflows profile image
QRflows

Both, actually — that's exactly the combination we landed on.

The llms.txt gives Claude a stable product overview before any tool call happens. The MCP server (mcp.qrflows.app/mcp) handles the dynamic part — create QR, update URL, pull scan stats in real time.

They solve different problems: llms.txt is context about what the product is, MCP is context about what's happening in the account right now. Static snapshot for intent, dynamic calls for state.

The maintenance burden is real though. Every time pricing or a feature changes, llms.txt needs a manual update. Haven't automated it yet — it's short enough that it's a 10-minute job, but I can see it becoming a problem at scale.

Collapse
 
publiflow profile image
PubliFlow

Splitting the static product schema from the real-time state mutations is a smart way to prevent the LLM from hallucinating outdated account data. Relying on the MCP server for actual tool calls keeps the context window clean and focused. I am curious if you have noticed any significant latency spikes when Claude has to chain multiple MCP calls compared to just reading the static file.

Thread Thread
 
qrflows profile image
QRflows

Latency difference is real but smaller than I expected. A single MCP call (list_qr_codes, get_qr_stats) adds ~300-500ms on Cloudflare Workers. Chained calls stack — so create + verify + get_stats is closer to 1-1.5s total.

The static file read is effectively zero latency in comparison.

But the tradeoff isn't really latency vs freshness — it's about what Claude is doing. For answering "what is QRflows" the static file is fine and faster. For "show me scan stats for my QR from last week" you need the live call regardless of latency.

Haven't hit a case yet where the latency was a problem in practice. The UX bottleneck is usually Claude deciding which tool to call, not the call itself.

Thread Thread
 
publiflow profile image
PubliFlow

That 300-500ms latency per MCP call definitely compounds during chaining, but your distinction between data freshness and cognitive load is the real takeaway. If the model is just acting as a dumb fetcher, that delay feels like a penalty, whereas using the static schema to reason about state mutations turns it into a necessary thinking tax. Have you noticed that feeding the static schema upfront actually reduces the total number of chained tool calls by helping Claude plan the execution path more efficiently?

Collapse
 
bulti_global profile image
Bulti

The split between an explicit Claude read and proactive discovery is the key caveat here. In a 284-brand Korean DTC scan we ran, 65.5% had zero appearances across 50 AI shopping-question checks, and the mean was only 0.648 appearances out of 50. So I’d treat llms.txt as controlled context for an MCP or user-directed fetch, not yet as evidence of organic discoverability. In your sequence, did Claude fetch /llms.txt without being pointed to it, or only after the domain/file was explicitly included in the prompt or connector context?

Collapse
 
qrflows profile image
QRflows

Honest answer: only when the domain was explicitly included — via MCP connector or direct URL in prompt. No unprompted discovery observed. Your "controlled context, not organic discoverability" framing is more accurate than mine.

Curious about your methodology — one model or multiple across those 50 checks?

Some comments may only be visible to logged-in visitors. Sign in to view all comments.