MB
~ / projects / educado

Educado_

A highly performant web platform helping expat families in Spain search and compare schools and kindergartens (guarderías) based on language programs, tuition fees, methodology, transport accessibility, and parental reviews. Built with defense against AI programmatic content aggregators in mind.

Next.js 15.3 React 19 Go Catalog API Laravel 12 Console Go Parser PostgreSQL 16 Elasticsearch 8.18 Redis 7 & Horizon
290+ Next.js files
24 Go handlers
47 controllers
34 services
108 migrations
190+ tests

// architecture

Decoupled Monorepo architecture. Combines a public Next.js frontend, a low-latency read-only Go Catalog API, a Laravel 12 Console for back-office operations and authorization, and a Go Parser for background data enrichment. All components share a single PostgreSQL 16 database and Elasticsearch 8 indexes.

$ cat architecture.txt
Browser
Caddy / Next.js Rewrite
┌────────────┴────────────┐
Go Catalog API Laravel 12 Console
├ stdlib net/http ├ Filament Admin v3
├ raw SQL (pgx/v5) ├ Fortify & OAuth
├ Elasticsearch 8 ├ Redis 7 & Horizon
└ In-Memory LRU Cache └ Domain Events (Queues)
└────────────┬────────────┘
PostgreSQL 16
Go Parser Daemon
(GORM & gocron/v2)
Monorepo Contract

Services share database schema and Elasticsearch definitions without code dependency

API Rewrites

Next.js proxies /api/v3/* searches to Go and /api/v2/* auth/leads to Laravel

Event-Driven Queue

13 Laravel domain events & 14 listeners handled asynchronously via Redis/Horizon

Multi-Level Cache

In-memory LRU cache combined with a Circuit Breaker fallback to PostgreSQL

SSR & ISR Routing

Next.js 15.3 Server Components & Incremental Static Regeneration for optimal LCP

Neobrutalistic Design

Custom Tailwind CSS v4 tokens system with micro-animations & dark-mode styling

// data enrichment pipeline

Multithreaded background parser daemon written in Go that enriches school data through a 4-stage pipeline. Each stage is fully idempotent and safe for repeated execution.

$ ./parser --run-pipeline
Stage 1
Google Places Integration
Search school by name/address → extract coordinates, ratings, reviews, photos
Stage 2
Web Scraping & Extraction
Crawl official school sites → parse schedules, language programs, allergy-safe menu, operations data
Stage 3
Semantic SEO Generator
Algorithmic structured metadata generation and Schema.org JSON-LD formatting
Stage 4
Multi-language Localization
Translate descriptions and text blocks across es, en, ru, uk with a caching layer
// internal/parser/pipeline.go
type Pipeline struct {
stages []Stage
db *gorm.DB
}
type Stage interface {
Name() string
Run(ctx context.Context, school *School) error
ShouldRun(school *School) bool
}

// school profile lifecycle

01. RAW
Raw Data Only

Basic name and address details from initial imports. Excluded from catalog.

02. ENRICHED
Pipeline Enriched

Enriched by Go parser, but not yet verified. Explicitly tagged with noindex.

03. PUBLISHED
Verified & Indexed

Verified with min 4 of 6 key fields (verified prices, badge, photo, ratio/kitchen/patio, Schema, lead form).

04. FEATURED
Premium Profile

Verified with premium media galleries, expanded content, and priority ranking in search results.

// key features

01. School Catalog

  • Low-latency search via Go Catalog API and phase queries
  • 4-level filtering (basic, advanced, expat-specific, sorting)
  • School profiles with valid JSON-LD schemas
  • Side-by-side school comparison (/comparar/{a}-vs-{b})

02. Parent Dashboard & Leads

  • Child profiles with precise age-to-grade matching
  • Favorites, personal notes, and search history
  • Direct lead forms sending parent requests directly to schools
  • Parent reviews with customizable thematic filtering

03. District-URL SEO Engine

  • PRE-rendered static landing hubs for specific districts
  • District-level nesting: e.g. /madrid/escuelas-infantiles/chamberi/bilingues/
  • Hreflang support for 4 locales (es, en, ru, uk) with x-default
  • Rich SEO structures: ChildCare, FAQPage, BreadcrumbList

04. Rich First-Party Data

  • Direct verification of school tuition fees and admission costs
  • Unique route transit text generated from coordinates (metro, bus, walk time)
  • Details: child-to-teacher ratio, dedicated patio, kitchen style
  • Expat-specific tags (bilingual, English focus, guarderías)

// quality & devops

Test Coverage

$ npm run test:ci && composer test
ESLint & Pint ...... passed
Vitest (Front) ..... 77 tests, 0 failures
PHPUnit (Back) ...... 113 tests, 0 failures

CI/CD Pipeline

$ gh workflow view deploy
Detect changes ... front / parser / console
Lint & Test ....... Pint, ESLint, PHPUnit, Vitest
Build assets .... npm run build
Deploy (rsync) .. zero-downtime deploy
Notify .......... Telegram

Security

  • CSRF, rate limiting, and SecurityHeaders middleware
  • Cloudflare Turnstile (CAPTCHA) integration
  • Google OAuth + multi-factor email verification
  • Form Request validation & raw SQL binding injections defense

Infrastructure

  • Ansible playbooks for server configuration and setups
  • Caddy reverse proxy with automatic SSL certificate management
  • systemd services to run Go services and Laravel Horizon worker queues
  • Makefile utilities for updates, backups, and deployments

// tech stack

Backend
Go 1.24 Catalog API
Laravel 12 Console
PHP 8.4, stdlib net/http
pgx/v5 (Raw SQL)
Frontend
Next.js 15.3
React 19
TypeScript 5.8
Tailwind CSS v4
next-intl, Vitest
Search & Database
Elasticsearch 8.18
PostgreSQL 16
Redis 7 + Horizon
LRU Cache, GORM (Parser)
Integrations
Google Places API
next-intl (4 languages)
Caddy Proxy (auto TLS)
Turnstile CAPTCHA
$ project-stats --summary
290+ Next.js components
24 Go API handlers
47/34 Controllers/Services
108 DB migrations
13/14 events/listeners