Share Interfaces between Angular and Node Applications easily using Nx

Yannick Haas
medialesson
Published in
3 min readApr 2, 2024

--

This is part of a multi-post series detailing how to consume environment variables in an Angular application, replacing the traditional environment.ts files. The other posts can be found here:

Let’s assume you want to create a simple API, which hosts a few different endpoints, and you want to fetch the data with an Angular application. You can either create two standalone repositories for this, which will have to be kept in sync, if the API changes or you could use Nx to combine them in a monorepo with shared interfaces for your API.

But how exactly can you do that? It’s actually quite easy when using Nx as it configures everything for you!

Creating the workspace and adding the projects

First of all we have to initialize our workspace. I chose angular-environment-variables as my project’s name:

# Create new nx workspace
npx create-nx-workspace angular-environment-variables

The following prompts I answered with:

✔ Which stack do you want to use? · angular
✔ Integrated monorepo, or standalone project? · integrated
✔ Application name · angular-environment-variables
✔ Which bundler would you like to use? · esbuild
✔ Default stylesheet format · scss
✔ Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? · No
✔ Test runner to use for end to end (E2E) tests · playwright
✔ Enable distributed caching to make your CI faster · No

Important: If you chose yes in the last step, information about your build will be uploaded to Nx Cloud. This information is publicly accessible until you’ve claimed it. More information and how to claim it here.

You can of course choose whatever you want here. However, I highly suggest using an integrated monorepo as it only contains a single package.json instead of the multiple JSONs used otherwise.

This already created our Angular application inside the folder apps . So we only need to add the project for the Node application, which I’ll be calling “Runtime Host”. We do this by executing the following commands inside the folder of our newly created project:

# Add required packages (schemas)
npm install -D @nx/node
# Generate Runtime Host project
nx generate @nx/node:application --name runtime-host --directory apps/runtime-host --framework express
# Generate library for app-configuration
nx generate @nx/node:lib --name app-configuration --directory libs/app-configuration

Now your project’s structure should look something like this:

├── apps
│ ├── angular-environment-variables
│ ├── angular-environment-variables-e2e
│ ├── runtime-host
│ └── runtime-host-e2e
└── libs
└── app-configuration

Adding the shared interface

We already created the library app-configuration . We’ll replace the contents of libs/app-configuration/src/lib/app-configuration.ts with our interface:

export interface AppConfiguration {
apiUrl: string | null;
backgroundColor: string | null;
angularEnvironment: 'development' | 'production';
}

Why did I add the type null ?
In case we don’t have an environment variable set for a property, we want to set null . This is to distinguish between an environment variable that simply doesn’t exist and an error during the request, where it and possibly the whole object will be undefined instead. That way we can add a user-facing error page later, which will then be able to provide the information where the error occurred instead of only saying “Oops, something went wrong”.

And that’s it! We can now use the interface defined in the library in both Node and Angular by importing it with:

import { AppConfiguration } from '@angular-environment-variables/app-configuration';

That way your API interfaces will never be different from each other. Furthermore, if it changes substantially, you’ll get a build error before the application is even deployed. No more undefined in your views!

--

--