Skip to content

Repository files navigation

emsa

A self-hosted member platform for organizations.

Members, projects, pillars, and organisational info — one app, one process, your brand.

License: MIT Bun PostgreSQL PRs Welcome

Features · Quick Start · Make It Yours · Deployment · Contributing

Home page

Originally built for EMSA Macedonia (European Medical Students' Association), now open source. The name, logo, brand color, and labels are all configurable — any organization can run it as its own.

Features

  • Public site — landing page, project pages with image galleries, organisational pillars, board positions, and a scrolling supporter logo strip, all editable from the admin panel
  • Members — email/password and Google OAuth login, profiles with avatars, admin-defined custom profile fields with a completion gate
  • Projects — registration windows, participant caps, self-service sign-up, attendance tracking
  • RolesUSERADMINSUPER_ADMIN, enforced server-side; the first registered account becomes the instance owner
  • Rebrandable — organization name, logo, tagline, socials, and even the "pillars" label (call them committees, departments, chapters, ...) are editable at runtime
  • Self-contained — a single Bun process serves both the API and the React SPA; images upload straight to any S3-compatible storage via presigned URLs
Projects page

Tech Stack

Bun · React 19 + React Router v7 · Tailwind CSS v4 + shadcn/ui · TanStack Query · React Hook Form + Zod · Drizzle ORM + PostgreSQL · Tiptap · Motion · JWT + Google OAuth · Cloudflare R2 (or any S3-compatible storage) · Resend

Quick Start

You'll need Bun >= 1.3.14 and a PostgreSQL database. For the full experience also grab an S3-compatible bucket (e.g. Cloudflare R2), Google OAuth credentials, and a Resend API key.

git clone https://github.com/AtanasovskiPetar/emsa.git
cd emsa
bun install

cp .env.example .env       # fill in your values — validated at startup in src/lib/env.ts

bunx drizzle-kit migrate   # apply database migrations
bun dev                    # http://localhost:3000

Register your first account — on a fresh install it automatically becomes SUPER_ADMIN, so the instance has an owner from day one.

For production:

bun run build
bun start

Make It Yours

Almost everything is configured at runtime from the Organization admin page: name, logo, tagline, description, socials, board positions, supporters, custom member fields, and the label used for pillars.

The only code change for a full rebrand is the brand color (default: red), in two places:

  1. styles/globals.css — the --primary and --sidebar-primary token pairs in both the :root and .dark blocks
  2. src/lib/email.ts — the theme object used by transactional email templates

Deployment

A production Dockerfile is included. There's also a complete Pulumi setup that provisions a Hetzner VPS with Traefik and deploys per-environment with Docker Compose — batteries included, but entirely optional.

Contributing

Contributions are welcome! To get set up:

bun install
bun dev            # dev server with hot reload
bun run lint       # ESLint
bun run prettier   # format

The codebase conventions live in CLAUDE.md — worth a skim before opening a PR.

Acknowledgements

A significant portion of this codebase was built with the assistance of Claude (Anthropic). All generated code has been reviewed, tested, and adapted to fit the project's requirements.

License

MIT

About

Self-hosted member platform for organizations — members, projects, pillars, and org info in one place.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages