Serein
Rust로 만든 가볍고 성능 좋은 Discord 전용 네이티브 클라이언트
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Swiss German. Together. zäme is a personal event platform built around the people that matter — not the logistics. Plan your birthday party, coordinate a day trip, share your concert dates, and make sure everyone gets there together. Self-hostable. Open source. Built with love in Bern.README 전문 보기 ↗
Swiss German. Together.
zäme is a personal event platform built around the people that matter — not the logistics. Plan your birthday party, coordinate a day trip, share your concert dates, and make sure everyone gets there together.
Self-hostable. Open source. Built with love in Bern.
.ics download and a live per-person iCal feed so confirmed events land in your calendar automatically.Not built yet — see ROADMAP.md: Fahrgemeinschaft (travel groups + SBB connections), to-do and pack lists, an in-app AI assistant.
| Framework | Nuxt 4 — full-stack, SSR for invite pages |
| UI | Nuxt UI + Tailwind CSS, stock theme |
| Database | PostgreSQL via node-postgres + Drizzle ORM |
| Auth | Better Auth — magic link + passkey, no passwords |
| Files | Any S3-compatible object store — presigned uploads via aws4fetch |
| Proton Bridge via the mail relay, or Resend; React Email templates | |
| Jobs | Inngest — invite, confirmation, reminder, cancellation and bring-list-nudge mail |
| IDs | cuid2 |
| Runtime | Node 22 (engines.node), built with buildpacks — no Dockerfile |
| Install | Web app manifest + a @vite-pwa/nuxt service worker that precaches build assets only — navigations always go to the network, so SSR and Open Graph cards survive |
zäme also publishes a versioned machine API (/api/v1) described by
docs/zaeme-api.openapi.yaml, served at
GET /api/openapi.yaml. See ARCHITECTURE.md.
zäme is a single Nuxt package with no build-time services of its own. It needs a PostgreSQL database and very little else: object storage and a mail transport are both optional, and the app degrades honestly without them rather than failing.
zäme has no passwords. Two ways in, and they fail independently:
On first run /setup claims the instance with a passkey: the first account
created owns it. Manage keys afterwards at /admin/security.
If you are locked out — the account exists but the instance cannot send you
a link — set ZAEME_OWNER_BOOTSTRAP_TOKEN to a random secret
(openssl rand -hex 32), redeploy, and open /setup/recover. Quoting it
registers a passkey on the owner account and nothing else: it is not a session,
it cannot name a different account, and every use is written to the audit log.
Remove the variable once you are back in — /admin/security nags until you
do.
git clone https://github.com/Bermos/zaeme
cd zaeme
pnpm install
# .env.example documents every variable and why it exists.
# DATABASE_URL and BETTER_AUTH_SECRET are the only required ones.
cp .env.example .env
# apply the schema (reads DATABASE_URL)
pnpm db:migrate
pnpm build
node .output/server/index.mjs
The server listens on $PORT (3000 by default). Visit it and zäme will send you
to /setup to claim the instance.
There is deliberately no Dockerfile and no compose file. The upstream
deployment runs on Kitchen with buildpacks,
configured by kitchen.json; migrations run there as a
pre-release migrate task (scripts/migrate.mjs), so a failed migration stops
the deploy instead of half-applying it. Any platform that can run
pnpm build and then node .output/server/index.mjs works the same way — run
the migration step before the new release takes traffic.
Only DATABASE_URL and BETTER_AUTH_SECRET are required.
# Database (required)
DATABASE_URL=postgresql://...
# Auth (required)
BETTER_AUTH_SECRET=your-secret-here
BETTER_AUTH_URL=https://your-domain.com
# Public origin — used for invite links, iCal feeds and the WebAuthn relying
# party. BASE_URL wins, then BETTER_AUTH_URL, then KITCHEN_URL.
BASE_URL=https://your-domain.com
# Object storage (optional; R2_* names are accepted as legacy aliases)
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_BUCKET=
S3_ENDPOINT= # or S3_ACCOUNT_ID for Cloudflare R2
S3_REGION=auto
# Mail (optional). The relay is tried first, then Resend, then a dry run to stdout.
MAIL_RELAY_URL= # or KITCHEN_SERVICE_MAIL, bound by the platform
MAIL_RELAY_TOKEN=
RESEND_API_KEY=
EMAIL_FROM=
# Background jobs (optional; without a key Inngest runs in dev mode)
INNGEST_EVENT_KEY=
# Break-glass passkey registration for a locked-out owner. Unset by default,
# and it should be unset again as soon as you are back in.
ZAEME_OWNER_BOOTSTRAP_TOKEN=
# The machine API (optional). Unset means /api/v1 answers 401 to everyone.
ZAEME_SERVICE_TOKEN=
ZAEME_ENTERPRISE_OWNER_ID=
There are no ENABLE_* feature flags. A capability is on when it is configured:
no storage config means uploads are unavailable, no mail transport means /login
stops offering a magic link and says so, no service token means /api/v1
authenticates nobody.
# install
pnpm install
# dev server
pnpm dev
# database
pnpm db:generate # generate migrations from server/database/schema/
pnpm db:migrate # apply them
# checks
pnpm lint
pnpm typecheck
pnpm test
# smoke tests (need a running server; only smoke:api runs in CI)
pnpm smoke:api # the whole /api/v1 surface, both sides of the credential wall,
# and the shipped service worker, run and asked what it caches
pnpm smoke:passkey # the real WebAuthn ceremony with a software authenticator
# build
pnpm build
One flat package — no pnpm workspace, no packages/*, no Nuxt layers.
zaeme/
app/ Nuxt 4 application (pages, components, layouts)
shared/ code used by both the app and the server
server/
api/
admin/ owner-only, instance-wide
host/ the planner's own events (session)
me/ cross-event view for a signed-in account
invites/ the guest capability surface (the link is the credential)
public/ published events, no credential at all
v1/ the machine API (service token)
auth/ better-auth handler
routes/ non-API routes (.ics feeds, /healthz)
domain/ all domain logic — handlers stay thin
database/
schema/ auth.ts, events.ts, audit.ts, index.ts
migrations/ generated by drizzle-kit
emails/ transports + templates
inngest/ background job definitions
middleware/ audit recorder, first-run setup redirect
utils/ db, auth, admin gate, storage, mail status, …
docs/
zaeme-api.openapi.yaml the machine API contract (source of truth)
public/
icons/ home-screen icons (generated, committed)
scripts/ migrate, API smoke, passkey smoke, icon + worker tools
test/ vitest — contract and boundary tests live here
kitchen.json build + runtime configuration
See ROADMAP.md for the full task list.
zäme is not a startup. It’s a tool built for a specific kind of person — someone who organizes real things with real friends and wants something that feels personal, not like a SaaS product.
It is open source because others might find it useful.
MIT