Link Loom Node.js Service Development Skill
This skill allows you to develop backend services for the Link Loom ecosystem, adhering to strict architectural, stylistic, and documentation standards.
Table of Contents
- Coding Standards
- Architecture & Concepts
- Naming Conventions
- Directory Structure
- Component Guidelines
- Registration & Indexing
- General Best Practices
- Resources & Documentation
- Instructions
- Examples
- Edge Cases
1. Coding Standards
Flat-Style & Defensive Coding (Critical)
- No Nested If-Else: Avoid deep nesting.
- Guard Clauses: Validate inputs at the beginning of the function.
- Negative Check First: Check for failure conditions (missing params, falsy values) immediately and return errors.
- Happy Path Last: The successful execution logic should remain at the end of the function.
Bad:
async myFunc(params) {
if (params) {
if (params.id) {
// logic...
return success;
} else {
return error;
}
} else {
return error;
}
}
Good (Required):
async myFunc({ params }) {
// 1. Defensive Checks
if (!params) return this._utilities.io.response.error('Missing params');
if (!params.id) return this._utilities.io.response.error('Missing ID');
// 2. Logic
const result = await this._doWork(params.id);
// 3. Negative Check on Result
if (!result) return this._utilities.io.response.error('Work failed');
// 4. Happy Path Return
return this._utilities.io.response.success(result);
}
2. Architecture & Concepts
Domain Driven Design (DDD) parity
CRITICAL: The backend structure dictates the frontend structure.
- Ensure that modules are organized by domain (e.g.,
workflow-orchestration/control-plane/...).
- Changes in this structure must be reflected in the frontend to maintain 1:1 parity.
Understanding what to build is as important as how to build it.
| Concept |
Usage |
| Service |
Default choice. Contains business logic, database interactions, and complex operations. Extends BaseModel patterns usually. |
| Function |
Single-purpose, often stateless utility or cloud function logic (e.g., timed, startup). Do not make a Function if it manages entity state. |
| App |
A long-running app, self-contained module or mini-application logic. |
| Model |
Data definition and schema. Must extend BaseModel. |
3. Naming Conventions
Strictly adhere to these naming conventions.
| Type |
File Pattern |
Class Name Pattern |
Example |
| Service |
kebab-case.service.js |
[Domain][Entity]Service |
WorkflowOrchestrationFlowDefinitionService (File: flow-definition.service.js) |
| Route |
kebab-case.route.js |
[Domain][Entity]Route |
WorkflowOrchestrationFlowDefinitionRoute (File: flow-definition.route.js) |
| Model |
kebab-case.model.js |
[Domain][Entity]Model |
WorkflowOrchestrationFlowDefinitionModel (File: flow-definition.model.js) |
| Utility |
kebab-case.util.js |
camelCase (func) |
dateFormatter |
Rule: Class names MUST be the concatenation of the Full Domain Path + Entity Name.
- Path:
src/models/workflow-orchestration/control-plane/flow-design/flow-definition/
- Entity:
FlowDefinition
- Class:
WorkflowOrchestrationFlowDefinitionModel
Rule: Class names MUST be the concatenation of the Full Domain Path + Entity Name.
- Path:
src/models/workflow-orchestration/control-plane/flow-design/flow-definition/
- Entity:
FlowDefinition
- Class:
WorkflowOrchestrationFlowDefinitionModel
4. Directory Structure
Place files in the correct location based on their responsibility.
src/
├── routes/
│ ├── router.js # Main router aggregator
│ └── api/
│ └── <module-name>/
│ ├── <module>.routes.js # Module-specific router (e.g., chat.routes.js)
│ └── <feature>.route.js # Route handler class
├── services/
│ ├── index.js # Main service exporter
│ └── <module-name>/
│ └── <feature>.service.js # Logic
├── models/
│ ├── index.js # Main model exporter
│ └── <model-name>.model.js # Schema
5. Component Guidelines
Models
- Inheritance: MUST extend
BaseModel (from @link-loom/sdk).
- Statuses:
entityStatuses MUST always include a color property (hex code) for UI consistency.
- Structure: Sub-models/Sub-entities MUST be placed in a
sub-entities/ folder within the model's directory.
- Strict Definitions: NO "black box" properties. All properties must be explicitly defined in
initializeEntityProperties. This prepares for TypeScript migration.
- Synchronization: Every property MUST be present in 4 places:
- Class Declaration: Top of the class (e.g.,
name;).
- Initialization: Inside
initializeEntityProperties (e.g., this.name = ...).
- Getter: Inside
get get() (e.g., name: this.name?.value).
- Swagger: Inside
@swagger definition.
- No Redundant Props: Do not define
id, created, modified, or status manually. These are inherited.
- Swagger: MUST include full Swagger
@swagger documentation for the schema.
- Initialization: Implement explicit
initializeEntityProperties(args) method.
- Getters: Implement
sanitized and get accessors.
Services
- Constructor Order:
- Base Properties (
dependencies)
- Custom Properties (private vars)
- Assignments
- Get Method: Must use a
switch(params.queryselector) to handle variants (id, all, etc.).
- Private Methods: Use private methods (
#getById, #getAll) for specific logic, called by the main public methods.
- Validation: Every public method must start with input validation (defensive coding).
Routes
- Micro-Routers: Do not add routes directly to
src/routes/router.js. Add them to src/routes/api/<module>/<module>.routes.js, then import that file in the main router.
- Classes: Route handlers are classes.
- Swagger: Every route method must have full Swagger documentation defining inputs/outputs.
- CRUD Mapping: Typically map
get, create, update, delete handlers, unless it is a command route (e.g., execute).
6. Registration & Indexing
- Services: Must be exported in
src/services/index.js.
- Models: Must be exported in
src/models/index.js.
- Routes: Must be defined in the module's
*.routes.js file (e.g., chat.routes.js) using the standard configuration object (httpRoute, route, handler, method).
7. General Best Practices
- Language: English ONLY for code and static text, unless explicitly requested otherwise by the user.
- Documentation: Avoid excessive comments. Document only complex algorithms. Code should be self-documenting.
- KISS Principle: keep it simple, stupid. Avoid overengineering. If a process is simple, keep the code simple.
- Naming: Use semantic variable names. NEVER use single-letter names like
x, ac, t. Names must indicate intent.
- Clean Code: Remove unused imports, dependencies, and functions. No dead code.
- Git: Use Conventional Commits if asked to generate commit messages.
- Design Patterns: Act as an experienced architect. Use patterns (Factory, Singleton, Proxy, etc) only when necessary to solve a specific problem. Do not force patterns where simple logic suffices.
- Context: Do not infer if unsure. Always ask the user for clarification if requirements are not clear. Challenge user requests that lead to "garbage code" or antipatterns.
- Backend Specifics:
- Reuse: ALWAYS check
link-loom/loom-sdk docs. Do not reinvent utilities or base classes that already exist.
- Model Awareness: Understand existing backend models before creating any functionality to deeply understand the domain.
- Strictness: Since you are the expert, do not let the user start to write bad code patterns, warn him.
- Linting: MANDATORY. Code must be written adhering to the project's linter configuration (e.g.,
.prettierrc, .eslintrc.js).
8. Resources & Documentation
CRITICAL: Before inventing new utilities or patterns, check the local documentation.
- Link Loom SDK Docs:
link-loom/github/loom-sdk/docs
- Core Utilities:
link-loom/github/loom-sdk/docs/core/utilities.module.md
- Infrastructure:
link-loom/github/loom-sdk/docs/infrastructure/ (Email, Storage, Database)
- Data Types:
link-loom/github/loom-sdk/docs/core/data-types.module.md
Use view_file on these paths to understand available tools before coding.
9. Instructions
- Read Context: Before creating a file, check the
index.js or router.js to see where it fits.
- Use Assets: Copy the base structure from the
assets/ templates.
- Apply Standards: Refactor the template code to match the "Flat-Style" and specific logic requirements (switch cases, defensive checks).
- Document: Add Swagger JSDoc immediately.
- Register: Update the corresponding
index.js or routes.js file to register the new component.
10. Examples
Service Implementation
See assets/service.js.
Route Implementation
See assets/route.js.
App Implementation
See assets/app.js.
Model Implementation
See assets/model.js.
11. Edge Cases
- Missing Organization ID: Almost all create methods require
organization_id. Fail if missing.
- Transaction Safety: If using database transactions, ensure errors are caught and logged properly before returning the error response.
- Legacy Code: If you see code that doesn't follow "Flat-Style", do not copy it. Upgrade it to the new standard.
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: loom-nodejs3description: Develop BACKEND Node.js services, APIs, routes, and models for Link Loom. Handles database interactions, business logic, and server-side operations using `loom-sdk`. Use when this capability is needed.4---56# Link Loom Node.js Service Development Skill78This skill allows you to develop backend services for the Link Loom ecosystem, adhering to strict architectural, stylistic, and documentation standards.910## Table of Contents11121. [Coding Standards](#1-coding-standards)132. [Architecture & Concepts](#2-architecture--concepts)143. [Naming Conventions](#3-naming-conventions)154. [Directory Structure](#4-directory-structure)165. [Component Guidelines](#5-component-guidelines)17 - [Models](#models)18 - [Services](#services)19 - [Routes](#routes)206. [Registration & Indexing](#6-registration--indexing)217. [General Best Practices](#7-general-best-practices)228. [Resources & Documentation](#8-resources--documentation)239. [Instructions](#9-instructions)2410. [Examples](#10-examples)2511. [Edge Cases](#11-edge-cases)2627---2829## 1. Coding Standards3031### **Flat-Style & Defensive Coding (Critical)**3233- **No Nested If-Else**: Avoid deep nesting.34- **Guard Clauses**: Validate inputs at the beginning of the function.35- **Negative Check First**: Check for failure conditions (missing params, falsy values) immediately and return errors.36- **Happy Path Last**: The successful execution logic should remain at the end of the function.3738**Bad:**3940```javascript41async myFunc(params) {42 if (params) {43 if (params.id) {44 // logic...45 return success;46 } else {47 return error;48 }49 } else {50 return error;51 }52}53```5455**Good (Required):**5657```javascript58async myFunc({ params }) {59 // 1. Defensive Checks60 if (!params) return this._utilities.io.response.error('Missing params');61 if (!params.id) return this._utilities.io.response.error('Missing ID');6263 // 2. Logic64 const result = await this._doWork(params.id);6566 // 3. Negative Check on Result67 if (!result) return this._utilities.io.response.error('Work failed');6869 // 4. Happy Path Return70 return this._utilities.io.response.success(result);71}72```7374---7576## 2. Architecture & Concepts7778### Domain Driven Design (DDD) parity7980**CRITICAL**: The backend structure dictates the frontend structure.8182- Ensure that modules are organized by domain (e.g., `workflow-orchestration/control-plane/...`).83- Changes in this structure must be reflected in the frontend to maintain 1:1 parity.8485Understanding what to build is as important as how to build it.8687| Concept | Usage |88| :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------- |89| **Service** | **Default choice.** Contains business logic, database interactions, and complex operations. Extends `BaseModel` patterns usually. |90| **Function** | Single-purpose, often stateless utility or cloud function logic (e.g., `timed`, `startup`). Do not make a Function if it manages entity state. |91| **App** | A long-running app, self-contained module or mini-application logic. |92| **Model** | Data definition and schema. **Must** extend `BaseModel`. |9394---9596## 3. Naming Conventions9798**Strictly** adhere to these naming conventions.99100| Type | File Pattern | Class Name Pattern | Example |101| :---------- | :---------------------- | :------------------------ | :-------------------------------------------------------------------------------- |102| **Service** | `kebab-case.service.js` | `[Domain][Entity]Service` | `WorkflowOrchestrationFlowDefinitionService` (File: `flow-definition.service.js`) |103| **Route** | `kebab-case.route.js` | `[Domain][Entity]Route` | `WorkflowOrchestrationFlowDefinitionRoute` (File: `flow-definition.route.js`) |104| **Model** | `kebab-case.model.js` | `[Domain][Entity]Model` | `WorkflowOrchestrationFlowDefinitionModel` (File: `flow-definition.model.js`) |105| **Utility** | `kebab-case.util.js` | `camelCase` (func) | `dateFormatter` |106107**Rule**: Class names MUST be the concatenation of the Full Domain Path + Entity Name.108109- Path: `src/models/workflow-orchestration/control-plane/flow-design/flow-definition/`110- Entity: `FlowDefinition`111- Class: `WorkflowOrchestrationFlowDefinitionModel`112113**Rule**: Class names MUST be the concatenation of the Full Domain Path + Entity Name.114115- Path: `src/models/workflow-orchestration/control-plane/flow-design/flow-definition/`116- Entity: `FlowDefinition`117- Class: `WorkflowOrchestrationFlowDefinitionModel`118119---120121## 4. Directory Structure122123Place files in the correct location based on their responsibility.124125```text126src/127├── routes/128│ ├── router.js # Main router aggregator129│ └── api/130│ └── <module-name>/131│ ├── <module>.routes.js # Module-specific router (e.g., chat.routes.js)132│ └── <feature>.route.js # Route handler class133├── services/134│ ├── index.js # Main service exporter135│ └── <module-name>/136│ └── <feature>.service.js # Logic137├── models/138│ ├── index.js # Main model exporter139│ └── <model-name>.model.js # Schema140```141142---143144## 5. Component Guidelines145146### Models147148- **Inheritance**: MUST extend `BaseModel` (from `@link-loom/sdk`).149- **Statuses**: `entityStatuses` MUST always include a `color` property (hex code) for UI consistency.150- **Structure**: Sub-models/Sub-entities MUST be placed in a `sub-entities/` folder within the model's directory.151- **Strict Definitions**: NO "black box" properties. All properties must be explicitly defined in `initializeEntityProperties`. This prepares for TypeScript migration.152- **Synchronization**: Every property MUST be present in 4 places:153 1. **Class Declaration**: Top of the class (e.g., `name;`).154 2. **Initialization**: Inside `initializeEntityProperties` (e.g., `this.name = ...`).155 3. **Getter**: Inside `get get()` (e.g., `name: this.name?.value`).156 4. **Swagger**: Inside `@swagger` definition.157- **No Redundant Props**: Do **not** define `id`, `created`, `modified`, or `status` manually. These are inherited.158- **Swagger**: MUST include full Swagger `@swagger` documentation for the schema.159- **Initialization**: Implement explicit `initializeEntityProperties(args)` method.160- **Getters**: Implement `sanitized` and `get` accessors.161162### Services163164- **Constructor Order**:165 1. Base Properties (`dependencies`)166 2. Custom Properties (private vars)167 3. Assignments168- **Get Method**: Must use a `switch(params.queryselector)` to handle variants (`id`, `all`, etc.).169- **Private Methods**: Use private methods (`#getById`, `#getAll`) for specific logic, called by the main public methods.170- **Validation**: Every public method must start with input validation (defensive coding).171172### Routes173174- **Micro-Routers**: Do not add routes directly to `src/routes/router.js`. Add them to `src/routes/api/<module>/<module>.routes.js`, then import that file in the main router.175- **Classes**: Route handlers are classes.176- **Swagger**: Every route method must have full Swagger documentation defining inputs/outputs.177- **CRUD Mapping**: Typically map `get`, `create`, `update`, `delete` handlers, unless it is a command route (e.g., `execute`).178179---180181## 6. Registration & Indexing182183- **Services**: Must be exported in `src/services/index.js`.184- **Models**: Must be exported in `src/models/index.js`.185- **Routes**: Must be defined in the module's `*.routes.js` file (e.g., `chat.routes.js`) using the standard configuration object (httpRoute, route, handler, method).186187---188189## 7. General Best Practices190191- **Language**: **English ONLY** for code and static text, unless explicitly requested otherwise by the user.192- **Documentation**: Avoid excessive comments. Document only complex algorithms. Code should be self-documenting.193- **KISS Principle**: keep it simple, stupid. Avoid overengineering. If a process is simple, keep the code simple.194- **Naming**: Use semantic variable names. **NEVER** use single-letter names like `x`, `ac`, `t`. Names must indicate intent.195- **Clean Code**: Remove unused imports, dependencies, and functions. No dead code.196- **Git**: Use **Conventional Commits** if asked to generate commit messages.197- **Design Patterns**: Act as an experienced architect. Use patterns (Factory, Singleton, Proxy, etc) **only** when necessary to solve a specific problem. Do not force patterns where simple logic suffices.198- **Context**: Do not infer if unsure. Always ask the user for clarification if requirements are not clear. Challenge user requests that lead to "garbage code" or antipatterns.199- **Backend Specifics**:200 - **Reuse**: ALWAYS check `link-loom`/`loom-sdk` docs. Do not reinvent utilities or base classes that already exist.201 - **Model Awareness**: Understand existing backend models before creating any functionality to deeply understand the domain.202- **Strictness**: Since you are the expert, do not let the user start to write bad code patterns, warn him.203- **Linting**: **MANDATORY**. Code must be written adhering to the project's linter configuration (e.g., `.prettierrc`, `.eslintrc.js`).204205---206207## 8. Resources & Documentation208209**CRITICAL**: Before inventing new utilities or patterns, check the local documentation.210211- **Link Loom SDK Docs**: `link-loom/github/loom-sdk/docs`212 - **Core Utilities**: `link-loom/github/loom-sdk/docs/core/utilities.module.md`213 - **Infrastructure**: `link-loom/github/loom-sdk/docs/infrastructure/` (Email, Storage, Database)214 - **Data Types**: `link-loom/github/loom-sdk/docs/core/data-types.module.md`215216Use `view_file` on these paths to understand available tools before coding.217218---219220## 9. Instructions2212221. **Read Context**: Before creating a file, check the `index.js` or `router.js` to see where it fits.2232. **Use Assets**: Copy the base structure from the `assets/` templates.2243. **Apply Standards**: Refactor the template code to match the "Flat-Style" and specific logic requirements (switch cases, defensive checks).2254. **Document**: Add Swagger JSDoc immediately.2265. **Register**: Update the corresponding `index.js` or `routes.js` file to register the new component.227228---229230## 10. Examples231232### Service Implementation233234See `assets/service.js`.235236### Route Implementation237238See `assets/route.js`.239240### App Implementation241242See `assets/app.js`.243244### Model Implementation245246See `assets/model.js`.247248---249250## 11. Edge Cases251252- **Missing Organization ID**: Almost all create methods require `organization_id`. Fail if missing.253- **Transaction Safety**: If using database transactions, ensure errors are caught and logged properly before returning the error response.254- **Legacy Code**: If you see code that doesn't follow "Flat-Style", do not copy it. Upgrade it to the new standard.255256---257> Converted and distributed by [TomeVault](https://tomevault.io/claim/link-loom) — claim your Tome and manage your conversions.258<!-- tomevault:4.0:skill_md:2026-04-11 -->