<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Black</title>
    <description>The latest articles on DEV Community by David Black (@dcblack87).</description>
    <link>https://dev.to/dcblack87</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2790881%2F4cc53b12-0340-4e36-a9b6-a13ad62ba72d.png</url>
      <title>DEV Community: David Black</title>
      <link>https://dev.to/dcblack87</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dcblack87"/>
    <language>en</language>
    <item>
      <title>I scanned 1,902 local-business websites for AI readiness. One in four already has an llms.txt.</title>
      <dc:creator>David Black</dc:creator>
      <pubDate>Mon, 12 Oct 2026 17:43:03 +0000</pubDate>
      <link>https://dev.to/dcblack87/i-scanned-1902-local-business-websites-for-ai-readiness-one-in-four-already-has-an-llmstxt-47c1</link>
      <guid>https://dev.to/dcblack87/i-scanned-1902-local-business-websites-for-ai-readiness-one-in-four-already-has-an-llmstxt-47c1</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5aezrm9lujr51yztr658.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5aezrm9lujr51yztr658.png" alt="One in four local-business websites already has an llms.txt file: 338 of 1,355" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I build a tool that checks whether AI answer engines can read a website. On 12 October I pointed it at 1,902 ordinary local-business sites in the USA and UK: dentists, plumbers, hairdressers, vets, gyms, estate agents and five other trades, in twenty big cities. 1,355 of them could be read and scored.&lt;/p&gt;

&lt;p&gt;I expected the story to be "small businesses are blocking AI and do not know it". That is not what the data says. Here is what it does say.&lt;/p&gt;

&lt;h2&gt;
  
  
  One in four already has an llms.txt, and most did not write it
&lt;/h2&gt;

&lt;p&gt;338 of the 1,355 sites (24.9%) serve an &lt;code&gt;llms.txt&lt;/code&gt; file. That is far more than I expected for businesses that mostly do not know the file exists.&lt;/p&gt;

&lt;p&gt;The reason is the site builder:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Sites with an llms.txt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wix&lt;/td&gt;
&lt;td&gt;118 of 121 (97.5%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shopify&lt;/td&gt;
&lt;td&gt;27 of 28 (96.4%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duda&lt;/td&gt;
&lt;td&gt;19 of 19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WordPress&lt;/td&gt;
&lt;td&gt;109 of 576 (18.9%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom-built&lt;/td&gt;
&lt;td&gt;38 of 342 (11.1%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Squarespace&lt;/td&gt;
&lt;td&gt;4 of 110 (3.6%)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you are on Wix, you almost certainly have one. If you are on Squarespace, you almost certainly do not. Whether anyone chose that is another matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Almost nobody blocks AI crawlers in robots.txt
&lt;/h2&gt;

&lt;p&gt;Only 9 sites (0.7%) have a robots.txt rule that shuts out an AI answer fetcher such as OAI-SearchBot or PerplexityBot. 14 (1.0%) shut out a training crawler such as GPTBot or ClaudeBot.&lt;/p&gt;

&lt;p&gt;I counted a block only when the file names the crawler and disallows the whole site. By that measure, local businesses are not opting out of AI. They have not touched the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real gap is that sites do not say who they are
&lt;/h2&gt;

&lt;p&gt;This is the finding that matters most for the businesses themselves.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;621 sites (45.8%) have no structured data describing the business at all. No name, address, phone number or hours in a form a machine can read without guessing.&lt;/li&gt;
&lt;li&gt;796 (58.7%) do not give their opening hours in structured data.&lt;/li&gt;
&lt;li&gt;Only 235 (17.3%) state every fact the scan looks for.&lt;/li&gt;
&lt;li&gt;Custom-built sites are worst: 254 of 342 have none. On Wix it is 26 of 121.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An answer engine asked "who is open now near me" has to get that from somewhere. For most of these sites it is not the site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seven in ten have no questions and answers
&lt;/h2&gt;

&lt;p&gt;970 sites (71.6%) had no FAQ page and no question-and-answer content on the pages read. Roofers and plumbers do best. Hairdressers and accountants do worst.&lt;/p&gt;

&lt;h2&gt;
  
  
  The typical score is 58 out of 100
&lt;/h2&gt;

&lt;p&gt;The median readiness score is 58.1. A third of sites score under 50. By platform the medians run from 69.8 (Shopify) down to 47.7 (custom-built), which is mostly the structured-data gap again: builders add it for you, and a hand-built site only has what someone remembered to write.&lt;/p&gt;

&lt;h2&gt;
  
  
  One listed website in six no longer works
&lt;/h2&gt;

&lt;p&gt;A side finding: 328 of the 1,902 sites I sampled from OpenStreetMap had no working website. 147 domains no longer resolve.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it was done, and what it cannot tell you
&lt;/h2&gt;

&lt;p&gt;The sample is independent businesses that list a website in OpenStreetMap, chains removed, up to 100 drawn at random per trade per country. Each site was read over plain HTTP, up to five pages, with no browser and no AI model. Twenty were checked by hand against a second reading and fifty were scanned twice.&lt;/p&gt;

&lt;p&gt;Limits worth knowing before you quote any of this: five pages is not a whole site; the sample leans towards established premises in big cities; and the scan ran from one connection on one day. It says nothing about whether an AI engine actually recommends any of these businesses. It measures whether a site can be read and what it states, which comes first.&lt;/p&gt;

&lt;p&gt;Every count, the method, the infographic and a CSV of the figures are in the full report: &lt;a href="https://mentionmachine.ai/research/ai-readiness-2026" rel="noopener noreferrer"&gt;How ready are local-business websites for AI answers?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contains data © OpenStreetMap contributors, available under the Open Database Licence.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>ai</category>
      <category>webdev</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Seeding a local directory with real listings on day one</title>
      <dc:creator>David Black</dc:creator>
      <pubDate>Mon, 12 Oct 2026 15:06:43 +0000</pubDate>
      <link>https://dev.to/dcblack87/seeding-a-local-directory-with-real-listings-on-day-one-3npk</link>
      <guid>https://dev.to/dcblack87/seeding-a-local-directory-with-real-listings-on-day-one-3npk</guid>
      <description>&lt;p&gt;Nobody adds their business to an empty directory, and nobody searches one twice. So a local directory has to open with listings already in it. Here is how to fill one with real businesses before launch, without inventing anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Count before you build
&lt;/h2&gt;

&lt;p&gt;Pick the unit first: one trade across a set of cities, or every trade in one town. Then count how many real businesses exist in that unit. If "tree surgeons in ten cities" comes to 150 businesses, you have a directory. If it comes to twelve, you have a blog post.&lt;/p&gt;

&lt;p&gt;A rough count takes an hour and saves you from building pages for cities that will hold one listing each.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Choose a source you are allowed to use
&lt;/h2&gt;

&lt;p&gt;There are three honest ones.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Places API.&lt;/strong&gt; The widest coverage, with phone numbers, websites and map positions. It is paid per request, and its terms limit what you may store and for how long, so read them before you design around it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenStreetMap.&lt;/strong&gt; Free and openly licensed (ODbL). You must credit it, and coverage is uneven: good for shops and clinics with premises, thin for trades that work from a van.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public registers.&lt;/strong&gt; Licensing boards, trade associations and council lists. Slow to collect, but often the only complete source for a regulated trade.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copying another directory is not on the list. Their descriptions are their copyright, and their mistakes become yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Make one CSV the hand-off between every step
&lt;/h2&gt;

&lt;p&gt;Whatever the source, land everything in one plain file with fixed column names. A workable minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csvs"&gt;&lt;code&gt;&lt;span class="k"&gt;business&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;website&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;street&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;postal&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;category&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;description&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only the name and the city are essential. The point of the file is that you can open it in a spreadsheet between steps, fix what is wrong and carry on. A pipeline you cannot inspect will import its errors at full speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Clean it before it goes anywhere
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remove duplicates.&lt;/strong&gt; Match on the website's domain first, then on name plus city. The same business often appears under two spellings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide about chains.&lt;/strong&gt; A national chain with forty branches can swamp a niche directory. Keep them or drop them on purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drop the dead.&lt;/strong&gt; A listing whose website no longer loads is usually a business that has closed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assign categories by rule.&lt;/strong&gt; "Found by the search phrase &lt;em&gt;tree removal&lt;/em&gt;" is a reliable reason to file a business under tree removal. A guess from the business name is not.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Write your own descriptions
&lt;/h2&gt;

&lt;p&gt;Do not paste the text from each business's own site. It is theirs, and a page that repeats what is already on the web gives a search engine no reason to show yours. Write two or three plain sentences per listing from the facts you hold: what they do, where, and anything that sets them apart. If you use a language model for this, give it only those facts and check a sample by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Fill in missing map positions
&lt;/h2&gt;

&lt;p&gt;Rows from a places API arrive with latitude and longitude. Rows from a register do not. OpenStreetMap's Nominatim service will look addresses up for free, at no more than one request a second and with a user agent that says who you are.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Import as pending, then approve
&lt;/h2&gt;

&lt;p&gt;Load the file with every listing held back, read a sample of fifty, and only then make them public. Skip duplicates on import so that fixing ten bad rows and loading the file again adds ten listings, not a second copy of everything.&lt;/p&gt;

&lt;p&gt;Once they are live, give owners a way to claim and correct their listing. They know their opening hours better than any source you used.&lt;/p&gt;

&lt;h2&gt;
  
  
  What not to do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Do not publish a city page with nothing on it. Leave the city out until it has listings.&lt;/li&gt;
&lt;li&gt;Do not invent businesses, reviews or ratings to make the place look busy.&lt;/li&gt;
&lt;li&gt;Do not email the businesses you imported unless the law where they are allows it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where this comes from
&lt;/h2&gt;

&lt;p&gt;I build DirectoryLab, a set of self-hosted directory kits. Its local kit runs these steps from the admin screens, and the page that explains &lt;a href="https://directorylab.io/docs/local-lab/data-pipeline" rel="noopener noreferrer"&gt;how the data pipeline works&lt;/a&gt;, including which steps have to run on your own computer, is public whether or not you use the kit.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>startup</category>
      <category>seo</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to check whether your site blocks ChatGPT, Claude and Perplexity</title>
      <dc:creator>David Black</dc:creator>
      <pubDate>Mon, 12 Oct 2026 14:50:16 +0000</pubDate>
      <link>https://dev.to/dcblack87/how-to-check-whether-your-site-blocks-chatgpt-claude-and-perplexity-31nl</link>
      <guid>https://dev.to/dcblack87/how-to-check-whether-your-site-blocks-chatgpt-claude-and-perplexity-31nl</guid>
      <description>&lt;p&gt;Plenty of sites turn AI crawlers away without anyone having decided to. A security plugin, a CDN setting or a line copied into &lt;code&gt;robots.txt&lt;/code&gt; years ago is enough. If an assistant cannot fetch your pages, it cannot quote them, and you will not hear about it.&lt;/p&gt;

&lt;p&gt;Here is how to check, in about ten minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two kinds of crawler, and why the difference matters
&lt;/h2&gt;

&lt;p&gt;AI companies run more than one crawler, and they do different jobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer fetchers&lt;/strong&gt; read a page so an assistant can answer a question with it, often while someone is waiting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;OAI-SearchBot&lt;/code&gt; and &lt;code&gt;ChatGPT-User&lt;/code&gt; (OpenAI)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PerplexityBot&lt;/code&gt; and &lt;code&gt;Perplexity-User&lt;/code&gt; (Perplexity)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Claude-SearchBot&lt;/code&gt; and &lt;code&gt;Claude-User&lt;/code&gt; (Anthropic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Training crawlers&lt;/strong&gt; collect pages to train future models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GPTBot&lt;/code&gt; (OpenAI)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ClaudeBot&lt;/code&gt; (Anthropic)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CCBot&lt;/code&gt; (Common Crawl, whose data many labs use)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Google-Extended&lt;/code&gt; (a &lt;code&gt;robots.txt&lt;/code&gt; token rather than a separate crawler; it controls use of your pages for Gemini)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may reasonably want to block the second group and allow the first. Blocking everything with "AI" in the name is how a business ends up invisible in answers it would have liked to be in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: read your robots.txt
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;https://yourdomain.com/robots.txt&lt;/code&gt; in a browser and look for any of the names above. This blocks one crawler from the whole site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt;&lt;span class="nc"&gt;User&lt;/span&gt;-agent: OAI-SearchBot
Disallow: /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things to know while reading it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A crawler obeys the most specific group that names it. If there is a &lt;code&gt;User-agent: GPTBot&lt;/code&gt; group, GPTBot ignores the &lt;code&gt;User-agent: *&lt;/code&gt; group entirely.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Disallow: /&lt;/code&gt; blocks everything. &lt;code&gt;Disallow:&lt;/code&gt; with nothing after it blocks nothing.&lt;/li&gt;
&lt;li&gt;A crawler that is never mentioned falls back to the &lt;code&gt;*&lt;/code&gt; group, so check that one too.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: check for a block that is not in robots.txt
&lt;/h2&gt;

&lt;p&gt;This is the one people miss. Firewalls, bot-protection plugins and CDN "block AI bots" switches refuse requests before &lt;code&gt;robots.txt&lt;/code&gt; is ever consulted. Your &lt;code&gt;robots.txt&lt;/code&gt; can look fine while every AI request gets a 403.&lt;/p&gt;

&lt;p&gt;You can get a rough signal by sending a request that identifies itself as a crawler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="s2"&gt;"Mozilla/5.0 (compatible; OAI-SearchBot/1.0)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://yourdomain.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;200&lt;/code&gt; is a good sign. A &lt;code&gt;403&lt;/code&gt;, &lt;code&gt;406&lt;/code&gt; or &lt;code&gt;429&lt;/code&gt; means something in front of your site is refusing that name.&lt;/p&gt;

&lt;p&gt;Be honest about what this proves. You are not the real crawler, and some protection checks the IP address as well as the name. A refusal here is strong evidence of a block. A &lt;code&gt;200&lt;/code&gt; is weaker evidence that you are open. Your server or CDN logs are the final word: search them for the crawler names and look at the status codes they actually received.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: decide, then write it down
&lt;/h2&gt;

&lt;p&gt;If you want to be quoted in AI answers but not used for training, say so explicitly rather than relying on defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight apache"&gt;&lt;code&gt;&lt;span class="nc"&gt;User&lt;/span&gt;-agent: OAI-SearchBot
&lt;span class="nc"&gt;User&lt;/span&gt;-agent: ChatGPT-User
&lt;span class="nc"&gt;User&lt;/span&gt;-agent: PerplexityBot
&lt;span class="nc"&gt;User&lt;/span&gt;-agent: Perplexity-User
&lt;span class="nc"&gt;User&lt;/span&gt;-agent: Claude-SearchBot
&lt;span class="nc"&gt;User&lt;/span&gt;-agent: Claude-User
&lt;span class="nc"&gt;Allow&lt;/span&gt;: /

&lt;span class="nc"&gt;User&lt;/span&gt;-agent: GPTBot
&lt;span class="nc"&gt;User&lt;/span&gt;-agent: ClaudeBot
&lt;span class="nc"&gt;User&lt;/span&gt;-agent: CCBot
&lt;span class="nc"&gt;User&lt;/span&gt;-agent: Google-Extended
Disallow: /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then find the setting that caused any firewall block and add the same exceptions there. Changing &lt;code&gt;robots.txt&lt;/code&gt; does nothing if the request never gets that far.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not do
&lt;/h2&gt;

&lt;p&gt;Letting a crawler in means it can read you. It does not mean an assistant will recommend you. That depends on what your pages say and who else says it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A shortcut for step 1
&lt;/h2&gt;

&lt;p&gt;I build MentionMachine, which has a &lt;a href="https://mentionmachine.ai/tools/robots-ai" rel="noopener noreferrer"&gt;free robots.txt checker for AI crawlers&lt;/a&gt;. It reads your file, shows which crawlers are allowed, blocked or never mentioned, and gives you a patch to copy. It writes nothing to your site and needs no account.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>ai</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What a niche directory needs before it can earn anything</title>
      <dc:creator>David Black</dc:creator>
      <pubDate>Mon, 12 Oct 2026 07:45:23 +0000</pubDate>
      <link>https://dev.to/dcblack87/what-a-niche-directory-needs-before-it-can-earn-anything-43ba</link>
      <guid>https://dev.to/dcblack87/what-a-niche-directory-needs-before-it-can-earn-anything-43ba</guid>
      <description>&lt;p&gt;Directory sites look easy: a list of businesses and a search box. The list is the easy part. I have built several of these and sold a few, and the things that decided whether a site earned were never on the listing page.&lt;/p&gt;

&lt;p&gt;Here is what I would have in place before expecting any income.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Real data on day one
&lt;/h2&gt;

&lt;p&gt;An empty directory is a dead one. Nobody claims a listing on a site with twelve entries. Seed it from a source with structured data. For local services that usually means a places API, which gives you a name, address, phone number, opening hours and categories for each business.&lt;/p&gt;

&lt;p&gt;Decide your unit of content early: one page per business, one per city, and one per category in a city.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pages that match what people search
&lt;/h2&gt;

&lt;p&gt;People search for "window cleaners in Leeds", not for your home page. The pages that bring visitors are the category-in-a-city pages, so give each one its own introduction, a count of listings and links to nearby cities.&lt;/p&gt;

&lt;p&gt;Do not publish a city page with nothing on it. Keep it out of the index until it has real listings, or you fill the site with thin pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. A way for owners to claim and pay
&lt;/h2&gt;

&lt;p&gt;The path is: find my business, claim it, verify by email, upgrade. Each extra step loses people, so keep it to one paid tier at first and send them to a hosted checkout rather than building your own card form.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. More than one way to earn
&lt;/h2&gt;

&lt;p&gt;In rough order of effort:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Featured listings.&lt;/strong&gt; The simplest thing to sell, because the buyer can see what they get.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leads.&lt;/strong&gt; A quote form on each category page, with the enquiry forwarded or sold to businesses in that area.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ads.&lt;/strong&gt; Worth adding once category pages have steady traffic, and not before.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. An admin you will actually use
&lt;/h2&gt;

&lt;p&gt;You need a moderation queue, a way to edit and merge duplicates, refunds and a log of who changed what. If fixing a listing takes a database query, you will stop fixing listings.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Automation for the boring parts
&lt;/h2&gt;

&lt;p&gt;Scheduled jobs should refresh hours and closures, rebuild the sitemap, send receipts and email you a daily summary. A directory that needs you every day is a job, not an asset.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would skip at the start
&lt;/h2&gt;

&lt;p&gt;User reviews, because of the moderation load. A mobile app. A second niche. Get one niche earning first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this comes from
&lt;/h2&gt;

&lt;p&gt;I packaged the engines my own directories run on as &lt;a href="https://directorylab.io" rel="noopener noreferrer"&gt;DirectoryLab&lt;/a&gt;. The &lt;a href="https://directorylab.io/docs" rel="noopener noreferrer"&gt;setup guides&lt;/a&gt; are free to read and cover each of the steps above, whether or not you use the kits.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>startup</category>
      <category>seo</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>How to write an llms.txt file for a small business site</title>
      <dc:creator>David Black</dc:creator>
      <pubDate>Mon, 12 Oct 2026 07:34:53 +0000</pubDate>
      <link>https://dev.to/dcblack87/how-to-write-an-llmstxt-file-for-a-small-business-site-2oa7</link>
      <guid>https://dev.to/dcblack87/how-to-write-an-llmstxt-file-for-a-small-business-site-2oa7</guid>
      <description>&lt;p&gt;AI assistants now answer questions like "who is the best plumber near me" by reading websites. An &lt;code&gt;llms.txt&lt;/code&gt; file is a small, plain-text page at the root of your site that tells them who you are and which pages to read first.&lt;/p&gt;

&lt;p&gt;It is an emerging convention, not a standard, and no engine has promised to use it. It takes about ten minutes, so I add one to every site I build.&lt;/p&gt;

&lt;h2&gt;
  
  
  What goes in it
&lt;/h2&gt;

&lt;p&gt;The format is Markdown with four parts, in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An H1 with the name of the business or site.&lt;/li&gt;
&lt;li&gt;A blockquote with a one-line description.&lt;/li&gt;
&lt;li&gt;One or more H2 sections.&lt;/li&gt;
&lt;li&gt;Under each section, a list of links, each with a short note.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Harbour Plumbing&lt;/span&gt;
&lt;span class="gt"&gt;
&amp;gt; Emergency and planned plumbing for homes in Bristol, open seven days a week.&lt;/span&gt;

&lt;span class="gu"&gt;## Services&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Boiler repair&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://example.com/boiler-repair&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: Same-day repairs for gas boilers, with fixed call-out prices.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Bathroom fitting&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://example.com/bathrooms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: Full bathroom installs, from design to tiling.

&lt;span class="gu"&gt;## About&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Pricing&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://example.com/pricing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: Call-out fees and hourly rates.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Contact&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://example.com/contact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: Phone, email and service area.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rules I follow
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use absolute URLs.&lt;/strong&gt; A crawler reading the file on its own has no base URL to resolve against.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write each note as a fact, not a slogan.&lt;/strong&gt; "Same-day repairs for gas boilers" tells a model something. "Best-in-class solutions" tells it nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;List the pages a customer would ask about.&lt;/strong&gt; Services, prices, service area and contact. Leave out legal pages and tag archives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep it short.&lt;/strong&gt; Twenty good links beat two hundred.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serve it as plain text&lt;/strong&gt; at &lt;code&gt;https://yourdomain.com/llms.txt&lt;/code&gt;, with a 200 status.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Check your robots.txt at the same time
&lt;/h2&gt;

&lt;p&gt;An llms.txt is no use if the crawlers are blocked. Look for rules that disallow &lt;code&gt;GPTBot&lt;/code&gt;, &lt;code&gt;ClaudeBot&lt;/code&gt; or &lt;code&gt;PerplexityBot&lt;/code&gt;. Some security plugins and CDN settings add these for you, so it is worth reading the file your site actually serves.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does not do
&lt;/h2&gt;

&lt;p&gt;A good llms.txt helps an engine read your site. It does not make the engine recommend you. The only way to know whether you are mentioned is to ask the engines the questions your customers ask, and read the answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  A shortcut
&lt;/h2&gt;

&lt;p&gt;I build MentionMachine, which has a &lt;a href="https://mentionmachine.ai/tools/llms-txt" rel="noopener noreferrer"&gt;free llms.txt generator&lt;/a&gt;. It builds the file from what you type and can validate one you have already published. There is no account, and nothing is rewritten by a model. There is also a &lt;a href="https://mentionmachine.ai/tools/robots-ai" rel="noopener noreferrer"&gt;robots.txt checker for AI crawlers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have added an llms.txt to your own site, I would like to hear whether you saw any change.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>ai</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
