Freelance

Doe Kyae Latt

Astro React TypeScript Tailwind CSS Keystatic CMS Cloudflare Leaflet Vitest

Overview

A commission for a Myanmar-based organic fertilizer company that needed a professional web presence. The site needed to work for two distinct audiences, English and Burmese speakers, across every piece of content. Rather than hardcode content, the whole site is driven by Keystatic CMS so the client's team can manage products, publish blog articles and videos, and update store listings without touching code. The store locator uses an interactive Leaflet map so customers can find nearby retailers. Deployed on Cloudflare Workers for fast global delivery.

What I built

  • Full bilingual support, every page, product, and blog post has an English and Burmese version with a live language toggle
  • Keystatic CMS integration so the client manages all content, products, blogs, videos, stores, and homepage, without developer involvement
  • Product catalog with filtering by plant type and size, featured product highlights, and star ratings
  • Blog with separate article and video post types
  • Interactive store locator built with Leaflet and React Leaflet, driven by CMS-managed location data
  • Hero slider, contact page, and privacy policy, all CMS-editable
  • Vitest unit test suite covering content utilities and component logic
  • Deployed on Cloudflare Workers with SSR via the Astro Cloudflare adapter

What I learned

  • Building a robust bilingual content system, structuring data so EN/MM fields are always in sync and neither language is an afterthought
  • Keystatic CMS, setting up collections, singletons, and content schemas that non-technical editors can actually use
  • Astro SSR with the Cloudflare adapter, edge rendering, environment constraints, and what prerender vs. server means in that context
  • Working with a client who isn't a developer, writing documentation, setting up editor guides, and designing the CMS schema around their workflow
  • Integrating Leaflet in an Astro/React SSR environment without SSR hydration conflicts

Architecture

flowchart TD
    Editor([" Client Editor"])
    Visitor([" Site Visitor"])

    subgraph CMS["Keystatic CMS"]
        Products["Products"]
        Blog["Blog Articles
& Videos"]
        Stores["Store Locations"]
        Home["Homepage Content"]
    end

    subgraph Astro["Astro SSR App"]
        Pages["Bilingual Pages
(EN / MM)"]
        Catalog["Product Catalog
& Filtering"]
        BlogPages["Blog
(Articles + Videos)"]
        Locator["Store Locator
(React Leaflet)"]
    end

    CF[" Cloudflare Workers"]

    Editor --> CMS
    CMS --> Astro
    Visitor -->|"requests"| CF
    CF --> Astro
    Astro --> Pages
    Pages --> Catalog
    Pages --> BlogPages
    Pages --> Locator