← back to Costa Rica
yolo tick 8: /about page (data sources, attribution, contact, roadmap, live stats) + Open Graph + Twitter card meta tags on home/provinces/verticals/search/stats + About nav across all pages + sitemap entry
57f58f55832ec59d33302cc11f4532d6de16a4ff · 2026-05-08 13:20:44 -0700 · Steve
Files touched
A public/about.htmlM public/index.htmlM public/province.htmlM public/provinces.htmlM public/search.htmlM public/stats.htmlM public/vertical.htmlM public/verticals.htmlM server.js
Diff
commit 57f58f55832ec59d33302cc11f4532d6de16a4ff
Author: Steve <steve@designerwallcoverings.com>
Date: Fri May 8 13:20:44 2026 -0700
yolo tick 8: /about page (data sources, attribution, contact, roadmap, live stats) + Open Graph + Twitter card meta tags on home/provinces/verticals/search/stats + About nav across all pages + sitemap entry
---
public/about.html | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++
public/index.html | 10 +++++
public/province.html | 1 +
public/provinces.html | 4 ++
public/search.html | 5 +++
public/stats.html | 6 ++-
public/vertical.html | 1 +
public/verticals.html | 5 +++
server.js | 2 +
9 files changed, 146 insertions(+), 1 deletion(-)
diff --git a/public/about.html b/public/about.html
new file mode 100644
index 0000000..4dd63c4
--- /dev/null
+++ b/public/about.html
@@ -0,0 +1,113 @@
+<!doctype html>
+<html lang="en" data-theme="light">
+<head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>About — Costa Rica Directory</title>
+ <meta name="description" content="How the Costa Rica Directory is built — data sources, image attribution, contact, and roadmap." />
+ <meta property="og:type" content="article" />
+ <meta property="og:title" content="About the Costa Rica Directory" />
+ <meta property="og:description" content="A non-commercial directory of Costa Rica businesses. Built from MEIC PYMEs, Hacienda registry, ICT tourism listings, and Wikipedia for region imagery." />
+ <script>(function(){try{var t=localStorage.getItem('cr-theme');if(t)document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>
+ <style>
+ :root{--bg:#fafaf7;--fg:#0e1015;--muted:#5a6270;--line:#e3e0d6;--card:#fff;--card-line:#ebe7da;--accent:#0a7a3a;--accent-2:#c2a85a}
+ [data-theme="dark"]{--bg:#0e1015;--fg:#f3f1ea;--muted:#9aa3b2;--line:#23262d;--card:#15181f;--card-line:#262932;--accent:#3ec07a;--accent-2:#d8c074}
+ *{box-sizing:border-box}
+ body{margin:0;background:var(--bg);color:var(--fg);font-family:-apple-system,BlinkMacSystemFont,'Inter','Segoe UI',Roboto,sans-serif;line-height:1.65}
+ a{color:inherit;text-decoration:none} a:hover{color:var(--accent)}
+ .nav{position:sticky;top:0;z-index:30;background:color-mix(in srgb,var(--bg) 88%,transparent);backdrop-filter:saturate(160%) blur(10px);border-bottom:1px solid var(--line)}
+ .nav-in{max-width:1320px;margin:0 auto;padding:14px 22px;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
+ .brand{font-weight:700;font-size:18px} .brand .pin{color:var(--accent)}
+ .nav-links{display:flex;gap:14px;flex-wrap:wrap;color:var(--muted);font-size:14px}
+ .nav-links a.active{color:var(--fg);font-weight:600}
+ .ml-auto{margin-left:auto} .icon-btn{appearance:none;background:transparent;color:inherit;border:1px solid var(--line);border-radius:999px;width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}
+
+ main{max-width:780px;margin:0 auto;padding:38px 22px 60px}
+ h1{font-size:clamp(34px,5vw,52px);letter-spacing:-.02em;margin:0 0 4px;line-height:1.05}
+ .lead{font-size:18px;color:var(--muted);margin:0 0 28px}
+ h2{font-size:22px;letter-spacing:-.01em;margin:32px 0 10px}
+ p{margin:0 0 14px}
+ .panel{background:var(--card);border:1px solid var(--card-line);border-radius:14px;padding:18px 22px;margin:18px 0}
+ .panel h3{margin:0 0 8px;font-size:16px;letter-spacing:-.01em}
+ .panel p{margin:0 0 8px;font-size:14px}
+ .panel a{color:var(--accent);font-weight:600}
+ ul{padding-left:22px;margin:8px 0 16px}
+ li{margin:4px 0}
+ .src{display:grid;grid-template-columns:140px 1fr;gap:8px 16px;font-size:14px;border-bottom:1px solid var(--line);padding:10px 0}
+ .src:last-child{border-bottom:0}
+ .src .k{color:var(--muted);font-weight:600;text-transform:uppercase;font-size:11px;letter-spacing:.05em}
+ .stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:22px 0}
+ .stat{background:var(--card);border:1px solid var(--card-line);border-radius:14px;padding:16px;text-align:center}
+ .stat b{display:block;font-size:28px;letter-spacing:-.02em}
+ .stat span{color:var(--muted);font-size:13px}
+ </style>
+</head>
+<body>
+ <header class="nav"><div class="nav-in">
+ <a class="brand" href="/"><span class="pin">●</span> Costa Rica Directory</a>
+ <nav class="nav-links">
+ <a href="/">Browse</a>
+ <a href="/search">Search</a>
+ <a href="/provinces">Provinces</a>
+ <a href="/verticals">Verticals</a>
+ <a href="/stats">Stats</a>
+ <a href="/about" class="active">About</a>
+ </nav>
+ <div class="ml-auto"><button class="icon-btn" id="themeBtn" aria-label="Theme">◐</button></div>
+ </div></header>
+
+ <main>
+ <h1>About this directory</h1>
+ <p class="lead">A working catalog of Costa Rica businesses, built from public registries and a few patient nights of importing.</p>
+
+ <div class="stats" id="stats">
+ <div class="stat"><b id="s-total">—</b><span>listings</span></div>
+ <div class="stat"><b id="s-regions">—</b><span>regions</span></div>
+ <div class="stat"><b id="s-verticals">—</b><span>verticals</span></div>
+ </div>
+
+ <h2>Why this exists</h2>
+ <p>Costa Rica is split into 7 provinces and 84 cantones. Discovering local businesses across that geography means jumping between the Hacienda registry, MEIC's PYMEs spreadsheet, ICT tourism boards, and a long tail of municipal patentes pages. This directory pulls those into one place — searchable, browseable, with the source URL kept beside every record.</p>
+
+ <h2>Where the data comes from</h2>
+ <div class="panel">
+ <div class="src"><span class="k">MEIC PYMEs</span><span><b>Primary source.</b> Activas registry of small-and-medium enterprises, ~31K rows. Fed via <a href="https://datos.go.cr/dataset" target="_blank" rel="noopener">datos.go.cr</a> CKAN dumps. Each row carries a cédula jurídica that links back to the Hacienda registry.</span></div>
+ <div class="src"><span class="k">Hacienda</span><span>Costa Rica Ministerio de Hacienda — the formal taxpayer registry. Used to verify cédula jurídica and pull official business name, situación (active / moroso / omiso), regimen, and CIIU activity codes via the public <a href="https://api.hacienda.go.cr/fe/ae" target="_blank" rel="noopener">Hacienda API</a>.</span></div>
+ <div class="src"><span class="k">ICT</span><span>Instituto Costarricense de Turismo — tour operators, lodging, surf schools, and other CST-certified tourism providers.</span></div>
+ <div class="src"><span class="k">Municipal patentes</span><span>City-level patente ledgers (Heredia, Escazú, Liberia, …) for businesses that wouldn't appear in MEIC.</span></div>
+ <div class="src"><span class="k">Wikipedia</span><span>Region cover images come from the Wikipedia REST API <code>/page/summary/{Title}</code> endpoint, with credit and source URL stored alongside the image. Each photo links back to the Wikimedia Commons file page.</span></div>
+ </div>
+
+ <h2>Image and data attribution</h2>
+ <p>Every region hero on this site shows a credit chip linking to the Wikipedia / Wikimedia Commons file page so you can see the photographer and license. Where a place has no photo of its own, we fall back to the region image (also credited). Government data is public-domain under Costa Rica's transparency laws; we keep the source URL on each record so it's auditable.</p>
+
+ <h2>What this is not</h2>
+ <ul>
+ <li><b>Not a transactional marketplace.</b> We don't take payments, route bookings, or hold escrow.</li>
+ <li><b>Not scraped from Reddit, Nextdoor, or social media.</b> Only public registries and structured datasets.</li>
+ <li><b>Not endorsed by the businesses listed.</b> If you're listed and want a correction or removal, email below.</li>
+ </ul>
+
+ <h2>Contact</h2>
+ <p>For corrections, takedown requests, or partnerships: <a href="mailto:info@agentabrams.com">info@agentabrams.com</a>.</p>
+
+ <h2>Roadmap</h2>
+ <ul>
+ <li>Hacienda enrichment pass — formal name + situación for every cédula</li>
+ <li>ICT CST scrape via Browserbase (~150 lodging/tour providers)</li>
+ <li>Per-place og:image enrichment from each website</li>
+ <li>Spanish-language interface toggle</li>
+ </ul>
+ </main>
+
+ <script>
+ const themeBtn=document.getElementById('themeBtn');
+ themeBtn.addEventListener('click',()=>{const cur=document.documentElement.getAttribute('data-theme')||'light';const nx=cur==='light'?'dark':'light';document.documentElement.setAttribute('data-theme',nx);try{localStorage.setItem('cr-theme',nx);}catch{}});
+ fetch('/api/stats').then(r=>r.json()).then(s=>{
+ document.getElementById('s-total').textContent=(s.total||0).toLocaleString();
+ document.getElementById('s-regions').textContent=s.by_region.filter(r=>r.n>0).length;
+ document.getElementById('s-verticals').textContent=s.by_vertical.length;
+ }).catch(()=>{});
+ </script>
+</body>
+</html>
diff --git a/public/index.html b/public/index.html
index 58d05ef..95258e3 100644
--- a/public/index.html
+++ b/public/index.html
@@ -7,6 +7,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Costa Rica Directory — tourism · rentals · local services</title>
<meta name="description" content="A working directory of Costa Rica businesses across tourism, rentals, and local services. Aggregated from government registries (Hacienda, MEIC, ICT) and local listings." />
+ <meta property="og:type" content="website" />
+ <meta property="og:title" content="Costa Rica Directory — 25,000+ businesses across all 7 provinces" />
+ <meta property="og:description" content="Tourism, rentals, and local services across San José, Alajuela, Heredia, Cartago, Guanacaste, Puntarenas, and Limón. Sourced from MEIC, ICT, and Hacienda." />
+ <meta property="og:site_name" content="Costa Rica Directory" />
+ <meta property="og:locale" content="en_US" />
+ <meta property="og:locale:alternate" content="es_CR" />
+ <meta name="twitter:card" content="summary_large_image" />
+ <meta name="twitter:title" content="Costa Rica Directory" />
+ <meta name="twitter:description" content="25,000+ Costa Rica businesses across all 7 provinces. Sourced from public registries." />
<script>
(function(){ try{ var t=localStorage.getItem('cr-theme'); if(t) document.documentElement.setAttribute('data-theme',t);}catch(e){} })();
</script>
@@ -81,6 +90,7 @@
<a href="/provinces">Provinces</a>
<a href="/verticals">Verticals</a>
<a href="/stats">Stats</a>
+ <a href="/about">About</a>
</nav>
<div class="ml-auto" style="display:flex;gap:8px;align-items:center">
<span id="stat-total" class="badge">—</span>
diff --git a/public/province.html b/public/province.html
index 8988b08..01acad2 100644
--- a/public/province.html
+++ b/public/province.html
@@ -69,6 +69,7 @@
<a href="/provinces" class="active">Provinces</a>
<a href="/verticals">Verticals</a>
<a href="/stats">Stats</a>
+ <a href="/about">About</a>
</nav>
<div class="ml-auto"><button class="icon-btn" id="themeBtn" aria-label="Theme">◐</button></div>
</div></header>
diff --git a/public/provinces.html b/public/provinces.html
index e2cfaae..ebdf212 100644
--- a/public/provinces.html
+++ b/public/provinces.html
@@ -5,6 +5,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>The 7 Provinces — Costa Rica Directory</title>
<meta name="description" content="Browse Costa Rica businesses by province — San José, Alajuela, Heredia, Cartago, Guanacaste, Puntarenas, Limón." />
+ <meta property="og:type" content="website" />
+ <meta property="og:title" content="The 7 Provinces — Costa Rica Directory" />
+ <meta property="og:description" content="Browse 25,000+ Costa Rica businesses by province. San José leads at 11K+ listings, then Alajuela, Heredia, Cartago, Guanacaste, Puntarenas, Limón." />
<script>(function(){try{var t=localStorage.getItem('cr-theme');if(t)document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>
<style>
:root{--bg:#fafaf7;--fg:#0e1015;--muted:#5a6270;--line:#e3e0d6;--card:#fff;--card-line:#ebe7da;--accent:#0a7a3a;--accent-2:#c2a85a}
@@ -51,6 +54,7 @@
<a href="/provinces" class="active">Provinces</a>
<a href="/verticals">Verticals</a>
<a href="/stats">Stats</a>
+ <a href="/about">About</a>
</nav>
<div class="ml-auto"><button class="icon-btn" id="themeBtn" aria-label="Theme">◐</button></div>
</div></header>
diff --git a/public/search.html b/public/search.html
index 7c232ff..3d7f1c6 100644
--- a/public/search.html
+++ b/public/search.html
@@ -4,6 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Search — Costa Rica Directory</title>
+ <meta name="description" content="Search 25,000+ Costa Rica businesses by name, address, region, or province." />
+ <meta property="og:type" content="website" />
+ <meta property="og:title" content="Search the Costa Rica Directory" />
+ <meta property="og:description" content="25,000+ businesses across all 7 provinces. Find tourism, rentals, food, retail, services." />
<script>(function(){try{var t=localStorage.getItem('cr-theme');if(t)document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>
<style>
:root{--bg:#fafaf7;--fg:#0e1015;--muted:#5a6270;--line:#e3e0d6;--card:#fff;--card-line:#ebe7da;--accent:#0a7a3a;--accent-2:#c2a85a}
@@ -63,6 +67,7 @@
<a href="/verticals">Verticals</a>
<a href="/search" class="active">Search</a>
<a href="/stats">Stats</a>
+ <a href="/about">About</a>
</nav>
<div class="ml-auto"><button class="icon-btn" id="themeBtn" aria-label="Theme">◐</button></div>
</div></header>
diff --git a/public/stats.html b/public/stats.html
index bd6cf51..dbec837 100644
--- a/public/stats.html
+++ b/public/stats.html
@@ -4,6 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Stats — Costa Rica Directory</title>
+ <meta name="description" content="Live counts of Costa Rica businesses by category, vertical, and region across the directory." />
+ <meta property="og:type" content="website" />
+ <meta property="og:title" content="Costa Rica Directory — Stats" />
+ <meta property="og:description" content="Live counts by category, vertical, and region across 25,000+ Costa Rica listings." />
<script>(function(){try{var t=localStorage.getItem('cr-theme');if(t)document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>
<style>
:root{--bg:#fafaf7;--fg:#0e1015;--muted:#5a6270;--line:#e3e0d6;--card:#fff;--card-line:#ebe7da;--accent:#0a7a3a;--accent-2:#c2a85a}
@@ -44,7 +48,7 @@
<header class="nav"><div class="nav-in">
<a class="brand" href="/"><span class="pin">●</span> Costa Rica Directory</a>
<nav class="nav-links">
- <a href="/">Browse</a><a href="/search">Search</a><a href="/provinces">Provinces</a><a href="/verticals">Verticals</a><a href="/stats" class="active">Stats</a>
+ <a href="/">Browse</a><a href="/search">Search</a><a href="/provinces">Provinces</a><a href="/verticals">Verticals</a><a href="/stats" class="active">Stats</a><a href="/about">About</a>
</nav>
<div class="ml-auto"><button class="icon-btn" id="themeBtn" aria-label="Theme">◐</button></div>
</div></header>
diff --git a/public/vertical.html b/public/vertical.html
index def54ec..c4cb704 100644
--- a/public/vertical.html
+++ b/public/vertical.html
@@ -67,6 +67,7 @@
<a href="/provinces">Provinces</a>
<a href="/verticals" class="active">Verticals</a>
<a href="/stats">Stats</a>
+ <a href="/about">About</a>
</nav>
<div class="ml-auto"><button class="icon-btn" id="themeBtn" aria-label="Theme">◐</button></div>
</div></header>
diff --git a/public/verticals.html b/public/verticals.html
index b0f9e82..734b5a6 100644
--- a/public/verticals.html
+++ b/public/verticals.html
@@ -4,6 +4,10 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Verticals — Costa Rica Directory</title>
+ <meta name="description" content="Browse Costa Rica businesses by vertical — tourism, rentals, retail, food, beauty, fitness, creative, pet, cleaning. 12 verticals across all 7 provinces." />
+ <meta property="og:type" content="website" />
+ <meta property="og:title" content="Browse by Vertical — Costa Rica Directory" />
+ <meta property="og:description" content="12 verticals across tourism, rentals, and local services in Costa Rica. Pick one to see top regions and sample listings." />
<script>(function(){try{var t=localStorage.getItem('cr-theme');if(t)document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>
<style>
:root{--bg:#fafaf7;--fg:#0e1015;--muted:#5a6270;--line:#e3e0d6;--card:#fff;--card-line:#ebe7da;--accent:#0a7a3a;--accent-2:#c2a85a}
@@ -45,6 +49,7 @@
<a href="/provinces">Provinces</a>
<a href="/verticals" class="active">Verticals</a>
<a href="/stats">Stats</a>
+ <a href="/about">About</a>
</nav>
<div class="ml-auto"><button class="icon-btn" id="themeBtn" aria-label="Theme">◐</button></div>
</div></header>
diff --git a/server.js b/server.js
index 0c08294..c0a29c8 100644
--- a/server.js
+++ b/server.js
@@ -491,6 +491,7 @@ app.get('/sitemap.xml', async (_req, res, next) => {
{ loc: '/', changefreq: 'daily', priority: '1.0' },
{ loc: '/provinces', changefreq: 'weekly', priority: '0.8' },
{ loc: '/verticals', changefreq: 'weekly', priority: '0.8' },
+ { loc: '/about', changefreq: 'monthly', priority: '0.7' },
{ loc: '/search', changefreq: 'weekly', priority: '0.6' },
{ loc: '/stats', changefreq: 'weekly', priority: '0.5' },
{ loc: '/?category=tourism', changefreq: 'daily', priority: '0.8' },
@@ -618,6 +619,7 @@ app.get('/stats', (_req, res) => res.sendFile(path.join(__dirname, 'public', 'st
app.get('/provinces', (_req, res) => res.sendFile(path.join(__dirname, 'public', 'provinces.html')));
app.get('/search', (_req, res) => res.sendFile(path.join(__dirname, 'public', 'search.html')));
app.get('/verticals', (_req, res) => res.sendFile(path.join(__dirname, 'public', 'verticals.html')));
+app.get('/about', (_req, res) => res.sendFile(path.join(__dirname, 'public', 'about.html')));
app.get('/v/:slug', (_req, res) => res.sendFile(path.join(__dirname, 'public', 'vertical.html')));
app.get('/pr/:slug', async (req, res) => {
if (!PROVINCE_SLUGS[req.params.slug]) return res.status(404).sendFile(path.join(__dirname, 'public', '404.html'));
← 6f4c5ce yolo tick 7: per-vertical landing pages — /verticals overvie
·
back to Costa Rica
·
snapshot: 10 file(s) changed, +1 new, ~9 modified fce51b2 →