Running WindoM locally
Option A - Extension Only Recommended to start#
This gets the extension running in Chrome with no backend needed. Clock, weather, todos, backgrounds, quotes, quick links, and the focus timer all work out of the box. Google Calendar and Spotify require the full stack setup below.
Prerequisites#
- Node.js 18 or higher
- Google Chrome
- Git
Steps#
Clone the repository.
git clone https://github.com/YehudaBriskman/WindoM.git cd WindoMInstall dependencies for the extension.
cd web npm installBuild the extension.
npm run buildThis creates a web/dist/ folder - that is your built extension.
Load the extension in Chrome.
- Open Chrome and go to
chrome://extensions - Enable Developer mode (toggle in the top right)
- Click Load unpacked
- Select the
web/distfolder
Open a new tab. WindoM should appear.
npm run dev instead of build, then load the web/ project root folder (not dist/) as the unpacked extension at chrome://extensions. Changes reload automatically via HMR.Option B - Full Stack Optional#
Required if you want Google Calendar sync or Spotify integration. This runs a local backend with a Postgres database using Docker.
Prerequisites#
- Everything from Option A
- Docker Desktop
- A Google Cloud project with OAuth credentials (for Calendar)
- A Spotify Developer app (for Spotify)
Steps#
Copy the example environment file.
cp backend/.env.example backend/.envThen open backend/.env and fill in the values. See the Environment Reference below for what each one means.
Generate secure secrets for JWT and token encryption.
node -e "const c=require('crypto'); console.log('JWT_ACCESS_SECRET='+c.randomBytes(32).toString('base64')); console.log('REFRESH_TOKEN_SECRET='+c.randomBytes(32).toString('base64')); console.log('TOKEN_ENC_KEY_BASE64='+c.randomBytes(32).toString('base64'));"Copy the output into your .env file.
Start the backend and database with Docker.
docker-compose up --buildThe API will be running at http://localhost:8080. The database runs at port 5433.
Build the extension pointing at your local backend.
cd web npm install npm run buildThe default backend URL is already http://localhost:8080 so no changes are needed.
Load web/dist as an unpacked extension in Chrome (same as Option A, step 4).
- Google Cloud Console → Authorized redirect URIs:
http://localhost:8080/auth/google/callbackhttp://localhost:8080/oauth/google/callback - Spotify Developer Dashboard → Redirect URIs:
http://localhost:8080/oauth/spotify/callback
Environment Reference#
All variables go in backend/.env. The ones marked optional are only needed for specific features.
| Variable | Description | Required |
|---|---|---|
PORT | Port the backend listens on. Default: 8080 | No |
DATABASE_URL | Postgres connection string. When using Docker Compose this is set automatically. | Yes |
JWT_ACCESS_SECRET | Random secret used to sign access tokens. Generate with openssl rand -base64 32 | Yes |
REFRESH_TOKEN_SECRET | Random secret used to sign refresh tokens. Generate separately from the above. | Yes |
TOKEN_ENC_KEY_BASE64 | 32 random bytes base64-encoded. Used to encrypt OAuth tokens at rest. | Yes |
GOOGLE_CLIENT_ID | OAuth 2.0 Client ID from Google Cloud Console. | For Google features |
GOOGLE_CLIENT_SECRET | OAuth 2.0 Client Secret from Google Cloud Console. | For Google features |
GOOGLE_REDIRECT_URI | Callback URL for Google Sign-in. Example: http://localhost:8080/auth/google/callback | For Google features |
GOOGLE_OAUTH_REDIRECT_URI | Callback URL for Google Calendar OAuth. Example: http://localhost:8080/oauth/google/callback | For Calendar |
SPOTIFY_CLIENT_ID | Client ID from your Spotify Developer app. | For Spotify |
SPOTIFY_CLIENT_SECRET | Client Secret from your Spotify Developer app. | For Spotify |
SPOTIFY_REDIRECT_URI | Callback URL for Spotify OAuth. Example: http://localhost:8080/oauth/spotify/callback | For Spotify |
CORS_ALLOWED_ORIGINS | Comma-separated list of allowed origins. Include your extension ID and localhost ports. | Yes |
EXTENSION_REDIRECT_BASE | The chromiumapp.org URL for your extension. Used as the OAuth redirect base for the Chrome identity flow. | For Google features |
SMTP_HOST | SMTP server. Defaults to smtp.gmail.com, so leaving it unset preserves the Gmail behaviour. Any provider works - Resend is smtp.resend.com, Brevo is smtp-relay.brevo.com. | No |
SMTP_PORT | Defaults to 465, which uses implicit TLS. Port 587 negotiates STARTTLS instead; the code follows the port, so the two stay consistent. | No |
SMTP_USER | SMTP username. Not required to be an email address - several providers use a plain login, such as the literal resend. If this and SMTP_PASS are unset, emails are printed to the console instead of sent. | No |
SMTP_PASS | 16-character Google App Password for the SMTP account. Generate at myaccount.google.com → Security → 2-Step Verification → App Passwords. | No |
FROM_EMAIL | The "From" address shown on outbound emails. Defaults to noreply@windom.app. On Gmail it must be SMTP_USER or a verified alias of it; dedicated providers only require the domain to be verified with them. | No |
APP_URL | Public base URL of the backend. Used to build email verification and password-reset links. Example: http://localhost:8080. | No |
chrome://extensions. The ID is shown under the extension name. Use it in CORS_ALLOWED_ORIGINS as chrome-extension://YOUR_ID and in EXTENSION_REDIRECT_BASE as https://YOUR_ID.chromiumapp.org.Example .env for local development#
docker-compose up, the DATABASE_URL is automatically overridden to point to the db container (port 5432 internally). You only need to set it manually if you run the backend directly on your host, in which case use port 5433 - the host-mapped port Docker Compose exposes.PORT=8080
NODE_ENV=development
DATABASE_URL=postgresql://windom:windom@localhost:5433/windom
JWT_ACCESS_SECRET=your-generated-secret-here
REFRESH_TOKEN_SECRET=your-other-generated-secret-here
TOKEN_ENC_KEY_BASE64=your-generated-key-here
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=http://localhost:8080/auth/google/callback
GOOGLE_OAUTH_REDIRECT_URI=http://localhost:8080/oauth/google/callback
SPOTIFY_CLIENT_ID=your-spotify-client-id
SPOTIFY_CLIENT_SECRET=your-spotify-client-secret
SPOTIFY_REDIRECT_URI=http://localhost:8080/oauth/spotify/callback
CORS_ALLOWED_ORIGINS=chrome-extension://YOUR_EXTENSION_ID,http://localhost:3000,http://localhost:5173
EXTENSION_REDIRECT_BASE=https://YOUR_EXTENSION_ID.chromiumapp.org
# Email - optional. If omitted, verification/reset emails are printed to the console.
# SMTP_USER=you@yourdomain.com
# SMTP_PASS=your-16-char-app-password
# FROM_EMAIL=noreply@windom.app
# APP_URL=http://localhost:8080