The Digital Back Office · Build no. 1

How a directory gets built, in order

Trail Scout is an off-road trail directory seeded entirely from free public government data. Eleven steps, in the order they actually happened, with the tools each one takes. The whole product exists to answer one question: can my rig handle this trail?

The Scout is the free niche-discovery tool that does Step 01 below — installs into Claude Code with two commands, no card.

Leg 1

Groundwork

No code yet. This leg is only about picking something worth building and finding a lawful, free source of data to build it on.

Start here
Step01

Pick the niche

A directory works when the market is fragmented, no single site owns it, and there's a question buyers ask that nobody answers well. For off-road, that question is rig compatibility. The existing apps are navigation — they show you where a trail goes, not whether your specific vehicle survives it. So Trail Scout is the discovery and trip-planning layer, not another map.

The test: name the one filter your competitor doesn't have. If you can't, keep looking.

NeedsA browserClaude, to argue with
Step02

Find a public data source

Never scrape a competitor's listings to seed a competing directory. The good news is that for most physical-world niches a government agency already publishes the underlying dataset for free. Here it's the Forest Service Motor Vehicle Use Maps, served as ArcGIS REST endpoints — thousands of legally designated routes with geometry and vehicle-class rules attached.

Two more sources queued: BLM travel routes, because the Moab classics sit on BLM land rather than Forest Service, and Recreation.gov for campgrounds near trailheads.

NeedsUSFS ArcGIS RESTBLM GTLFRecreation.gov RIDB
Leg 2

Data

Everything here happens in the terminal. The goal is a database full of real, grouped, deduplicated trails — before a single page of the website exists.

Step03

Write the puller

One Python file. It looks up the map layer by name instead of by ID, so it keeps working when the agency renumbers their services. It walks each state by bounding box, pages through the features, and normalizes every row into a clean record — including a derived flag for whether full-size rigs are legally allowed. Raw responses get saved untouched alongside the normalized output, so nothing is lost in translation.

$ python3 pull_trail_data.py --selftest
NeedsTerminalPython 3requests
Step04

Prove the pipe live

Offline self-test first, then one deliberately tiny live pull — a single state, capped at 500 features. It confirmed the layer lookup resolves, the paging works against production servers, and every field the normalizer reads actually exists on live records. What it did not confirm is whether the values are any good. That's what the sanity report in step 07 is for.

$ python3 pull_trail_data.py --states UT --limit 500

Gotcha: the normalized files are rewritten from scratch on every run, so pull all the states you want in one command or you'll only keep the last batch.

NeedsTerminal
Step05

Write the standing brief

A single markdown file in the project root that Claude Code reads at the start of every session. It lists what already works and must not be rewritten, the data-model traps, the current task list, and the house rules. Without it every new session starts by guessing — and the first thing it guesses wrong is that a working script needs refactoring.

The trap it exists to prevent: map rows are segments, not trails. One named trail is many rows. Miss that and every count on the site is wrong.

NeedsClaude Code
Step06

Load it into the database

Schema first, then a loader that upserts the normalized records in batches, keyed on ID so re-running it is always safe. The connection string lives in an environment file and never in the code. Raw segments land in their own table, untouched — every later table is derived from it, so a bad transform is always reversible.

NeedsSupabasePostgres.env
Step07

Group segments into trails

The step that turns a pile of government records into a directory. Segments get grouped by route number, name, and forest into one row per real trail, each with a URL slug, total mileage, and a rolled-up access flag. Then a sanity report prints: how many segments, how many trails, what percentage allows full-size rigs, and the twenty longest routes. That report is the first honest look at whether the dataset is any good.

NeedsSQLPostGIS
Step08

Enrich past what the government gives you

Public data gives you legality and geometry. It does not give you difficulty ratings, obstacle descriptions, photos, or recent conditions — and those are the things people actually search for. This is the crawl layer, and it's a one-time bulk ingest rather than an ongoing feed, which is why an open-source crawler beats a credit-metered service here. The paid tool earns its keep as the fallback for pages that block everything else.

Order matters: crawl only after the trails table exists. Enrichment needs something to attach to, or you're collecting orphaned text.

NeedsCrawl4AIFirecrawl, free tier
Leg 3

Product

Only now does a website appear. Building this leg first is the most common way a directory dies — a beautiful shell with forty listings in it.

Step09

Generate the pages

One page per trail, generated from the database rather than written by hand, plus per-state and near-me pages built from the same rows. This is where the earlier discipline pays off: because trails were grouped properly, every page has a real name, real mileage, and a stable URL instead of a route number nobody searches for.

NeedsNext.jsVercelPorkbun
Step10

Make it findable

Segmented sitemaps so a few thousand pages actually get crawled, IndexNow for fast submission, Search Console to watch what gets indexed versus ignored, and a plain-text file describing the site for AI crawlers. Every trail page also carries a line telling people to verify against the current official map before they go — the printed map is the legal document, not this site.

NeedsSearch ConsoleIndexNow
Step11

Build the part nobody can copy

Anyone can pull the same public dataset — the seed is not the moat. The moat is the rig compatibility engine: matching a specific vehicle, on specific tires, with or without lockers, against a specific trail. That data is manual and community-contributed, it compounds slowly, and it's the reason someone comes back rather than bookmarking a map.

NeedsSupabaseReal users
Appendix A

The whole stack

Everything the build touches, and what each piece is actually for.

ToolWhat it does hereStep
TerminalWhere every data step runs. No dashboard, no UI03–08
Python 3The puller, the loader, the grouping script03–07
USFS / BLM ArcGISFree government route data — the seed02–04
Claude CodeBuilds against the standing brief, reviewed before merge05–11
SupabasePostgres for raw segments and grouped trails06–07
PostGISGeometry column and spatial index for near-me07
Crawl4AIBulk enrichment crawl — photos, conditions, difficulty08
FirecrawlFallback for pages that block the open-source crawler08
Next.jsProgrammatic pages generated from the database09
VercelHosting and deploys09
PorkbunDomain registration and DNS09
Search ConsoleIndexing coverage and query data10
Appendix B

Standing rules

These apply at every step, and they're written into the brief so they survive a new session.

  1. Seed from public data. Never scrape a competitor to build a competing directory.
  2. Never hit a government or third-party server without asking first, and always send a real contact address in the user agent.
  3. Never touch a production database without asking first.
  4. No trademarked term in the product name, the domain, or the logo. Referencing compatible vehicles in the content is fine.
  5. Nothing commits or pushes until it's reviewed.
  6. The official printed map is the legal document. Every public page says so.
FAQ

Common questions

About this build, and about doing it yourself.

Can you really build a directory in a week?

You can get it built and live in about a week — niche picked, public data pulled and grouped into real listings, pages generated, site deployed. That's what this roadmap covers. Getting it ranking is a separate clock: indexation and search traffic still take months, and no tool speeds that up.

What is the Scout, and is it free?

The Scout is the free niche-discovery tool that does Step 01 here — it scores a niche on demand, data, incumbent, and monetization so you know whether it's worth building. It installs into Claude Code with two commands, no card. Get the Scout.

What's the difference between the Scout and Directory Stack?

The Scout finds the niche (free). Directory Stack builds the directory — schemas, page templates, the quality classifier, and the full playbook — for $149 one time. Your Scout key upgrades in place if you buy.

Where does the trail data come from?

Free public government sources — the Forest Service Motor Vehicle Use Maps, with BLM travel routes and Recreation.gov queued. The rule across every build: seed from public data, never scrape a competitor.

Do I need to know how to code?

You need Claude Code running in a terminal and the willingness to follow steps. The scripts and templates are written to be driven by an LLM coding assistant, not typed by hand — but the boring data work is yours, and it's the part that makes a directory worth trusting.

Build your own

Start where this build started.

Every roadmap here begins at Step 01: is the niche worth building? The Scout is the free tool that answers it — the same niche-discovery system from Directory Stack, installed straight into Claude Code with two commands. No card.

When the Scout finds a niche worth building, the rest of this roadmap — schemas, page generation, indexing, the part nobody can copy — is the full Directory Stack, a one-time $149.

Stuck at any step? Email me — a person answers.