firme.ba
A programmatic business directory turning 88,000 raw government registry records into a searchable, indexable directory of Bosnian companies — without generating a single thin-content page.
Visit live sitePublic business data that nobody can use
The FIA registry contains every registered company in Bosnia & Herzegovina. But the data arrives raw: zero descriptive copy, roughly 42% of records missing an address or phone number, and an activity description that is byte-identical across hundreds of companies in the same category.
The naive programmatic-SEO approach — one page per record — turns 88,000 rows into tens of thousands of pages sharing the same meta description. That is exactly what Google classifies as thin and duplicate content.
Scale is not the hard part. Making each page worth indexing is.
naziv: "A.N. GRADNJA D.O.O." adresa: null telefon: null djelatnost_opis: "Gradnja stambenih i nestambenih zgrada"
Same activity text on 1,000+ records. Nothing to index.
<title>A.N. GRADNJA d.o.o. — Građevinarstvo, Zavidovići</title> <meta name="description" content= "A.N. GRADNJA d.o.o., Sinanovići b.b, Zavidovići. Građevinarstvo." />
Company-specific. Distinct from every sibling page.
Threshold-gated page generation
Pages are not generated because a URL is possible. They are generated when there is enough real data behind them to be worth reading.
Threshold
A category × city combination earns its own page only at 3+ companies. Below that, the page is noindex. Of 3,972 possible combinations, 2,767 (69.7%) qualify.
Revalidate
Next.js ISR with on-demand revalidation. When a combination crosses the threshold, the page, the sitemap, and the internal links update without a redeploy.
Audit
A custom Node.js CLI checks every build for duplicate meta (Jaccard and cosine similarity), slug consistency, and LocalBusiness schema completeness.
What the threshold protects against
Every build has to pass the audit
The audit CLI runs in CI and reports findings by severity. These are the three categories that mattered most, measured before and after the fixes landed.
Duplicate meta descriptions
Meta templates rewritten to use company-specific fields — name, category, city, address, phone, size, year registered — instead of the shared registry activity text. High-severity findings fell from 84,402 to 188 (−99.8%).
Slug inconsistencies
A transliteration layer normalises Bosnian diacritics (č, ć, ž, š, đ) into stable, collision-free URL slugs — applied once at ingest and enforced on every build.
Missing schema fields
Organization and WebSite/SearchAction on the root, BreadcrumbList across all three category levels, LocalBusiness on every company profile.
Want something like this built?
We design and develop web products, directories, and high-performance sites at scale.