Tech Contra Bolsonaro: Technical SEO and Privacy in 18 Days
SEO & AEOFeatured

Tech Contra Bolsonaro: Technical SEO and Privacy in 18 Days

AI Summary

Paulo H. Alkmin was one of about ten volunteers on Tech Contra Bolsonaro (techcontrabolsonaro.dev), a mobilization hub built in 18 days for the second round of Brazil's 2026 presidential election. The collective speaks as a group and he never spoke for it; on the technical side he set the order of the SEO work and made several of the security and privacy calls. He audited the Next.js 16 site for SEO, AEO and GEO and turned the findings into 28 prioritized issues the team worked from. He fixed crawling and indexing (real 404s instead of soft 404s, a server-rendered tool list, noindex on submission pages), added JSON-LD structured data, a sitemap with real lastmod dates, llms.txt and a Content-Signal line declaring search and AI answers allowed and model training denied. He wrote the LGPD privacy policy and shipped byte-level metadata stripping for uploaded photos and videos, removing GPS and device data without re-encoding. He opened 25 pull requests, all merged. Google Search Console shows organic clicks going from about 2 to 67 a day between October 9 and 29, 2026. The window starts two days into the project and covers weeks of heavy election-related search, so the figure mixes the SEO work with a new site's indexing ramp and election demand.

Volunteer SEO, AEO and privacy work on a Next.js hub built in 18 days for Brazil's 2026 runoff. Organic clicks rose from 2 to 67 a day during election weeks.

October 31, 2026
SEO & AEO
Technologies
Next.js 16Technical SEOJSON-LDllms.txtSupabaseLGPDContent Security PolicyVercel

On October 7, 2026, a group of tech workers started building a site with a deadline nobody could move: the second round of Brazil's presidential election, 18 days later. What came out of it was Tech Contra Bolsonaro, a hub with interactive mobilization tools, a manifesto open for signatures, a moderated feed of photos and videos sent by the community, and an editorial blog.

I was one of about ten volunteers. I took the search side (SEO, AEO and GEO) and ended up owning privacy and security as well. The collective always speaks as a group, and I never spoke for it. Inside the team I set the order of the SEO work, wrote the privacy policy the collective signs, and made several of the calls where the safe default was the wrong one for this site. I wrote a good share of the code too, and I still help maintain the project's infrastructure.

The site Google saw

The engineering underneath was careful. The browser never wrote to the database. Every submission went through a Supabase Edge Function that checked the Cloudflare Turnstile token, the fields, and the file type and size, and new content waited as pending until someone approved it. CI applied database migrations before releasing a production deploy, and a Docker Compose setup with seed data let anyone run the whole thing locally.

Google saw something else. The tool catalog only existed after JavaScript ran, pages that didn't exist answered with status 200, and one H1 read "Carregando..." ("Loading...").

For a crawler, most of the site was empty.

Eighteen days decide the order

I audited the site and split what I found into 28 issues, each with a severity, an effort estimate, the expected gain, its dependencies and acceptance criteria. The calendar set the priorities. A page Google finds on day 16 does very little for a vote on day 18, so whatever blocked crawling went first. Those fixes merged on October 10 and 11: real 404s, the tool list rendered on the server, the "Carregando..." heading gone, noindex on submission pages, and an og:image for every internal page so shared links had a proper preview.

With about ten people contributing in their spare time, the issue list did a second job. Anyone could pick an item and know what "done" meant without asking me first.

Teaching machines what the pages are

Once crawlers could reach the pages, they had to understand them. I added JSON-LD for the organization and the site, a WebApplication for each interactive tool, an ItemList for the catalog, breadcrumbs, WebPage, and ImageObject with creditText, so a community photo carries the credit its author chose. The sitemap got real lastmod dates and stable media URLs. Any page with fewer than 40 words of text gets noindex automatically, which keeps one-line submissions from diluting the pages that matter.

Some of it was plumbing. I migrated the canonical domain with 301 redirects that keep the path, added seo_title and seo_description fields so editors could write search copy without touching code, and modeled a template for full tool pages.

For AI answer engines, the site publishes an llms.txt and a Content-Signal line in robots.txt: search=yes, ai-input=yes, ai-train=no. It states that search engines and AI answers may use the collective's content and that model training may not. Each crawler decides whether to honor it, but the preference is written down. I've covered why entities and structured data carry so much weight now in the 2026 SEO landscape.

A signature is a political opinion

Signing a political manifesto reveals a political opinion. Brazil's data protection law, the LGPD, lists political opinion as sensitive personal data (article 5, II) and restricts how it can be processed (article 11). On a political site with motivated opponents, every form field carries that risk.

I wrote the privacy policy: legal bases, processors, international transfers, retention periods, and the data subject rights in article 18. The collective signs it as a group, without names. The phone field became optional, the submission form now warns that credits are public and suggests a pseudonym, and the policy names who is legally responsible for the data and how to reach them.

Then the uploads. A phone photo taken at a street action can carry the GPS coordinates of where it was taken and the model of the phone. I wrote metadata stripping that works on the file bytes, without re-encoding, for JPEG (progressive and MPF included), PNG, WebP, GIF and MP4. Each format runs on an allowlist that keeps only what the file needs to display and drops everything else. That removes GPS, XMP and manufacturer-specific boxes today, plus whatever a new phone starts writing next year. Decoded pixels and each video's framemd5 stayed identical to the originals.

It also removes C2PA provenance, the data that can prove a photo is authentic. For photos of people at a protest, I chose their privacy over the provenance.

The same work turned up a bigger problem: CI wasn't deploying the submission Edge Function at all.

The metadata fix would have passed every test and never reached production.

Two security calls

I tightened the Content Security Policy, dropping unsafe-eval, restricting connect-src and frame-src and setting object-src 'none', and kept the homepage's ISR cache working through all of it.

HSTS stayed without preload, on purpose. Getting a domain off the browser preload lists takes months, and preload requires includeSubDomains, so the rule would bind every subdomain as well. Two weeks before an election, on infrastructure that changed every day, I didn't want the site making a promise it couldn't take back. Any scanner will flag the missing preload, and for this site that flag was fine.

Every one of my pull requests ran the full test suite, lint, tsc, a build and a check against a local production build. The suite went from about 368 to more than 390 tests along the way.

What the numbers say, and what they don't

Tech Contra Bolsonarotechcontrabolsonaro.dev
PeriodOctober 7 to 25, 2026, ending on election day
TeamAbout 10 volunteers, 127 pull requests and 108 issues in total
My part25 pull requests, all merged (about 20% of the total), and 33 issues, the second-highest count
StackNext.js 16, React 19, TypeScript, Supabase (Postgres with row-level security, Storage, Edge Functions), Cloudflare Turnstile, Vercel
TestingVitest, Testing Library and Playwright
Organic clicks from GoogleAbout 2 a day to 67 a day, October 9 to 29 (Search Console)

The click figure needs its context. October 9 was two days into the project, and the weeks that followed had heavy election-related search, so the jump mixes a new site getting indexed, election demand and the SEO work, and Search Console can't separate the three. The part the SEO work can claim is narrower: when people searched, the pages could be crawled and indexed, and Google and AI answer engines got an accurate description of each one.

Most audits I run come with months to work through the list. This one had 18 days, with crawl fixes in by day four. In the same weeks I also contributed to Radar da Virada, and at the end of the month I built Voto Livre.

If your launch date can't move either, what does Google see on day three?