Mythopia: A Free Library of African Folklore
A free library of curated African folktales in four languages, Spring Boot and PostgreSQL backend, tuned for search and speed, keeping oral storytelling traditions alive online
Oct 2025 – Present
What it does
Mythopia preserves and shares African folklore and fairy tales, the stories grandmothers, mothers and elders have passed down orally for generations. Anyone can read them for free, with no account.
- Readers can browse a story library, explore by tag (such as Ananse/Anansi trickster tales), search, and save favourites.
- Each story page has comments, share buttons and an optional audio player.
- The site is available in English, French, Spanish and Portuguese.
- Signed-in contributors can submit and edit stories through a Keycloak-protected flow.
- It serves three audiences equally: the African diaspora reconnecting with heritage, parents and teachers looking for culturally rich material, and folklore enthusiasts.
- Its main differentiator is editorial trust. The stories are curated, authentic tellings, not generic or AI-generated retellings.
How I built it
- Backend: A Spring Boot (Java) REST API backed by PostgreSQL. It serves stories, tags, authors, comments and saved stories. It publishes an OpenAPI spec, and I generate the Angular API client from that spec with
ng-openapi-gen, so the frontend and backend stay in sync on types. - Frontend: Angular 21 with server-side rendering, hydration and event replay. It uses Tailwind v4 and DaisyUI v5 with a custom theme, and runs as an installable PWA through the Angular service worker.
- SSR server: A custom Express server sits in front of the API with in-memory render caching, sitemap and robots handling, and 301 redirects for merged tags (Anansi to Ananse, egbo to igbo).
- Localisation: Transloco handles UI strings. A translation pipeline, with LibreTranslate seeding, scripts to translate stories and tags, and verification, produces the locale-prefixed
fr,esandptroutes. - Auth and media: Keycloak handles authentication on the client only, so server-rendered pages stay public. Images come from a CDN through a custom image loader.
- SEO as a feature: Every route has its own titles, meta and structured data (BlogPosting, FAQPage, ItemList, BreadcrumbList). I maintained a 43-keyword registry with a baseline scorecard, benchmarked Core Web Vitals against competitors for each keyword, and retargeted
/storiestoward "African folktales". - Quality and docs: A written design language with a PR checklist, an engineering best-practices guide, Lighthouse CI, and a CSS check that runs before each build. The app ships in Docker.
What I learned
- SSR with hydration makes content-heavy sites fast and crawlable, but caching and layout shift (CLS) need active measurement.
- A typed contract between the Spring Boot API and the Angular client removed a whole class of integration bugs. Paginated endpoints, such as the storyteller pages, also kept payloads small.
- For a content site, organic search is the main way readers arrive. Treating SEO as an engineering problem (keyword ownership, sitemap hygiene, canonical redirects) paid off more than ad hoc tweaks.
- Real multilingual support takes more than translating UI strings. Story content, tag names and editorial intros all need translating and verifying.
- Keeping reading anonymous and authentication client-side keeps the public experience simple and cacheable.
- Preserving cultural stories means putting curation and authenticity before volume.