Environment Configuration
Relevant source files
The following files were used as context for generating this wiki page:Environment configuration in the ever-rec project is managed on a per-application basis within the monorepo structure. Each primary application (api, portal, extensions) has its own set of environment variables, defined in .env files. This approach allows for tailored configurations for different deployment environments (e.g., development, production) and services.
The configuration process relies on template files (.env.sample) which must be copied to create environment-specific files (e.g., .env.dev, .env.prod, .env.local). These variables are then loaded and consumed by the applications at runtime or during the build process, particularly for the browser extension which uses Webpack to inject values.
General Setup
Each application that requires environment variables includes a .env.sample file. To configure an environment, you must copy this sample file to a new file corresponding to the environment you are setting up.
For example, to set up the API for development, you would run:
cp apps/api/.env.sample apps/api/.env.dev
Sources: README.md:154-158
The following diagram illustrates the general process for setting up environment files.
Sources: README.md:154-199
API Server Configuration (apps/api)
The NestJS API server uses the @nestjs/config module to manage environment variables. This allows for a structured way to access configuration values throughout the application.
Sources: apps/api/src/main.ts:1, 12
Environment Files
The API server uses distinct files for development and production:
apps/api/.env.devfor development.apps/api/.env.prodfor production.
Sources: README.md:156-161
Required API Variables
The following variables are required for the API server to function correctly.
| Variable | Description |
|---|---|
FIREBASE_API_KEY | Firebase project API key. |
FIREBASE_AUTH_DOMAIN | Firebase project authentication domain. |
FIREBASE_DATABASE_URL | Firebase Realtime Database URL. |
FIREBASE_PROJECT_ID | Firebase project ID. |
FIREBASE_STORAGE_BUCKET | Firebase Storage bucket URL. |
FIREBASE_MESSAGING_SENDER_ID | Firebase Cloud Messaging sender ID. |
FIREBASE_APP_ID | Firebase application ID. |
FIREBASE_MEASUREMENT_ID | Firebase measurement ID for Google Analytics. |
FIREBASE_ADMIN_PRIVATE_KEY | Private key for the Firebase Admin SDK service account. |
FIREBASE_ADMIN_CLIENT_EMAIL | Client email for the Firebase Admin SDK service account. |
EXTENSION_ID | The ID of the associated browser extension. |
JIRA_CLIENT_ID | Client ID for Jira OAuth integration. |
JIRA_CLIENT_SECRET | Client Secret for Jira OAuth integration. |
TRELLO_KEY | API Key for Trello integration. |
API_BASE_URL | The base URL of the API server itself. |
WEBSITE_URL | The URL of the frontend web portal. |
API_PORT | The port on which the API server will listen. |
Sources: README.md:163-178, apps/api/src/services/atlassian/atlassian.api.service.ts:33-41, apps/api/src/main.ts:38-44
Consumption in Code
The ConfigService is injected into various services and modules to retrieve these values.
This diagram shows how the ConfigService provides configuration to different parts of the API.
For example, in main.ts, the ConfigService is used to set up CORS and determine the listening port:
// File: apps/api/src/main.ts:12, 38-44
const configService: ConfigService = app.get(ConfigService);
// ...
app.enableCors({
origin: [configService.get<string>('WEBSITE_URL')],
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true,
});
const port = configService.get<string>('API_PORT') || 3000;
Similarly, AtlassianApiService retrieves credentials for Jira and Trello integrations:
// File: apps/api/src/services/atlassian/atlassian.api.service.ts:33-41
constructor(
private readonly configService: ConfigService,
//...
) {
this.clientId = this.configService.get<string>('JIRA_CLIENT_ID');
this.clientSecrete = this.configService.get<string>('JIRA_CLIENT_SECRET');
this.baseURL = this.configService.get<string>('API_BASE_URL');
this.websiteUrl = this.configService.get<string>('WEBSITE_URL');
//...
this.trelloKey = this.configService.get<string>('TRELLO_KEY');
}
Web Portal Configuration (apps/portal)
The web portal, built with Next.js, also uses an environment file for its configuration.
Environment File
apps/portal/.env.localis used for local development.
Sources: README.md:182-184
Required Portal Variables
| Variable | Description |
|---|---|
NEXT_PUBLIC_API_BASE_URL | Base URL for the backend API server. |
NEXT_PUBLIC_WEBSITE_URL | The public URL of the web portal itself. |
NEXT_PUBLIC_STATIC_FILES_URL | URL for static assets. |
EXTENSION_ID | The ID of the associated browser extension. |
Sources: README.md:186-192
Consumption in Code
These variables are consumed by the Next.js application. For example, next.config.js uses them to configure image domains and URL rewrites.
// File: apps/portal/next.config.js:23-37
const nextConfig = {
//...
images: {
domains: ['storage.googleapis.com', 'lh3.googleusercontent.com'],
},
//...
async rewrites() {
return [
{
source: '/fonts/:path*',
destination: 'https://api.rec.so/fonts/:path*', // This would typically be an env variable
},
];
},
};
Note: The hardcoded URL in rewrites would typically be replaced by an environment variable for flexibility.
Browser Extension Configuration (apps/extensions)
The browser extension's configuration is managed via Webpack, which injects environment variables during the build process. This is crucial for creating different builds for development and production.
Environment Files
apps/extensions/.env.devfor development.apps/extensions/.env.prodfor production.
Sources: README.md:195-200, apps/extensions/webpack.dev.js:7
Required Extension Variables
| Variable | Description |
|---|---|
EXTENSION_ID | The unique ID for the browser extension. |
API_BASE_URL | Base URL for the backend API server. |
WEBSITE_URL | The public URL of the web portal. |
STATIC_FILES_URL | URL for static assets. |
Sources: README.md:202-207
Build Process Integration
The extension's Webpack configuration is set up to handle environment variables for different targets.
This diagram shows how Webpack processes environment variables for the extension.
Key components of this process:
webpack.dev.js: This file merges with the basewebpack.config.jsand specifies the development mode. It usesdotenv-webpackto load variables from the appropriate.env.{target}file.// File: apps/extensions/webpack.dev.js:5, 13-17 const target = 'dev'; // ... module.exports = merge(config, { // ... plugins: [ new DotenvPlugin({ path: `./.env.${target}`, }), ], });webpack.config.js:- It uses
CopyPluginto process and copy files likemanifest.jsonand various HTML files. - A
transformManifestfunction uses Handlebars to inject theversionfrompackage.jsoninto themanifest.jsonfile.
// File: apps/extensions/webpack.config.js:342-348 function transformManifest(content) { const template = Handlebars.compile(content.toString('utf8')); const name = process.env.EXTENSION_NAME; const manifest = JSON.parse(template({ name, version })); return JSON.stringify(manifest, null, 2); }- A
transformHtmlfunction usesejsto render environment variables (made available byDotenvPlugin) into the HTML files.
// File: apps/extensions/webpack.config.js:350-354 function transformHtml(content) { return require('ejs').render(content.toString(), { ...process.env, }); }- The SASS loader is also configured to receive the
STATIC_FILES_URLvariable, making it available within SCSS files.// File: apps/extensions/webpack.config.js:110-112 options: { additionalData: `$static-url: ${JSON.stringify( process.env.STATIC_FILES_URL, )};`, },
- It uses
This build-time injection ensures that the correct API endpoints and configuration values are baked into the extension files for each specific environment.