Why a 1,044-business directory doesn't need a CMS: the MANYA Madrid case
Does a directory of over a thousand businesses need a CMS, or is version-controlled code and a static build enough?
By Pietro Fiorillo ·
In this article
The problem: becoming the local reference in a market of paid directories
The market was full of directories where whoever pays appears first, with unreliable reviews and outdated data. MANYA Madrid needed to become the local reference for finding trustworthy businesses in Madrid, with visible editorial criteria instead of unlabeled purchased positions.
Why the content lives in code, not a CMS
Each business is an Empresa object defined in TypeScript, inside one of 104 data files. There's no Sanity, no Contentful, no CMS at all: content is edited directly in code and version-controlled with git.
export interface Empresa {
slug: string;
nombre: string;
sectorSlug: string;
barrioSlug: string;
rating: Rating;
descripcionEditorial: string;
rangoPrecios: "€" | "€€" | "€€€" | "€€€€";
premium: boolean;
asociada?: boolean;
ultimaVerificacion: string; // fecha ISO de la última verificación
posicion: number; // 1-10 dentro de sector x barrio
}src/types/index.ts.The posicion field is the key to the entire directory's «ranking»: a number from 1 to 10 within each sector and neighborhood combination, hand-written by me, not computed by any algorithm. The «6-phase methodology» I describe publicly (research, manual verification, review analysis, editorial assessment, ranking, monthly review) is exactly that: a process I follow, not a software pipeline. There's no scraper, cron job or scoring engine anywhere in the repository running it, and I'd rather say that plainly than let it sound more automated than it is.
How the premium plan works with no payment gateway
The directory has a free plan and a featured plan, but there's no Stripe or any payment integration in the code. The plans page itself says so: no online charge, payment is arranged by email after verifying the business.
Counting the real flags across all 1,044 records: 10 businesses have premium: true today. None have asociada: true, the cheaper plan, also meant to be arranged by email.
How I validated this architecture
I ran npm run build against the real repository and counted the generated routes instead of repeating a number from memory.
const nextConfig: NextConfig = {
output: "export",
images: { unoptimized: true },
};next.config.ts.| Metric | Result | Environment / evidence |
|---|---|---|
| Lighthouse Performance (mobile, lab) | 99 / 100 | Lighthouse 13.5.0, simulated throttling |
| LCP (lab) | 1.7 s | Same Lighthouse run, not field (CrUX) data |
| Local build time | 27.0 s | next build with Turbopack, Next.js 16.2.2 |
| Static pages generated | 1,158 | 97 sector pages, 1,044 business pages and the rest fixed routes |
| Export size | 294 MB across 10,325 files | /out folder generated by that build |
| Development commits | 47, from April to October 2026 | The repository's git log, with activity on the very day of this article |
It's by far the highest Lighthouse score I've measured across this whole series. My reading is that a text-and-structured-data directory, with no image carousel or real-time reads blocking initial render, lets static export perform at the very top of what it can deliver: nothing competes with the HTML for first paint.
SEO: notifying Google instead of waiting for it to crawl on its own
The repository's most recent commit, from the same day I'm writing this, adds a script to notify new URLs to Google's Indexing API, instead of relying only on Googlebot finding them on its own in a directory of over a thousand pages.
A system isn't more trustworthy for sounding more automated. It's more trustworthy when you say precisely which part is code and which part is editorial work.
My part in this project
MANYA Madrid is an in-house project within MANYA Digital: I designed the architecture, built the site, and run the research and editorial verification for every listed business.
What I'd do differently: published numbers that didn't match the code
Before writing this article, the project page said «67 sectors» and «over 1,050 businesses». Counting directly in the code (and confirming it with the build output), the real number is 97 sectors and 1,044 businesses. I've already corrected those figures on the project page; I'm recording them here for what they were: outdated data, not a deliberate exaggeration, but genuinely outdated all the same.
What I'd test next
I'd evaluate at what point the «data as code» approach stops being comfortable, probably once more than one person needs to edit at the same time, and I'd automate a simple alert based on the ultimaVerificacion field to flag which listings have gone longest without review before someone has to check by hand.
Sources
Frequently asked questions
Is the 6-phase methodology an automated system?
No. It's an editorial process: research, manual verification, review analysis, editorial assessment, ranking and monthly review. I found no scraper, cron job or scoring engine in the code running it. The 6 phases describe how I work, not a software pipeline.
How is each business's ranking decided?
With a posicion field (1 to 10 within each sector and neighborhood) hand-written in each business's data file. There's no scoring algorithm: position is an editorial decision I enter directly in the code.
Is there a CMS behind the directory?
No. The 1,044 businesses live in 104 version-controlled TypeScript files in the repository, not in Firestore or an external CMS. Firestore is only used for contact forms and change-suggestion submissions.
Why is this project's Lighthouse score so much higher than others?
Likely because it's a text-and-structured-data directory, with no heavy image carousel or real-time reads blocking initial render, unlike a product catalog. Static export performs better when there's less media content to load.
How much does it cost to maintain a directory like this?
Hosting is minimal since it's a static export. The real cost is editorial time: researching, verifying and keeping 1,044 business listings updated by hand, with no CMS automating data entry.