---
auto_generated: true
created: 2026-05-18
manual_updated_at: 2026-05-18
modified: 2026-05-18
name: Developer_Manual
status: active
tags:
- tech/nextjs
- tech/node
- tech/sqlite
type: sop
---

# 3M OMG Portal Developer Manual

## Architecture Overview

The 3M OMG Portal is a Node.js application serving both static frontend files and API endpoints. It communicates with the One2Edit service via a proxy and uses SQLite for local storage of sessions, tokens, and user data.

### High-Level Flow

```
Browser  →  /api/auth/*        →  lib/routes/auth.js
Browser  →  /api/admin/*       →  lib/routes/admin.js
Browser  →  /api               →  lib/proxy.js  →  One2Edit API (requires auth)
Browser  →  static files       →  login.html, dashboard.html, editor.html, admin.html …
```

## Tech Stack

- **Runtime**: Node.js (vanilla HTTP, no framework)
- **Database**: SQLite (via file-based storage in `DATA_DIR`)
- **Authentication**: Email/password with HttpOnly cookies
- **Email Service**: Mailgun
- **Frontend**: Vanilla HTML/CSS/JS

## Local Setup

1. **Clone the repository**
2. **Copy environment variables**:
   ```bash
   cp .env.example .env
   ```
3. **Fill in required values** in `.env`:
   - `SERVICE_USERNAME` and `SERVICE_PASSWORD` (One2Edit service account)
   - `INITIAL_ADMINS` (optional, for bootstrapping)
4. **Install dependencies**:
   ```bash
   npm install
   ```
5. **Start the server**:
   ```bash
   npm start
   ```
6. **Access the app** at [http://localhost:3000](http://localhost:3000)

## Environment Variables

| Variable             | Description                                                                 |
|----------------------|-----------------------------------------------------------------------------|
| `SERVICE_USERNAME`   | One2Edit service account email                                              |
| `SERVICE_PASSWORD`   | One2Edit service account password                                           |
| `PORT`               | HTTP port (default 3000)                                                    |
| `APP_BASE_URL`       | Public base URL used in email links                                         |
| `DATA_DIR`           | Directory for SQLite DB (default `./data`)                                  |
| `COOKIE_NAME`        | Session cookie name (default `portal_session`)                              |
| `COOKIE_SECURE`      | Set `false` for local http dev, `true` for prod                           |
| `SESSION_TTL_MS`     | Session lifetime in ms (default 28800000 = 8h)                             |
| `INITIAL_ADMINS`     | JSON array of admins to seed on first boot                                 |
| `MAILGUN_API_KEY`    | Mailgun API key                                                             |
| `MAILGUN_DOMAIN`     | Mailgun sending domain                                                      |
| `MAILGUN_FROM`       | From address for emails                                                     |

### `INITIAL_ADMINS` Format

```json
[
  {"email":"admin@example.com","one2editUsername":"firstname.lastname","password":"strongpassword"},
  {"email":"admin2@example.com","one2editUsername":"firstname2.lastname2","password":"strongpassword2"}
]
```

> **Note**: Delete `INITIAL_ADMINS` from `.env` after the first login and password change.

## Key Services & Entry Points

- **`server.js`**: Main entry point. Loads `.env`, bootstraps the database, sets up routing, and serves static files.
- **`lib/db.js`**: Handles database initialization and admin bootstrapping.
- **`lib/session.js`**: Manages session creation, validation, and cleanup.
- **`lib/tokens.js`**: Manages password reset and invitation tokens.
- **`lib/proxy.js`**: Proxies requests to the One2Edit API.
- **`lib/routes/auth.js`**: Handles login, logout, password reset, and invitation flows.
- **`lib/routes/admin.js`**: Handles admin-specific user management routes.

## API Reference

### Auth Endpoints

- `POST /api/auth/login`: Logs in a user.
- `POST /api/auth/forgot-password`: Sends a password reset email.
- `POST /api/auth/reset-password`: Resets password using a token.
- `POST /api/auth/invite-info`: Validates an invitation token.
- `POST /api/auth/accept-invite`: Accepts an invitation and creates an account.
- `GET /api/auth/me`: Returns current user session info.

### Admin Endpoints

- `GET /api/admin/users`: Lists all users.
- `POST /api/admin/users/:id`: Updates a user.
- `DELETE /api/admin/users/:id`: Deletes a user.

## Deployment

1. Set `COOKIE_SECURE=true` in production.
2. Ensure `SERVICE_USERNAME` and `SERVICE_PASSWORD` are configured.
3. Use a reverse proxy (e.g., Nginx) for HTTPS.
4. Run `npm start` or use a process manager like PM2.

## Known Gotchas

- **`INITIAL_ADMINS`**: Must be removed from `.env` after first use to avoid re-creating accounts.
- **`COOKIE_SECURE`**: Must be `true` in production to ensure HTTPS-only cookies.
- **Password Policy**: Passwords must be at least 10 characters.
- **Session Cleanup**: Expired sessions and tokens are cleaned up hourly. Ensure the server stays up or manually trigger cleanup if needed.

## Related
- [[3M OMG Portal Project Overview]]