Data yako
Database yako iko kwenye seva yako, Tanzania. Hakuna mtu wa tatu anayeshikilia funguo. Own your data, on your own soil.
Sehemu ya stack sovereign ya Laetoli
Laetoli Data ni backend unaojiendesha mwenyewe — database, REST API, na uthibitishaji — unaokimbia kwenye VPS ya Tanzania au Raspberry Pi. Miliki data yako, acha kulipa ada za kila-project za SaaS.
A sovereign, self-hostable backend — Postgres + PostgREST + auth + a drop-in SDK. Open, offline-capable, Swahili-aware.
Why own your backend. Four reasons it matters.
Database yako iko kwenye seva yako, Tanzania. Hakuna mtu wa tatu anayeshikilia funguo. Own your data, on your own soil.
Endesha apps nyingi kwenye seva moja. Lipa seva, sio kila mradi. No per-project SaaS fees.
Stack nzima ndani ya kisanduku kinachoshika mkononi — "shule ndani ya kisanduku", bila internet. An offline classroom in a box.
Msimbo wazi, leseni ya Apache-2.0. Stack iliyothibitishwa: PostgreSQL + PostgREST. Open, Apache-2.0, built on proven tools.
One TLS edge, two services, one database. Caddy → PostgREST + auth → Postgres + RLS.
anon, authenticated, laetoli_admin. Row-Level Security inatumia sub (user id) + role kutoka kwa JWT — mfano uleule wa Supabase, hivyo RLS migrations zinahamia moja kwa moja.PGRST_JWT_SECRET.{ sub, role, exp }./rest/* → PostgREST, /auth/* → auth.Hatuvumbui Supabase upya — tunakusanya stack iliyothibitishwa (PostgreSQL + PostgREST) pamoja na auth nyepesi ya sovereign na SDK ya drop-in.
Karibu drop-in ya Supabase — badilisha import tu. @laetoli/data, zero deps, pure fetch.
import { createClient } from '@laetoli/data';
// Point at your Laetoli Data endpoint (VPS or a Raspberry Pi).
const db = createClient('https://data.yangu.tz', {
apikey: 'optional-anon-key',
});
// Query / Hoji
const { data, error } = await db
.from('works')
.select('id, title, author_id')
.eq('type', 'pulse')
.order('created_at', { ascending: false })
.limit(20);
// Auth / Uthibitishaji (username + password, or anonymous)
await db.auth.signInWithPassword({ username: 'naim', password: '••••' });
await db.auth.signInAnonymously();
const { data: { user } } = await db.auth.getUser();
- import { createClient } from '@supabase/supabase-js';
+ import { createClient } from '@laetoli/data';
- const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
+ const supabase = createClient(LAETOLI_DATA_URL, { apikey: ANON_KEY });
Inahifadhi shapes zilezile: from().select/insert/update/delete/eq/order/limit/single na auth.signUp/signInWithPassword/signInAnonymously/getUser/signOut → { data, error }. Tofauti: utambulisho ni username, sio email.
Three steps to a running backend. Docker Compose inashughulikia kila kitu.
Anza na faili la mazingira.
cp .env.example .env
Tengeneza POSTGRES_PASSWORD na JWT_SECRET ndefu, za nasibu.
echo "JWT_SECRET=$(openssl rand -base64 48)"
Postgres + PostgREST + Auth + Caddy, zote kwa amri moja.
docker compose up -d
Picha zote ni multi-arch (linux/arm64). Acha CADDY_DOMAIN wazi kwa LAN ya HTTP-tu, docker compose pull mara moja ukiwa na internet, kisha stack inawaka bila internet. Apps zinaelekea kwa IP ya LAN ya Pi. Ona RASPBERRY_PI.md.