Skip to content

Run Musubi locally

This is the shortest reliable path from a fresh clone to a working development environment. It deliberately separates the backend, docs, and native client so you can run only the layer you are changing.

Tool Version / notes
Node.js 22.12 or newer. Astro 7 requires it.
pnpm Use Corepack; the root manifest activates exactly [email protected].
PostgreSQL 15+ locally, or Docker. The bundled Compose stack uses PostgreSQL 17.
Git Any recent version.
Native client Android Studio for Android; Xcode on macOS for iOS; or an EAS development build.
  1. Clone and install the pinned workspace.

    Terminal window
    git clone https://github.com/frgtn-dot-dev/musubi.git
    cd musubi
    corepack enable
    pnpm install --frozen-lockfile

    package.json at the repository root is the only package-manager version source. Do not install a separate global pnpm or add package-local packageManager fields.

  2. Create the local environment file.

    Terminal window
    cp .env.example .env

    For a minimal local stack, set:

    POSTGRES_USER=musubi
    POSTGRES_DB=musubi
    POSTGRES_PASSWORD=local-development-only
    DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}
    API_SERVER_PORT=7531
    ENVIRONMENT=dev
    BETTER_AUTH_URL=http://localhost:7531
    BETTER_AUTH_SECRET=replace-with-a-long-random-value

    Generate secrets instead of inventing production values:

    Terminal window
    openssl rand -base64 32 # BETTER_AUTH_SECRET
    openssl rand -hex 32 # CALDAV_ENC_KEY, when testing CalDAV/federation

    See Environment variables for every setting, feature gate, and rotation consequence.

  3. Start PostgreSQL.

    Terminal window
    docker compose up -d db
    docker compose ps
  4. Apply every server migration.

    Terminal window
    pnpm db:migrate

    Migrations live in packages/db/drizzle/ and are applied in journal order.

  5. Start the API and verify it.

    Terminal window
    pnpm --filter @musubi/api dev

    In a second terminal:

    Terminal window
    curl http://localhost:7531/api/v1/server/ok
    # {"ok":true}
  6. Start the documentation site.

    Terminal window
    pnpm docs:dev

    Open http://localhost:4321/docs/.

  7. Build and start the native client.

    Connect a device with USB debugging or start an emulator, then run:

    Terminal window
    pnpm --filter @musubi/client android

    The first run generates the ignored native project and installs a development build. Later JavaScript-only sessions can use:

    Terminal window
    pnpm --filter @musubi/client start

localhost means different things depending on where the client runs:

Client API URL to enter on the welcome screen
iOS simulator http://localhost:7531
Android emulator http://10.0.2.2:7531
Physical phone http://<your-computer-LAN-IP>:7531

For a physical phone, the computer and phone must be on the same network. Set BETTER_AUTH_URL to that same LAN origin before starting the API, for example http://192.168.1.42:7531. Run the client with pnpm --filter @musubi/client start; the workspace-wide pnpm dev uses the client’s localhost-only Metro mode and is best suited to simulators.

Once each layer works independently:

Terminal window
pnpm dev

Turborepo starts every workspace that declares dev and displays the API, client, and docs in a terminal UI. Use stream output when logs need to be copyable:

Terminal window
pnpm exec turbo run dev --ui=stream

Before editing code, establish the same baseline contributors use:

Terminal window
pnpm check

This first validates release/toolchain metadata and peer dependencies, then runs client + API typechecks, the twelve existing assertion-based self-checks, client lint, and the docs build. Lint has zero errors and a locked budget for 108 known React Compiler/hook warnings; a net increase fails the command. The remaining migration is recorded in the codebase audit.

Use this five-minute smoke flow before beginning onboarding:

  1. Enter the local server URL and create an email/password account.
  2. Finish onboarding and rename the auto-created personal calendar.
  3. Create a second calendar and an event.
  4. Edit the event, enable attendees, and move it in day view.
  5. Restart the app and confirm cached calendars/events render before refresh.

Continue with Codebase Onboarding and trace those actions through the client, API, database, provider boundary, and SSE echo.