@noego/app
v0.0.34
Published
Production build tool for Dinner/Forge apps.
Downloads
733
Readme
@noego/app
@noego/app is the application runtime and CLI for NoEgo projects. It is the layer that turns the lower-level NoEgo packages into a complete full-stack app: Express processes, Dinner API routing, Forge SSR/CSR rendering, IoC-scoped controllers, development process orchestration, and production build output.
For new projects, use @noego/app as the main entrypoint. Packages like @noego/forge and @noego/dinner still work on their own, but direct booting is the low-level path. App is the recommended path for generated NoEgo applications.
What It Does
@noego/app coordinates the runtime pieces that a full-stack NoEgo app needs:
- Application boot: loads
noego.config.yml, resolves paths, sets runtime environment, and calls the project boot entry. - Backend API: boots
@noego/dinnerwith OpenAPI routes, controller lookup, middleware lookup, and request-scoped IoC. - Frontend SSR: boots
@noego/forgewith Svelte 5 SSR, client navigation, HTML shell rendering, and page-controller construction. - Browser hydration: exposes
client.init()for browser-side Forge startup with IoC-backed page controllers. - Development runtime: runs router, frontend, and backend services in split-serve mode and restarts the right service when watched files change.
- Build pipeline: compiles server code, copies runtime assets, builds client bundles, compiles SSR components, rewrites the HTML shell, and emits a runtime manifest.
The goal is to preserve the framework contracts that make NoEgo productive:
- OpenAPI declares both server routes and UI routes.
- Controllers and page controllers resolve through the IoC container.
- SQL files stay next to repository code at runtime.
- Forge and Dinner keep file-based discovery working in dev and production.
- Generated projects have one reviewable config file instead of scattered boot flags.
Package Role
NoEgo projects are built from several packages:
| Package | Role |
| --- | --- |
| @noego/app | Application runtime, CLI, config, process orchestration, build output |
| @noego/dinner | Server-side OpenAPI routing, controller dispatch, request validation |
| @noego/forge | Svelte SSR/CSR frontend routing, layouts, loaders, page controllers |
| @noego/ioc | Dependency injection for services, controllers, and page controllers |
| @noego/stitch | OpenAPI stitching for modular YAML files |
| sqlstack | SQL-first repositories with co-located query files |
Installation
Generated projects include @noego/app automatically. For an existing project:
npm install @noego/app @noego/dinner @noego/forge @noego/ioc express
npm install --save-dev typescript vite tsx chokidarThe package exposes both binaries:
noego dev
app buildProject Shape
A typical full-stack project looks like this:
.
├── noego.config.yml
├── src/
│ ├── index.ts
│ ├── server/
│ │ ├── server.ts
│ │ ├── stitch.yaml
│ │ ├── openapi/
│ │ ├── controller/
│ │ ├── logic/
│ │ ├── services/
│ │ └── repo/
│ ├── middleware/
│ └── ui/
│ ├── frontend.ts
│ ├── index.html
│ ├── stitch.yaml
│ ├── openapi/
│ ├── pages/
│ ├── layout/
│ └── controllers/
└── migrations/The paths are configurable. App does not require this exact layout, but generated projects use it because it keeps runtime discovery predictable.
Configuration
App auto-discovers config files named:
noego.yaml,noego.yml,noego.config.yaml,noego.config.ymlapp.yaml,app.yml,app.config.yaml,app.config.yml- legacy
hammer.yaml,hammer.yml,hammer.config.yaml,hammer.config.yml
Generated projects use noego.config.yml:
root: .
mode: production
outDir: dist
app:
boot: src/index.ts
watch:
- src/index.ts
- noego.config.yml
server:
main: src/server/server.ts
controllers: src/server/controller
middleware: src/middleware
openapi: src/server/stitch.yaml
watch:
- src/server/**/*.ts
- src/middleware/**/*.ts
- src/server/stitch.yaml
- src/server/openapi/**/*.yaml
- migrations/**/*.sql
client:
main: src/ui/frontend.ts
shell: src/ui/index.html
openapi: src/ui/stitch.yaml
componentDir: src/ui
watch:
- src/ui/**/*.ts
- src/ui/**/*.tsx
- src/ui/**/*.svelte
- src/ui/stitch.yaml
- src/ui/openapi/**/*.yaml
- vite.config.js
exclude:
- src/server/**
- src/middleware/**
assets:
- src/ui/resources/**
- migrations/**/*.sql
dev:
watch: true
splitServe: true
port: 3000Important fields:
app.boot: project-level boot file. Required.server.main: backend service bootstrap. Required whenserveris present.server.controllers: base directory for Dinnerx-controllerresolution.server.middleware: base directory for Dinner/Forgex-middlewareresolution.server.openapi: server OpenAPI or Stitch entry.client.main: frontend service bootstrap. Required whenclientis present.client.shell: Forge HTML shell.client.openapi: UI route OpenAPI or Stitch entry.client.componentDir: base directory for Svelte pages, layouts, controllers, and loaders.client.exclude: server-only paths that must not enter the browser bundle.assets: files copied into production output.dev.splitServe: in the recommended dev path, runs router/frontend/backend as separate processes.
Relative paths resolve from root.
Runtime Entry Points
Application Boot
app.boot is the top-level entry that the runtime imports. In generated projects it wires shared setup such as logging, environment loading, and process-specific boot behavior.
Backend Boot
server.main is called with the Express app and resolved config. It should install app middleware, initialize process-local resources, and call the backend boot() helper from @noego/app/client:
import express from 'express';
import { boot as bootBackend } from '@noego/app/client';
export default async function server(app: express.Express, config: any) {
app.use(express.json({ limit: '50mb' }));
return bootBackend();
}bootBackend() creates the Dinner server and resolves controllers through a request-scoped IoC container. Controller methods receive { req, res }. Projects can pass Dinner asset mappings when they need static backend assets.
Frontend Boot
client.main is also called with the Express app and resolved config. It should initialize any frontend-process resources that SSR loaders need, then call client.boot():
import { client } from '@noego/app/client';
import { initDatabase } from '../server/repo/boot';
export default async function frontend(app: import('express').Express, config: any) {
await initDatabase();
await client.boot();
}That initDatabase() call is important in split-serve mode. The frontend SSR process is separate from the backend API process, so .load.ts files cannot rely on backend-only initialization.
Browser Entry
The browser bundle calls:
import { client } from '@noego/app/client';
export default async function initApp() {
await client.init();
}client.init() reads the Forge configuration injected into the page, mounts the app on #app, and supplies a controller_factory that resolves Forge page controllers through a scoped IoC container.
Development
Use the default IoC-based dev path for current projects:
noego devdev.splitServe: true is currently required by the IoC-based dev command.
With dev.port: 3000, App runs:
| Process | Port | Purpose |
| --- | ---: | --- |
| router | 3000 | Public entrypoint and proxy |
| frontend | 3001 | Forge SSR/Vite service |
| backend | 3002 | Dinner API service |
The router sets process environment such as NOEGO_SERVICE, NOEGO_PORT, NOEGO_FRONTEND_PORT, NOEGO_BACKEND_PORT, NOEGO_CONFIG_FILE, and NOEGO_CLI_ROOT.
Watch Classification
When dev.watch: true, App watches configured globs and restarts only the service that needs to restart:
app.watch: restart backend and frontend.server.watch: restart backend.client.watch: restart frontend.
Svelte/CSS/browser module updates are normally handled by Vite HMR in the frontend process. Use client.watch for changes that require rebuilding the SSR process or route manifest, such as UI OpenAPI or config changes.
Hooks
Hooks run shell commands when matching files change. They are useful for generated artifacts such as OpenAPI clients, stitched schemas, or SQL/codegen output.
hooks:
- name: generate-openapi
watch:
- src/server/openapi/**/*.yaml
- src/server/stitch.yaml
command: npm run openapi:generate
cwd: .
debounceMs: 250Required fields:
watch: non-empty list of glob patterns.command: shell command to run.
Optional fields:
name: display name for logs. Defaults to the command.cwd: command working directory. Defaults to the config root. Relative paths resolve from the config root.debounceMs: debounce delay per hook. Defaults to250; use0to run immediately.
Hook failures are logged and do not stop the dev server. A file change can both run hooks and trigger service restarts if it matches both sets of patterns.
Build
Use:
noego buildThe production build pipeline:
- Loads and normalizes config.
- Cleans
outDir. - Discovers server controllers, middleware, UI pages, and layouts from OpenAPI/Stitch YAML.
- Builds server TypeScript while preserving runtime file layout.
- Copies required assets, OpenAPI YAML, SQL files, middleware, and static resources.
- Builds the browser client bundle with Vite.
- Builds Forge SSR components with Vite SSR.
- Rewrites the HTML shell to use production assets.
- Emits a runtime manifest.
- Generates a production bootstrap entry.
The build intentionally preserves file-based contracts. Dinner must still find controllers and middleware, Forge must still find SSR components/loaders, and sqlstack must still find .sql files beside compiled repository code.
Serve and Preview
Development-style serve:
noego servePreview prints resolved build configuration without running the full build:
noego previewUse --verbose when debugging config resolution or generated build paths.
OpenAPI-Driven Discovery
App relies on OpenAPI as the source of runtime structure:
- Server OpenAPI
x-controllervalues identify controller files. - Server and UI
x-middlewarevalues identify middleware files. - UI route
x-view,x-layout, andx-controllervalues identify Forge pages, layouts, and page controllers. - Stitch files let large apps split route definitions across feature folders.
Because the route graph is explicit, App can validate output and produce focused SSR build inputs instead of guessing from broad filesystem globs.
CLI Options
Common flags:
noego build --root . --config noego.config.yml --verbose
noego dev --root .Shared options include:
--root <dir>: project root.--config <file>: explicit config file.--out <dir>: output directory root.--mode <value>: build mode forwarded to Vite.--legacy: use the legacy direct command system instead of the default IoC-based runtime.--experimental: accepted for backwards compatibility; the IoC-based runtime is already the default.--verbose: verbose debug logging.
Legacy lower-level flags such as --server, --page, --controllers, --middleware, --openapi, --ui-openapi, --assets, and Vite override flags still exist, but committed noego.config.yml is the recommended source of truth.
Notes
@noego/apprequires Node>=20.11.- The IoC-based runtime is the default and is what generated projects target.
- Direct Forge or Dinner booting remains possible for legacy projects via
--legacy, but new full-stack apps should prefer App-managed runtime and config.
