Skip to content
Bryant Moreira dos Anjos

Project

Eis Aqui

A local discovery platform for Brazil where the trust signal is how many real people recommended each business. It turns the 'does anyone know a good electrician around here?' question that circulates in WhatsApp neighborhood groups into a searchable directory — with branded business pages, catalogs, quotes, online scheduling, orders and paid plans.

Eis Aqui cover image
TypeScriptReactFastifyPostgreSQLKyselyTailwindCSSDockerGitHub ActionsMCP

Description

Eis Aqui is a local discovery platform for Brazil, organized by city and category, built around one idea: the trust that already exists inside a community is a better signal than star ratings. Instead of asking a WhatsApp neighborhood group for a plumber for the hundredth time, you search a directory where each business carries the number of real people who recommended it — one recommendation per account, binary, no stars. The explicit target is the informal business: no company registration, no storefront, no website. A listing never requires a street address, so someone who cooks at home or does house calls appears the same as a formal shop.

Business owners get a branded page with a catalog, contact links and quote requests for free, and paid plans add in-platform checkout, online scheduling, order and financial management, detailed analytics, coupons and sponsored slots. Every conversation still ends in WhatsApp — the platform organizes discovery, not the relationship. Live at eisaqui.com.br since August 2026.

Technologies

The API is Fastify 5 with Kysely over PostgreSQL and Zod at every boundary, plus Argon2 for passwords, S3-compatible storage with a Sharp image pipeline, web push, and an MCP server that exposes the same service layer so an AI agent can manage listings and categories directly. The web app is React 19 on React Router in SSR mode, with TanStack Query, TailwindCSS 4, i18next (pt-BR and en), and a service worker for PWA/offline. Deployment is continuous: GitHub Actions builds the images and publishes them to GHCR, and the VPS only pulls — nothing is built on the server. Staging and production run side by side on the same machine with separate databases, behind a shared nginx edge that belongs to its own repository.

Repository

Private repository — the live site is the best way to see the product.

Live Demo

eisaqui.com.br is the real thing, in production. You can search and browse by category and city, open a business page with its catalog and contact links, and request a quote without an account; recommending, favoriting and building shareable lists need a login.

Main Challenges

  • Serving SSR pages from a shared cache without ever leaking one visitor’s page to another. The pages that matter for SEO are server-rendered and cached by nginx, but the same routes are also visited by logged-in users with a session cookie — and a cache that is wrong here is not a slow site, it is one visitor seeing another’s account.
  • Ordering results by distance while keeping the cache shared. Distance is the most useful sorting signal for local discovery, and it is different for every visitor — exactly the kind of personalization that makes a shared cache impossible.

Solutions Implemented

  • Routes were split into explicit caching tiers, with the cache key varying by city cookie and bypassed entirely whenever a session is present. The gate is a script that runs against a live instance and asserts three things over real HTTP: every route answers with the Cache-Control its tier prescribes, every shared-cached route renders byte-identical HTML for an anonymous and a logged-in visitor, and the cache in front behaves — MISS then HIT, BYPASS with a session, and a separate entry per city. A unit test asserting a constant would have caught none of that.
  • Distance never reaches the server. The cached payload stays user-agnostic and carries each business’s coordinates like any other public field; the browser computes the haversine distance against the visitor’s location, which is held in memory only and never persisted or sent anywhere. SSR and the shared cache are fully preserved, and the platform never stores anyone’s position.