Skip to main content

Adding a Feature Library

Feature libraries encapsulate domain-specific functionality (login, tickets, products, etc.) and are consumed by the applications (unpispas-pos, upp-test). This guide walks through creating a new feature from scratch.

Existing Features

The monorepo already includes these feature libraries under libs/feature/:

FeaturePathModule
Loginlibs/feature/login/FeatureLoginModule
Ticketlibs/feature/ticket/FeatureTicketModule
Productlibs/feature/product/FeatureProductModule
Placelibs/feature/place/FeaturePlaceModule
Categorylibs/feature/category/FeatureCategoryModule
Employeelibs/feature/employee/FeatureEmployeeModule
Userlibs/feature/user/FeatureUserModule
Offerlibs/feature/offer/FeatureOfferModule
Extralibs/feature/extra/FeatureExtraModule
QR Codelibs/feature/qrcode/FeatureQrcodeModule
Assetslibs/feature/assets/FeatureAssetsModule
Top Barlibs/feature/topbar/FeatureTopbarModule
Periodlibs/feature/period/FeaturePeriodModule
Shortcutlibs/feature/shortcut/FeatureShortcutModule

Step 1 — Generate the Library

Use the Nx generator to scaffold the library:

npx nx generate @nx/angular:library \
--name=feature-<name> \
--directory=libs/feature/<name> \
--importPath=@unpispas/feature-<name> \
--prefix=upp \
--style=scss \
--standalone=false

This creates the standard structure:

libs/feature/<name>/
├── src/
│ ├── lib/
│ │ └── feature-<name>.module.ts
│ ├── components/
│ │ └── <component>/
│ │ ├── upp-<component>.ts
│ │ ├── upp-<component>.html
│ │ └── upp-<component>.scss
│ ├── index.ts
│ └── test-setup.ts
├── project.json
├── tsconfig.json
├── tsconfig.lib.json
└── tsconfig.spec.json

Step 2 — Set Up the Module

The module follows a consistent pattern. Import the shared modules and declare your components:

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';

import { UppBaseModule } from '@unpispas/upp-base';
import { UppWdgtModule } from '@unpispas/upp-wdgt';
import { UppDataModule } from '@unpispas/upp-data';

import { MyPageComponent } from '../components/my-page/upp-my-page';
import { MyFeatureComponent } from '../components/my-feature/upp-my-feature';

@NgModule({
declarations: [
MyPageComponent,
MyFeatureComponent,
],
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
IonicModule,
UppBaseModule,
UppWdgtModule,
UppDataModule,
],
exports: [
MyFeatureComponent,
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class FeatureMyFeatureModule {}

Key conventions

  • Import UppBaseModule, UppWdgtModule, and UppDataModule as needed.
  • Only export the components that consuming apps need to use directly.
  • Use CUSTOM_ELEMENTS_SCHEMA for Ionic web-component selectors.

Step 3 — Create Components

Place each component in its own folder under src/components/:

src/components/my-page/
├── upp-my-page.ts
├── upp-my-page.html
└── upp-my-page.scss

Follow the naming convention: prefix with upp-, separate the template and styles into .html and .scss files.

Step 4 — Export from index.ts

The barrel file re-exports the module and any public components:

export * from './lib/feature-my-feature.module';
export * from './components/my-feature/upp-my-feature';

Step 5 — Import in the Application

In the consuming app module (e.g. unpispas-pos):

import { FeatureMyFeatureModule } from '@unpispas/feature-my-feature';

@NgModule({
imports: [
FeatureMyFeatureModule,
// ...
],
})
export class AppModule {}

Step 6 — Routing (if applicable)

If the feature has navigable pages, add routes in the application's routing module that point to the feature's page components.

Feature Structure Convention

A well-structured feature library follows this layout:

libs/feature/<name>/
├── src/
│ ├── lib/
│ │ └── feature-<name>.module.ts ← NgModule declaration
│ ├── components/
│ │ ├── <name>/ ← Main feature component (exported)
│ │ │ ├── upp-<name>.ts
│ │ │ ├── upp-<name>.html
│ │ │ └── upp-<name>.scss
│ │ └── <name>-page/ ← Page-level component (internal)
│ │ ├── upp-<name>.ts
│ │ ├── upp-<name>.html
│ │ └── upp-<name>.scss
│ ├── index.ts ← Barrel exports
│ └── test-setup.ts

Keep reusable logic in the shared libraries (upp-base, upp-data, upp-wdgt); feature libraries should be thin wrappers that compose UI from shared widgets and connect to data services.