richardmowatt.com

Projects

What I build when nobody assigns it.

Three things I own end to end — the code, the Terraform, the boxes, the DNS, the certificates. Nobody hands you a platform team on a side project, which is exactly what makes them worth showing.

GitHub

github.com/rbmowatt

Source for the projects below, plus the smaller packages and experiments that did not earn a section here.

Browse the repositories →

Glazewave Personal project
2026 · live

glazewave.com

Surf session analytics

A log for surf sessions that turns into analytics: what you rode, where, in what conditions, and whether the board was actually the problem.

The stack
Node and Express over MySQL with Sequelize, React and Redux on the front, Elasticsearch behind search, Cognito for auth and S3 for uploads.
The infrastructure
One ARM instance in us‑east‑1 running node, nginx, MySQL and Elasticsearch beside each other. No load balancer, no RDS, no managed search. All of it in Terraform with remote state, TLS renewed by a certbot systemd timer. It runs near $15 a month, on purpose.
The part I like
Conditions resolve to the session’s own date and coordinates, so a session logged three weeks late still gets the swell and wind from the day it actually happened — and a value you corrected by hand stays corrected when you change the date.
  • Node
  • Express
  • MySQL
  • Sequelize
  • React
  • Redux
  • Elasticsearch
  • Cognito
  • Terraform
  • EC2
  • S3
rbmowatt/base Open source
2020 – present

API scaffolding for Laravel

A PSR‑4 package that gives a new Laravel service its response envelope, query parsing, filtering and pagination on day one, so every service stops re‑deciding what a list endpoint looks like.

What it does
One consistent JSON envelope, a query‑string parser for filters, sorts, includes and pagination, and a CRUD service layer the app extends instead of copying.
How it’s held to account
PHPStan level 5 with larastan as its own CI job, plus a PHPUnit suite that keeps the previously‑exploitable cases as regression tests. Filtering is default‑deny: a column a service has not listed is rejected rather than quietly queried, and bulk reads carry a hard row ceiling instead of trusting the caller.
Provenance
First commit June 2020. Supports Laravel 11, 12 and 13 on a PHP 8.3 floor, tagged from v0.1.0 while the API is still moving.
  • PHP 8.3
  • Laravel 11–13
  • PSR-4
  • PHPStan
  • PHPUnit
  • GitHub Actions
Gringo Assist Personal project
2026 · in progress

A WhatsApp assistant for Baja Sur

Chacho tells a non‑Spanish speaker who to contact and what to say, then translates both sides of the conversation inline — inside WhatsApp, with no second app to switch to.

Where it is
The Laravel site is live at gringoassist.mx while the WhatsApp side goes through approval.
The infrastructure
A plain LAMP box: one small ARM instance running Apache, PHP‑FPM and MariaDB together, provisioned with Terraform, DNS delegated to a Route 53 zone. Same shape as Glazewave, deliberately — one pattern run well beats two run badly.
How it’s built
The reusable half goes into PSR‑4 packages under the same vendor, abstract at the core, with the business logic staying in the application. Side projects are where that discipline is cheapest to test.
  • Laravel
  • PHP 8
  • MariaDB
  • Terraform
  • Route 53
  • EC2
  • WhatsApp

Also

This site

Hand‑written HTML and one stylesheet. No build step, no framework, no JavaScript anywhere. It deploys by copying files onto a shared host, which is the correct amount of machinery for a site this size.

Contact

Want to talk about any of it?

Happy to go through the architecture, the tradeoffs, or the parts I would do differently the second time.

richmowatt@gmail.com