Eduin Garcia
Qollabi · Senior Software Developer & DevOps Engineer · Jan 2024 – Apr 2026

Qollabi 2.0 — aground-up rewrite

Multi-tenant B2B SaaS for partner and channel management — workspaces, partner and customer records, opportunities, objectives and key results (OKRs), campaigns with a visual email builder, smart lists, shared partner spaces and CSV import. It is a ground-up TypeScript rewrite of the legacy PHP and React platform, deployed under the internal project name qollabi-ai.

Qollabi platform
Qollabi 2.0 — platform scaleBun workspacesSheet 01
~205k
Lines of TypeScript
7 + 26
Apps & shared packages
77
PostgreSQL tables
64
Migrations
163
Command handlers
545
Route modules
81
Design-system components
19
Background jobs

Team-built platform; my own contribution is in section 01.

01 · My role

Product · pipelines · cloud

02 · Architecture

Bloom · CQRS · RLS tenancy

03 · Apps in the monorepo

Seven deployables
shelfCustomer-facing Remix SPA and SSR app for partnerships, opportunities and OKRs (473 route modules).
dashboardInternal admin app for organizations, workspaces and campaign/smart-list templates.
spacesExternally shared partner spaces app.
backendThe domain layer: schemas, repositories, commands, events and jobs, consumed in-process by the apps.
workerGraphile Worker process (3 replicas locally) plus a React Email preview server.
webhooksStandalone Hono service for inbound webhooks (Postmark, integrations).
public-apiPylon GraphQL surface for third-party integrations.

04 · Backend

Bun · Hono · PostgreSQL 17
Runtime
Bun 1.2 / Node 22, TypeScript 5.5
Framework
Bloom (in-house kernel + plugin system), Hono 4
Database
PostgreSQL 17, Drizzle ORM 0.36 + drizzle-zod, postgres / pg drivers
Migrations
Custom @bloom/drizzle-migrations CLI on Drizzle Kit — generate, up/down, status, rebase, validate, fresh, refresh (Jest-tested)
Auth
Keycloak 26 (OIDC) via remix-auth-oauth2, jsonwebtoken, Keycloak Admin Client SDK wrapper, bcrypt-edge
Queues / jobs
Graphile Worker (Postgres-backed), typed job registry, 19 background jobs
Pub/Sub
@bloom/postgres-emitter — LISTEN/NOTIFY client with channel mapping, auto-reconnect and backoff
KV / cache
Keyv with a PostgreSQL adapter (@keyv/postgres)
Validation
Zod 3 everywhere — command schemas, env schemas, @hono/zod-validator, zod-validation-error
Email
Postmark (transactional + inbound webhooks), React Email for templates, Maily for the customer-facing drag-and-drop builder
Storage
AWS S3 SDK v3 + presigned URLs (LocalStack in dev)
Data import
Streaming CSV pipeline — csv-parser, chardet + iconv-lite encoding detection, S3 staging, chunked job processing
i18n
i18next + remix-i18next, per-module translation catalogs (en / fr / nl)
Logging
Pino (pino-pretty in dev)
Errors
Sentry (toucan-js) and Rollbar
Public API
@getcronit/pylon — GraphQL generated from plain TypeScript functions (early scaffold)

05 · Frontend

Remix 2 SSR · React 18.3
Core
React 18.3, TypeScript 5.5, Remix 2 (Vite 5), SSR
Routing
remix-flat-routes, typed search params via nuqs, remix-hono server adapter
Components
shadcn/ui on Radix UI primitives (~22 packages) — shared @bloom/ui-web with 81 components + blocks, hooks and themes
Styling
Tailwind CSS 3.4, tailwindcss-animate, class-variance-authority, clsx, tailwind-merge, Poppins via Fontsource
Forms
React Hook Form 7 + remix-hook-form + Zod resolvers
Client state
Redux Toolkit + React Redux (shelf), nuqs for URL state
Tables & lists
react-virtuoso (virtualized lists), react-easy-sort, emblor (tag input)
Charts
Recharts 2
Maps
Mapbox GL / MapLibre GL via react-map-gl
Rich text
TipTap 3 (inside the Maily email editor)
Dates
date-fns + date-fns-tz, react-day-picker
Multi-step forms
@bloom/wizard — type-safe wizards with pluggable cookie / KV / memory storage backends and automatic namespaced state
Icons
Lucide, FontAwesome Pro
Misc
Sonner, Vaul, cmdk, Embla, Motion, input-otp, react-phone-number-input, react-currency-input-field, next-themes, NProgress
Mobile
@bloom/ui-mobile — React Native primitives (@rn-primitives, NativeWind-style CVA) and an Expo tsconfig/CI workflow, prepared for a mobile client

06 · Infrastructure & DevOps

Swarm · GitLab CI · ephemeral UAT

07 · Engineering highlights

Eight decisions
An in-house framework, not a framework-shaped folder

Bloom's kernel, plugin lifecycle, DI container and CQRS bus are versioned packages with their own docs, letting six deployables share one composition model.

RLS + AsyncLocalStorage tenancy

Tenant scoping is enforced by the database inside a per-request transaction rather than by query-building convention, so a forgotten where clause cannot leak data across workspaces.

Transactional event dispatch

The event recorder buffers domain events and flushes them only on successful command completion, eliminating the “email sent for a rolled-back write” class of bug.

Custom migration tooling

Validation runs in CI, and rebase resolves the migration-ordering conflicts that plague long-lived branches on a shared Drizzle schema.

Ephemeral per-ticket environments

Full database and identity-provider isolation, provisioned and destroyed by the pipeline.

Postgres-only infrastructure

Queue, KV and pub/sub all ride the primary database, removing Redis and a broker from the operational surface while keeping jobs transactional with the data they touch.

Two-sided email system

A Maily/TipTap drag-and-drop builder for customer campaigns and React Email templates for system mail, both rendered through a shared @bloom/maily-renderer package.

Architecture conventions encoded in the repo

.cursor/rules and .prompts hold the backend and frontend scaffolding rules, so AI-assisted scaffolding conforms to the layering instead of eroding it.

Qollabi smart lists
Qollabi on mobile
Previous: lightnotesNext: Qollabi