@rettangoli/fe includes CLI commands for building, developing, validating, and scaffolding components. All commands are run through the rtgl CLI.
Commands
| Command | Description |
|---|---|
rtgl fe build |
Build component bundles |
rtgl fe watch |
Start dev server with file watching |
rtgl fe scaffold --category <folder> --component-name <name> |
Generate a new component from a template |
rtgl fe check |
Validate components against contracts |
rtgl fe examples |
Generate example specs for visual testing |
rtgl fe build
Bundles all components found in the configured directories into a single output file.
rtgl fe build
Uses the outfile path from rettangoli.config.yaml:
fe:
dirs:
- "./src/components"
outfile: "./dist/bundle.js"
The build uses Vite 8 (vite.build) with Rolldown and Oxc for production bundling and minification.
Source maps are off by default. --sourcemap writes a .map next to each
emitted file and links it with a sourceMappingURL comment. --sourcemap hidden
writes the same maps without the comment, so a shipped bundle never points at
them; keep those maps privately to symbolicate production errors. Maps embed
the original source code, so publish them only if that source may be public.
rtgl fe build --sourcemap hidden
rtgl fe watch
Starts a development server that watches for file changes and applies updates automatically.
rtgl fe watch
Uses Vite (vite.createServer) for dev serving. Compatible component edits use
HMR, preserving component instances and store state. Locale YAML edits replace
the development catalogs while retaining the selected locale and existing
subscriptions. Component directories, the setup module, and i18n sources are
watched explicitly, including when they are outside the served static root.
Changes to setup files and component or locale file additions/removals perform a full page reload. An update that changes an incompatible browser contract, such as a component name or observed prop, also falls back to a full reload.
Use fe.publicDir to serve a directory of static assets at / without Vite
transformations:
fe:
publicDir: "./static"
The equivalent CLI option is rtgl fe watch --public-dir ./static. Relative
paths are resolved from the project root. This is useful when binary assets use
extensionless filenames that Vite would otherwise treat as JavaScript modules.
Vite Integration Details
FE keeps the same CLI interface and integrates Vite internally.
- Virtual entry: FE generates a virtual module (
virtual:rettangoli-fe-entry) from configured component files. - Plugin hooks used:
resolveId+loadto provide generated entry code.handleHotUpdateto route compatible component and locale edits through the FE virtual-entry HMR boundary.configureServermiddleware to serve the configuredoutfilepath in watch mode and handle full-reload fallbacks.
- Startup behavior:
- Watch mode warms and validates the virtual entry before reporting the server as ready.
- Output behavior:
- Build preserves configured
fe.outfileas the entry filename. - Additional chunks may be emitted under a
chunks/folder when splitting is enabled.
- Build preserves configured
- Validation behavior:
- Contract validation and YAML/template parsing run before bundle generation.
- Watched YAML changes invalidate the virtual entry before HMR processing.
Current limitation:
- FE does not enable extra Vite CSS plugin configuration.
rtgl fe scaffold
Generates a new component with the required boilerplate files:
rtgl fe scaffold --category components --component-name my-component
--category is the folder name the component is created under (inside --dir, default ./example).
This creates:
./example/components/my-component/
my-component.schema.yaml
my-component.view.yaml
my-component.store.js
my-component.handlers.js
Each file contains a minimal valid template ready for editing.
rtgl fe check
Validates all components against the framework contracts. Checks include:
- Every component has a
.schema.yamlfile - No forbidden API keys in
.view.yaml(elementName,viewDataSchema,propsSchema,events,methods,attrsSchema) - No legacy dot property bindings in views
- Schema methods match
.methods.jsexports
Text Output (default)
rtgl fe check
Outputs a grouped summary by rule and component, plus detailed error lines.
JSON Output
rtgl fe check --format json
Machine-readable JSON report for CI integration.
Error Codes
| Code | Description |
|---|---|
| RTGL-CONTRACT-001 | Missing .schema.yaml for component |
| RTGL-CONTRACT-002 | Forbidden API key in .view.yaml |
| RTGL-CONTRACT-003 | Legacy dot property binding in view |
| RTGL-HANDLERS-001 | handleBeforeMount returned a Promise |
| RTGL-HANDLERS-002 | View references a missing handler |
| RTGL-METHODS-001 | Method name is default |
| RTGL-METHODS-002 | Method payload is not an object |
| RTGL-METHODS-003 | Method conflicts with element property |
| RTGL-STORE-001 | Action payload is not an object |
rtgl fe examples
Generates example spec files from .schema.yaml examples for use with @rettangoli/vt visual testing.
rtgl fe examples
Output directory is configured in rettangoli.config.yaml:
fe:
examples:
outputDir: "./vt/specs/examples"
Configuration
All commands read from rettangoli.config.yaml at the project root:
fe:
dirs:
- "./src/components"
- "./src/pages"
setup: "setup.js"
outfile: "./dist/bundle.js"
publicDir: "./static"
i18n:
dir: "./src/i18n"
defaultLocale: "en"
fallbackLocale: "en"
locales:
- "en"
- "vi"
examples:
outputDir: "./vt/specs/examples"
| Key | Description |
|---|---|
dirs |
Directories to scan for component files |
setup |
Setup script that exports custom dependencies |
outfile |
Output path for the bundled JavaScript |
publicDir |
Optional directory served at / without transformations in watch mode |
i18n.dir |
Directory containing locale YAML files |
i18n.defaultLocale |
Initial locale used by the runtime |
i18n.fallbackLocale |
Locale used if another locale cannot be loaded |
i18n.locales |
Supported locale codes |
examples.outputDir |
Output directory for generated example specs |
Setup File
The setup.js file exports a deps object that provides custom dependencies to your components. Dependencies are keyed by category (matching directory names under your configured dirs).
const deps = {
components: {
// available as deps.apiClient in component handlers
apiClient: createApiClient(),
},
pages: {
router: createRouter(),
},
}
export { deps }
Each category's dependencies are merged into the deps argument that handlers receive. The framework handles virtual DOM and patching internally — setup.js is only for your application-level dependencies.
The generated entry imports the setup module before any component module. Bootstrap code that setup.js imports first, such as error reporting, therefore runs before component modules are evaluated and can observe their load-time errors.