Files
skills/docs/devtools/tooling/electrobun/src/templates/features.md
2026-05-29 08:20:56 +01:00

3.2 KiB

Feature templates — features.ts

Purpose

Owns every renderer that produces a per-feature file in the scaffolded output: i18n, networking (basic + full), api, api-schemas, storage, auth, form-builder, and r3f. The renderers are pure functions over ProjectOptions; the r3f renderer additionally branches on options.r3fModules to wire camera / physics / particles / character / pathfinding subsystems into the emitted scene.

The companion templates.ts module covers the project-level renderers; the two together replace the upstream src/templates/*.ts and src/templates/features/*.ts blob set. renderFeature(feature, options) is the single dispatch entry the generator uses; individual render*Feature helpers are exported for tools that want to render a single feature in isolation (for example, a "show me the API skeleton" preview pane in an IDE extension).

Features

  • Eight per-feature renderers — every closed FeatureModule value has a dedicated implementation.
  • renderNetworkFeature vs renderNetworkFullFeature selected by options.networkingComplexity.
  • renderR3fFeature composes the camera / physics / particles imports
    • scene fragments based on options.r3fModules.
  • featurePath(feature) returns the canonical output path for each feature (the generator uses this to assemble the file list).

Usage: Basic

import { renderFeature, featurePath } from "@suaveplan/electrobun/templates";

const content = renderFeature("i18n", opts);
const path = featurePath("i18n");
// path === "src/features/i18n.ts"

Usage: Advanced

import {
    featurePath,
    renderFeature,
} from "@suaveplan/electrobun/templates";

const featureFiles = opts.features.map((f) => ({
    path: featurePath(f),
    content: renderFeature(f, opts),
}));

API Reference

  • renderI18nFeature(), renderNetworkFeature(), renderNetworkFullFeature(), renderApiFeature(), renderApiSchemasFeature(), renderStorageFeature(), renderAuthFeature(), renderFormBuilderFeature(), renderR3fFeature(options).
  • renderFeature(feature: FeatureModule, options: ProjectOptions): string — dispatch table.
  • featurePath(feature: FeatureModule): string.

Implementation Notes

The r3f renderer is the only one whose output is materially shaped by ProjectOptions beyond the basic "the feature is enabled" toggle. The imports and scene fragments are assembled by joining arrays of strings, which makes the relative ordering deterministic and the diff-noise low when a new R3F module is added: the test for "r3f renderer emits the requested modules" pins the order so a refactor cannot silently re-shuffle imports.

The networking renderer dispatches on options.networkingComplexity rather than options.networking because the upstream contract used "basic" / "full" to gate the full mesh layer. Keeping the same contract means downstream electrobun projects already on the networkingComplexity shape do not need to migrate.

featurePath lives here rather than in the generator because the mapping is per-feature; the generator consumes it as a thin lookup. If a future feature lands with a non-default output path, the change is local to features.ts.