A database can power the lists, links, and files around a blog without ever holding the articles, and for AI visibility that split is the safe one. The bottom line: keep article content as server rendered or static HTML so crawlers read it directly, and use a database like Supabase for structured records such as a demo library, related links, and generated files, making sure anything a crawler needs is rendered into the HTML and not fetched by the browser afterward.
For a full definition, read our answer engine optimization guide.
What we use Supabase for, and what we do not
Our articles are static HTML files. Supabase holds the records around them: a demos table that drives the automation library, a related demos table linking each demo to up to three others, and the data behind an hourly rebuilt llms.txt. A GitHub Actions workflow runs when a page changes, reads a JSON block embedded in each demo page, upserts a full record into Supabase, and scores related demos by tag overlap. A database trigger on the demos table calls an edge function that submits new and updated URLs to IndexNow.
| Data | Where it lives | Why |
|---|---|---|
| Article body and headings | Static HTML in the page | Crawlers read it directly with no rendering |
| Demo records and tags | Supabase demos table | One source for the library, filters, and llms.txt |
| Related demo links | Supabase related demos table, maximum three per demo | Small, structured, easy to update in one place |
| Related articles on blog posts | Baked into each page's HTML at build time | A crawler can see them without any database call |
| llms.txt | Route that reads Supabase and revalidates every hour | New demos appear without a code change |
The rule that matters for AI visibility
Vercel and MERJ found that the major AI crawlers do not render JavaScript. Anything your page loads from a database in the browser, after the page arrives, is invisible to them. Our related demo cards are loaded by a script, so an AI crawler will not see them, and that is acceptable because they are navigation, not the content we want cited. Article text is a different matter and must never depend on a client side fetch.
How to set up the pattern
- Decide what must be readable by crawlers. Article text, headings, structured data, and links you want followed. Render these into the HTML.
- Put records in tables. A row per demo, tool, or resource, with a stable id and a status field so unpublished items stay out of public lists.
- Add constraints that protect the data. We enforce a unique pair of demo and position so no demo ever has more than three related links.
- Sync from the page, not by hand. Embed a full JSON record in each page and let a workflow upsert it on every push, so the page is the source of truth.
- Generate files from the records. Build llms.txt and sitemaps from the table, so a new record appears everywhere at once.
- Notify search engines on change. A trigger or the sync step submits changed URLs to IndexNow.
- Bake important lists into the HTML at build. Related articles on blog posts are generated ahead of time so they exist in the response.
Mistakes to avoid
- Incomplete records. Our sync fails with a 400 error if the embedded JSON lacks required fields, because the table has required columns.
- Deleting a page without deleting its record. The library then shows a card for a page that no longer exists, and the sync can re add relationships to it.
- Putting article text in the database and rendering it in the browser. That trades a simple static page for content crawlers cannot see.
When a database is the wrong tool
If your site has a few dozen pages and no filterable library, plain files are simpler and give crawlers less to go wrong. A database earns its place when many records share structure and you need to query, filter, relate, or generate files from them.
Questions people ask
Should blog posts be stored in Supabase?
You can store them there, but render them into the HTML on the server or at build. If the browser fetches article text after the page loads, AI crawlers that do not run JavaScript will not see it.
What do we use Supabase for on our own site?
A demo library table, a related demos table limited to three links per demo, and the data behind an hourly rebuilt llms.txt. Articles themselves are static HTML.
How can a database help with indexing?
A trigger can call an edge function that submits new and updated URLs to IndexNow whenever a record changes.
Why bake related links into the HTML?
Because content fetched by a script after load is not in the server response, and AI crawlers do not run JavaScript.