193 lines
7.1 KiB
TypeScript
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;
|