npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nestjs-ember-static

v0.3.1

Published

Nest - modern, fast, powerful node.js web framework (nestjs-ember-static)

Readme

Description

The nestjs-ember-static package enhances the Nest framework to serve static Single Page Applications (SPAs) built with Ember. Drawing inspiration from @nestjs/serve-static, this module stands out by offering tailored features for Ember applications.

Why choose this over @nestjs/serve-static? Primarily for its support of live reloading and configuration injection. Designed to facilitate the integration of EmberJS applications within a NestJS mono repository, this module ensures that both front-end and back-end can be accessed through the same port. During development, it preserves the Ember application's live reloading capabilities. Moreover, it provides a feature where the back-end can inject configuration metadata directly into the generated index.html. This functionality makes it ideal for developers seeking a seamless development experience with combined Ember and NestJS applications.

Compatibility

As of v0.3.0, this package supports NestJS 11 + Express 5 (and Fastify).

| nestjs-ember-static | NestJS | Express | path-to-regexp | Node | | --------------------- | ------- | ------- | -------------- | ------- | | >=0.3.0 | 11 | 5 | 8 | >=20 | | <0.3.0 | 9–10 | 4 | 7 | >=18 |

Express and Fastify are declared as optional peer dependencies — install only the adapter you use. NestJS 11's @nestjs/platform-express ships Express 5 by default, so no extra pinning is required.

@nestjs/config is an optional peer dependency. The library no longer imports ConfigModule itself, so it always uses your application's single copy. If your Ember injection helpers or config modifiers inject ConfigService, register ConfigModule globally so it is resolvable inside EmberModule:

ConfigModule.forRoot({ isGlobal: true });

(Alternatively, pass your own imports to EmberModule.forRootAsync({ imports: [...] }).)

What changed in v0.3.0

This release deliberately decouples the library from the application’s Nest runtime. That means the package no longer assumes it owns the app’s Nest instances for core integration points like @nestjs/core or @nestjs/config.

In practical terms:

  • @nestjs/config is now fully owned by the host app. The library no longer imports ConfigModule on your behalf.
  • If your helpers need ConfigService, register ConfigModule globally or pass it through EmberModule.forRootAsync({ imports: [...] }).
  • The Ember loader setup now runs against the already-created Nest app, so the host application controls which Nest versions and adapters are in play.

If you are upgrading from an older version, the safest mental model is: the app creates Nest, and nestjs-ember-static layers Ember behavior onto that app after startup rather than trying to bootstrap Nest internals itself.

Note: v0.3.0 drops Express 4 support. If you still need Express 4 / NestJS 9–10, stay on the 0.2.x line.

Installation

$ pnpm install nestjs-ember-static

Usage

To incorporate the EmberModule into your Nest application, configure it with EmberModule.forRootAsync(...) and return one of these shapes:

  • static mode: { metaTagName, static: { rootPath }, ... }
  • proxy mode: { metaTagName, proxy: { target }, ... }

The library currently uses a single async configuration path for real-world setups. The forRoot() method exists, but does not accept options.

Static Configuration with forRootAsync

Use static.rootPath when Nest should serve a built Ember app from disk:

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { EmberModule, EmberModuleOptions } from 'nestjs-ember-static';
import { join } from 'path';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    EmberModule.forRootAsync({
      useFactory: async (configService: ConfigService): Promise<EmberModuleOptions> => {
        const env = configService.get('env', { infer: true });

        return {
          metaTagName: '@my-ember-app/config/environment',
          static: {
            rootPath:
              env['name'] === 'development'
                ? join(env['appRoot'], '../frontend/dist')
                : join(env['appRoot'], 'client'),
          },
        };
      },
      inject: [ConfigService],
    }),
  ],
})
export class AppModule {}

Proxy Configuration with forRootAsync

Use proxy.target during development when the Ember app is running separately:

import { Module } from '@nestjs/common';
import { EmberModule, EmberModuleOptions } from 'nestjs-ember-static';

@Module({
  imports: [
    EmberModule.forRootAsync({
      useFactory: async (): Promise<EmberModuleOptions> => ({
        metaTagName: '@my-ember-app/config/environment',
        prefix: '/',
        proxy: {
          target: 'http://127.0.0.1:4200',
        },
      }),
    }),
  ],
})
export class AppModule {}

Additional Configuration Injection

For advanced configuration, such as dynamically setting properties or modifying the application title, you can add extra providers within the module. This enhances the module's flexibility and functionality, especially during development:

extraProviders: [
  {
    provide: EMBER_INJECTION_HELPERS,
    useFactory: (configService: ConfigService) => [
      new EmberConfigInjectionHelper('@my-ember-app/config/environment', configService),
      new TitleInjectionHelper('Ember Application'),
    ],
    inject: [ConfigService],
  },
];

By following these configurations, you can effectively integrate and serve your Ember SPA within a NestJS application, leveraging both static and dynamic setup options.

Inject Helpers

To implement custom inject helpers for dynamic configuration, you need to define them by extending an abstract class. They get passes the rootElement from the html document (see node-html-parser for how to mutate that).

export abstract class AbstractInjectionHelper {
  public abstract process(htmlElement: HTMLElement): void;
}

Here's an example of how you can create your own inject helpers:

export class TitleInjectionHelper extends AbstractInjectionHelper {
  constructor(private title: string) {
    super();
  }

  public process(htmlElement: HTMLElement): void {
    htmlElement.querySelector('title')!.textContent = this.title;
  }
}`

Note: The InjectionHelpers given in this library are meant to be implemented by you. These are provided as examples to illustrate how you might structure your own helpers for configuration injection.

Adding Route Guards

The EmberModule supports route guards to control access to your Ember SPA.

To add a route guard, provide a guard into the EmberModule via the extraProviders:

import { Module } from '@nestjs/common';
import { join } from 'path';
import { EMBER_MODULE_GUARD, EmberModule } from 'nestjs-ember-static';
import { ConfigService } from '@nestjs/config';
import { MyCustomGuard } from './guards/my-custom.guard';

@Module({
  imports: [
    EmberModule.forRootAsync({
      extraProviders: [
        {
          provide: EMBER_INJECTION_HELPERS,
          useFactory: (configService: ConfigService) => [
            new EmberClientConfigInjector('@3dlayermaker/device-controller-frontend/config/environment', configService),
          ],
          inject: [ConfigService],
        },
        {
          provide: EMBER_MODULE_GUARD,
          useClass: ControllerApiAuthGuard,
        },
      ],
    }),
  ],
})
export class AppModule {}

The guard will be applied to all routes handled by the EmberModule. The guard should implement the CanActivate interface, and you can control access by implementing the canActivate method.

Development mode

While developing, I typically run both the NestJS application and the EmberJS application simultaneously. My package.json includes a script like:

"start:dev": "concurrently --kill-others 'cd apps/frontend && pnpm run start' 'cd apps/backend && pnpm run start:debug'"

In production, I build the Ember app and point static.rootPath at the built output directory. In development, I usually run the Ember app separately and use proxy.target so Nest forwards SPA requests to the running client.

Backing frameworks Express and Fastify

The nestjs-ember-static module supports both Express and Fastify as backing frameworks. This flexibility allows you to choose the framework that best suits your application's needs and preferences. Whether you are using the default Express or have switched to Fastify for improved performance, the nestjs-ember-static module integrates seamlessly with both, ensuring consistent functionality and easy setup.

However, it's important to note that Fastify has some limitations. For more details on these limitations, refer to the @nestjs/serve-static module documentation. This will help you understand any potential constraints and how they might impact your application when using Fastify as the backing framework.

Public Option Shape

The public configuration currently revolves around these top-level properties:

| Property | Type | Description | | ------------- | -------- | ----------- | | metaTagName | string | Required meta tag name used when injecting Ember config into index.html. | | prefix | string | Optional mount prefix. Defaults to /. | | beautify | object | Optional HTML beautify options for injected output. | | static | object | Static serving mode. Use static.rootPath to point to built Ember assets. | | proxy | object | Proxy mode. Use proxy.target to point at the running Ember dev server. |

static and proxy are mutually exclusive.

Migrating to v0.3.0 (NestJS 11 + Express 5)

v0.3.0 targets NestJS 11, whose @nestjs/platform-express is built on Express 5. Express 5 uses path-to-regexp 8, which changes route-pattern syntax. The bare * wildcard is no longer valid and must be written as a named wildcard:

  • **splat (unnamed segments are no longer allowed)
  • A catch-all render path is now /{*splat} (or /*splat)

The library's default render path already uses the new syntax internally, so most applications need no changes.

If you are upgrading from an older release, note that the old top-level config shape shown in earlier docs is no longer accurate:

  • rootPath is now configured as static.rootPath
  • proxy.target is used for dev-server forwarding
  • renderPath is handled internally by the loader
  • liveReloadOrigin is not part of the current public options interface

For full details see the Express 5 migration guide and the path-to-regexp 8 changes.

Support

Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.

Stay in touch

License

As this is based on serve-static, this module is also licensed under the MIT license.