Files
zias/apps/web/src/content/projects/smog.tsx

193 lines
7.1 KiB
TypeScript

import type { Project } from "../../lib/projects";
function Content() {
return (
<>
<h1>SMOG & CO</h1>
<p>
SMOG stands for <i>Spreken Met Ondersteuning van Gebaren</i> Speaking
with Support of Signs. It's a Belgian sign language system developed by
VZW Gezin en Handicap, used by parents, caregivers, therapists, and
teachers to communicate with people with intellectual disabilities — and
even got used to teach a horse the language!
</p>
<p>
It's also useful for anyone learning Dutch: immigrants, young children,
or older adults with dementia. SMOG & Co is the digital platform that
brings that system to life: a video library of SMOG gestures, available
on web, iOS, and Android.
</p>
<img
src="https://img.zias.be/LlebL.png"
alt="SMOG & Co app interface showing gesture library"
className="w-full rounded-lg my-8"
/>
<h2>The web app</h2>
<p>
The web app is a React SPA built with Vite and TanStack Router. At its
core it's a gesture browser: search, filter by category, watch the
video, save to favorites. On desktop you get a split-pane layout — the
gesture list on the left, the video detail on the right — so you never
lose your place while browsing. On mobile it collapses to a single
column and nudges you toward the native app.
</p>
<p>
The app is trilingual — Dutch, French, and English — and GDPR-compliant
by design. Analytics are opt-in, data export and account deletion are
built in, and guest mode means you never have to create an account to
use it.
</p>
<h2>The native app</h2>
<p>
The native app is React Native with Expo, available on both{" "}
<a
href="https://apps.apple.com/app/smog-co/id6758547774"
target="_blank"
rel="noopener noreferrer"
>
iOS
</a>{" "}
and{" "}
<a
href="https://play.google.com/store/apps/details?id=be.zias.smog"
target="_blank"
rel="noopener noreferrer"
>
Android
</a>
. It's not a webview wrapper it's a proper native app with a tab bar,
native navigation, platform-specific icons, and a Rive animation on
launch.
</p>
<p>
The biggest feature is full offline support. All gestures are synced to
a local SQLite database on first launch. From that point on, the app
works without a network connection — you can search, browse, and watch
videos even without internet. When connectivity returns, favorites and
user data sync back to Convex automatically. For a platform whose users
often work in environments like schools, care homes, or on the go, this
isn't a nice-to-have. It's a requirement.
</p>
<h2>Under the hood</h2>
<p>
Both platforms share the same backend — a Convex database for real-time
sync and a Hono API server for auth and business logic. Auth is WorkOS
(PKCE flow on native, cookie-based on web). Videos are hosted on Mux.
The API is oRPC, giving full type safety from the router all the way to
the client on both platforms.
</p>
<h2>The challenges</h2>
<p>
Building two production apps simultaneously is ambitious. The hardest
part wasn't writing the code it was keeping the experience consistent
across platforms while respecting what makes each one native. The web
app and the native app share logic through shared packages, but the UI
layer is entirely separate. Two codebases, one product.
</p>
<p>
The offline architecture on native was its own challenge. SQLite sync
needs to be reliable, fast, and transparent to the user. Getting that
right handling partial syncs, network interruptions, and schema
migrations took serious iteration.
</p>
<p>
GDPR compliance across both platforms added another layer. Consent has
to be collected before any analytics fire, stored correctly, and
respected across sessions. Data export and account deletion aren't just
legal checkboxes — they're full features that touch every part of the
data layer.
</p>
<h2>The sponsoring system</h2>
<p>
This is the part of the project I'm most proud of, and the most unique
thing about SMOG & Co. Organizations and individuals can become{" "}
<i>peter of meter</i> — godfather or godmother — of a specific gesture.
Their name, and optionally their logo, gets rendered directly into the
video. Not as a banner on the page. Into the video itself.
</p>
<p>
The flow works like this: a sponsor picks one or more gestures, enters
their name and optional logo, and gets a live preview video generated on
the spot via Remotion. They watch it, approve it, and pay via Mollie. An
admin reviews and approves the submission. The original gesture video
gets replaced with the sponsored version for exactly one year. When the
year ends, a cron job restores the original video and the sponsorship
expires cleanly.
</p>
<p>
Sponsors pay €50 per gesture per year, plus €10 if they include a logo.
If the admin wants changes, they can send the sponsor a re-edit link —
the sponsor updates their details, a new preview is generated, and it
goes back for review. No re-payment needed.
</p>
<p>
I've never seen a sponsoring model like this anywhere else. It directly
ties financial support to the content it funds. When you sponsor a
gesture, that gesture carries your name. It's tangible, it's meaningful,
and for an organization like SMOG & Co a non-profit that needs
sustainable funding it creates a real incentive for companies to get
involved.
</p>
<h2>250 users in two days</h2>
<p>
We launched and within 48 hours had over 250 registered users. That
number doesn't include guests — people using the app without an account.
For a niche platform serving a specific Belgian sign language community,
that's a strong signal that there was real demand waiting for something
like this.
</p>
<p>
The momentum didn't stop there. Within the first week, SMOG & Co hit{" "}
<b>#6 in the Education category</b> on the Belgian App Store. For a
specialized tool serving a niche community, reaching the top 10
alongside mainstream education apps was a validation that this was
filling a real gap in the market.
</p>
<h2>Stack</h2>
<ul>
<li>React + Vite + TanStack Router (web)</li>
<li>React Native + Expo (iOS & Android)</li>
<li>Convex (database + real-time sync)</li>
<li>Hono (API server)</li>
<li>oRPC (type-safe RPC)</li>
<li>WorkOS (auth)</li>
<li>Mux (video hosting)</li>
<li>Remotion (programmatic video composition)</li>
<li>Mollie (payments)</li>
<li>Turborepo monorepo</li>
</ul>
<p className="text-small opacity-60 mt-12">
This blog was written and reviewed by myself with the help of AI
</p>
</>
);
}
export default {
slug: "smog",
title: "SMOG & CO",
description:
"Sign language learning platform for SMOG & Co VZW — web, iOS, and Android.",
tags: [
"react-native",
"expo",
"convex",
"mux",
"remotion",
"orpc",
"typescript",
],
url: "https://app.smog.vlaanderen",
Content,
} satisfies Project;