Architecture

This page covers general system architecture and code organization.

  1. Most code should be placed in library projects under libs/, even if it isn't shared. App projects are very lean, creating an "environment" or a "shell" necessary for the app to function. App projects are tasked only with importing and glueing together all required library project modules and handling static assets which cannot be packaged and imported from a library project. The library projects are your real code. See this explanation by the Nx creator: https://www.youtube.com/watch?v=qYNiOKDno_I&t=395s).

  2. Apps configure dependency injection and wire up libraries. They should not contain components, services, or business logic. Libs contain services, components, utilities, etc. They have well-defined public API. A typical Nx workspace has many more libs than apps, so pay especially careful attention to the organization of the libs directory.

  3. The code in each library project should follow the Single Responsibility principle. Opt for having more library projects vs. adding more than one responsibility into the same library.

  4. The goal of the barrel index.ts is to define the public API of the library. Anything else is non-public, considered private/hidden and cannot be directly accessed.

  5. Application-specific libraries go in the directory matching the application name (e.g. libs/api/... or libs/web/...)

  6. Local TypeScript imports (same app or same lib) must be relative, starting with ./ or ../. External imports start with '@solomon/...' path prefix generated by Nx in the root tsconfig.base.json file.

    // Local imports
    import { logger } from './logger.middleware'
    
    // External import (from another app or lib project)
    import { ApiAppModule } from '@solomon/apps/api'
    import { DisputeApi } from '@solomon/web/data-access-api'
    import { Role } from '@solomon/shared/util-auth'
    
  7. Nx enforces dependency rules by scope and by library type. See Nx Library Types and Dependencies (Frontend) example for the frontend. Most of this applies to the other app types as well, except app specific libs like "UI" maybe.

  8. Read additional guidelines from the Nx team

💡 Any of the generator commands accepts --dryRun param that you can use to review the changes prior to executing them.

Frontend

We use the nx-vue3-vite plugin. Post any frontend issues to that repository.

Note - Data Access and Feature libraries may also use @nrwl/node:library. nx-vue3-vite:lib is geared towards component library generation, so if the library will not include Vue Single File Components, it doesn't make sense to use that generator.

Apps:

# Vue3/Vite site
$ nx g nx-vue3-vite:app web --tags scope:web,type:app

# Vue3/Vite Cypress E2E
$ nx g nx-vue3-vite:cypress --project web --tags scope:web,type:app

# Frontend Feature library
$ nx g nx-vue3-vite:lib feature-login --directory=web --tags scope:web,type:feature

# Frontend UI library
$ nx g nx-vue3-vite:lib ui-themes --directory=web --tags scope:web,type:ui

# Frontend Data Access library
$ nx g nx-vue3-vite:lib data-access-nft-search --directory=web --tags scope:web,type:data-access

# Shared Utility library
$ nx g @nrwl/node:library util-nft-interface --directory=shared --tags scope:shared,type:util

Node apps

# NestJS API app with API request specs
npx nx g @nrwl/nest:app api --tags=scope:api,type=app

# Node Feature library
$ npx nx g @nrwl/nest:library feature-core --directory=api --tags=scope:api,type:feature

# Node Data Access library
$ npx nx g @nrwl/nest:library data-access-core --directory api --tags=scope:api,type:data-access

# Node Utility library
$ npx nx g @nrwl/nest:library util-app-config --directory=api --tags=scope:api,type:util

# Node Shared Utility library
$ npx nx g @nrwl/node:library util-core --directory=shared --tags=scope:shared,type:util

Python apps

We use nx-python-poetry to generate opinionated Python apps and libraries. It's currently WIP and library generation is not stable yet, so for now all code lives in the Python apps folders.

# FastAPI Python app
$ nx g nx-python-fastapi:app web --tags scope:api,type:app

Blockchain

Note - the nx-hardhat generators set up a workable folder structure, but adjustments need to be made to run tests and develop locally. See the onboarding guide for environment setup instructions.

# Create Ethereum contracts app
npx nx g nx-hardhat:app --name contracts --tags scope:blockchain,type:app

Deleting Projects

# Delete project
$ npx nx g rm|remove [project-name]
$ npx nx g @nrwl/workspace:rm --project=[project-name]
  --- Example:
  npx nx g rm web-react-e2e

Renaming Projects

❗ Currently buggy. Prefer generating a new lib and deleting the old one instead.

Misc

# List installed and available plugins
$ npx nx list

# List capabilities of plugin
$ npx nx list [plugin] # e.g. @nrwl/nest, @nrwl/node