> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meridian.study/llms.txt
> Use this file to discover all available pages before exploring further.

# Development Guide

> Day-to-day Meridian development: where to run commands, how dev servers fit together, and pointers to platform conventions

<Info>
  **Prerequisite:** Complete [Getting started](/getting-started) (Node 20, MongoDB, `gh`, clone, `npm run setup`, and `.env`) before using this page.
</Info>

## Conventions (read these first)

Product rules and code patterns live in two dedicated guides—this page stays **workflow-oriented** (commands, layout, debugging). When you touch code, start from the right doc:

<CardGroup cols={2}>
  <Card title="Web client best practices" icon="code" href="/frontend/best-practices">
    **`Meridian/frontend/`** — `useFetch`, **`postRequest`** (no direct axios), dev **proxy** to port **5001**, routing, SCSS/Tailwind, and ESLint entrypoints.
  </Card>

  <Card title="Backend best practices" icon="server" href="/backend/best-practices">
    **`Meridian/backend/`** — **`getModels(req, …)`**, **`req.db` / `req.globalDb`**, **`verifyToken`**, org permissions, and how **`events`** routes mount.
  </Card>
</CardGroup>

***

## Monorepo layout

You **clone the Meridian repo** first (`Meridian/` is a real git checkout). **`Events-Backend/`**, **`Meridian-Mobile/`**, and this docs site are **separate** checkouts or folders you place **next to** Meridian on disk when needed. Some teams call that sibling layout **“Meridian-Mono”**—it is a **folder convention**, not something you `git clone` as one repository.

```text theme={null}
workspace/                    # any parent directory (not a git repo)
├── Meridian/                 # clone of Meridian — daily driver for web + API
│   ├── frontend/
│   ├── backend/              # Express entry: server.js
│   │   └── events/           # Symlink → ../Events-Backend when using meridian CLI
│   ├── bin/meridian.js
│   └── package.json          # dev, server, client, test:*
├── Events-Backend/           # private module; sibling of Meridian/ when linked
├── Meridian-Mobile/          # optional: separate Expo / React Native clone
└── Meridian-Mintlify/        # optional: this documentation site
```

Unless a doc says otherwise, run **install, dev, and test commands from `Meridian/`** so `concurrently` and path assumptions match CI and the rest of the team.

***

## Run the app locally

From **`Meridian/`**:

| Script               | What it does                                                                                                                                                                    |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`npm run dev`**    | Runs **`npm run server`** and **`npm run client`** together (see `Meridian/package.json`). Default URLs: **frontend** `http://localhost:3000`, **API** `http://localhost:5001`. |
| **`npm run server`** | **`nodemon`** + `node --preserve-symlinks backend/server.js` — Express API with reload.                                                                                         |
| **`npm run client`** | **`cd frontend && npm start`** — webpack dev server for the React app.                                                                                                          |

**Run API and web separately** (two terminals, still from `Meridian/`):

```bash theme={null}
npm run server
```

```bash theme={null}
npm run client
```

Do **not** rely on `cd Meridian/backend && npm start` — the backend **`package.json`** does not define a `start` script; the supported entry is **`npm run server`** from **`Meridian/`**.

### Custom ports

* **API:** `backend/server.js` uses **`process.env.PORT`** and defaults to **5001**.

  ```bash theme={null}
  PORT=5002 npm run server
  ```

* **Frontend:** the CRA-style dev server respects **`PORT`** when you start the client (from `Meridian/`):

  ```bash theme={null}
  PORT=3001 npm run client
  ```

Keep the frontend **`package.json` `proxy`** target aligned with wherever the API listens (default `http://localhost:5001/`).

***

## Branching and CLI

Use the **[Meridian CLI](/meridian-cli)** for branch names that match automation (for example **`MER-123-short-slug`**), syncing **`Events-Backend`**, and shipping. Install **`gh`** and run **`gh auth login`** (see [Getting started — GitHub CLI](/getting-started#github-cli-gh)) so `meridian ship` can open and merge PRs.

Plain Git is fine for small fixes; for anything touching the private events module or lockfile, follow the CLI doc.

***

## Testing

From **`Meridian/`**:

```bash theme={null}
npm run test:ci          # backend coverage + frontend coverage (matches a large part of CI)
npm run test:backend     # Jest in backend/
npm run test:frontend    # Jest in frontend/
```

See **[Testing](/testing)** for **`test:unit` / `test:integration` / `test:routes`**, folder layout, and how GitHub Actions maps jobs.

***

## Linting

There is **no** root `npm run format` or `npm run type-check` in **`Meridian/package.json`**. Formatting is team/IDE-driven unless you add scripts yourself.

**Frontend** (ESLint config lives in `Meridian/frontend/package.json`):

```bash theme={null}
cd Meridian/frontend && NODE_ENV=development npx eslint src/
```

**Backend:** there is currently **no** `lint` script in `Meridian/backend/package.json`; rely on your editor and the patterns in [Backend best practices](/backend/best-practices) until a shared script exists.

***

## Debugging

### Frontend

* React DevTools in the browser.
* Network tab: confirm requests go to **relative** URLs so the **dev proxy** and **cookies** behave (see [Web client best practices](/frontend/best-practices)).
* Remove stray **`console.log`** before merge.

### Backend

* Logs in the terminal running **`npm run server`**.
* **`debugger`** breakpoints under Node inspect if you use that workflow.
* **`curl` / Postman / Insomnia** against `http://localhost:5001` (or your `PORT`).

### MongoDB

Use **`mongosh`** with the same URI as **`Meridian/backend/.env`** (for example **`MONGO_URI_RPI`** or **`MONGODB_URI`**). See [Getting started — Environment variables](/getting-started#environment-variables) and [Update local database](/update-local-db) for data refresh.

```bash theme={null}
mongosh "mongodb://127.0.0.1:27017/<your-db-name>"
show collections
db.users.find().limit(5)
```

***

## Environment variables

Do **not** commit real **`.env`** files. The repo may not ship a single **`.env.example`** at the repo root—follow **[Getting started — Environment variables](/getting-started#environment-variables)** for which files to create (`Meridian/backend/.env` at minimum) and typical keys (`JWT_SECRET`, Mongo URIs, `NODE_ENV`).

***

## Common issues

<AccordionGroup>
  <Accordion title="Module not found or stale dependencies">
    Reinstall from the package that owns the dependency:

    ```bash theme={null}
    cd Meridian/frontend && rm -rf node_modules && npm install
    cd Meridian/backend && rm -rf node_modules && npm install
    ```

    From **`Meridian/`** you can also reinstall root tooling deps: **`rm -rf node_modules && npm install`**.
  </Accordion>

  <Accordion title="Port already in use (3000 / 5001)">
    **macOS / Linux**

    ```bash theme={null}
    lsof -ti:3000 | xargs kill
    lsof -ti:5001 | xargs kill
    ```

    **Windows (PowerShell)**

    ```powershell theme={null}
    netstat -ano | findstr :3000
    netstat -ano | findstr :5001
    taskkill /PID <pid> /F
    ```
  </Accordion>

  <Accordion title="Database connection errors">
    Confirm MongoDB is running and the URI in **`Meridian/backend/.env`** matches your local database name. **macOS (Homebrew):** `brew services list`. **Windows:** **Services** (`services.msc`) or `net start MongoDB`. See [Getting started — Prerequisites](/getting-started#prerequisites).
  </Accordion>

  <Accordion title="WebSocket or real-time issues">
    Ensure the **API** process is up, the browser is on the same origin/proxy path you expect, and that CORS / cookie settings match how you are hitting the API (see [Web client best practices](/frontend/best-practices)).
  </Accordion>
</AccordionGroup>

***

## Before you open a PR

* Run **`npm run test:ci`** (or at least the suites you touched).
* Follow **`MER-*`** / CLI conventions when your work spans **`Events-Backend`** or the lockfile—see **[Meridian CLI](/meridian-cli)** and **[Deployment](/deployment)**.
* Prefer **conventional commits** (`feat:`, `fix:`, `docs:`) so history stays readable.

***

## Related pages

<CardGroup cols={2}>
  <Card title="Getting started" icon="rocket" href="/getting-started">
    Stack, MongoDB, `gh`, `npm run setup`, and first-run env vars.
  </Card>

  <Card title="Testing" icon="flask" href="/testing">
    Backend vs frontend tests, route-outcomes, and CI alignment.
  </Card>

  <Card title="Web client best practices" icon="code" href="/frontend/best-practices">
    `useFetch`, `postRequest`, proxy, and UI conventions.
  </Card>

  <Card title="Backend best practices" icon="server" href="/backend/best-practices">
    Multi-tenant `req.db`, auth, and route patterns.
  </Card>

  <Card title="Authentication overview" icon="shield" href="/backend/auth/overview">
    How login, JWTs, and cookies line up with the dev proxy.
  </Card>

  <Card title="Multi-tenant identity" icon="users" href="/backend/multi-tenant-identity">
    Subdomains, global DB, and how `req.user` resolves locally.
  </Card>

  <Card title="API reference" icon="book" href="/api-reference/introduction">
    HTTP surfaces the web app calls through `useFetch` / `postRequest`.
  </Card>

  <Card title="Meridian CLI" icon="terminal" href="/meridian-cli">
    Branches, `Events-Backend`, lockfile, and `meridian ship`.
  </Card>
</CardGroup>

For **credentials, tenant Atlas URIs, or production access**, use internal Study Compass engineering channels—not this docs site.
