- Add ProjectTemplate TypeScript interfaces for type-safe templates - Implement EmbeddedTemplateProvider for bundled templates - Create Hello World template (Router + Home page + Text) - Update LocalProjectsModel to use embedded templates by default - Remove programmatic project creation workaround - Fix: Add required fields (id, comments, metadata) per TASK-010 - Fix: Correct node type 'PageRouter' → 'Router' - Add comprehensive developer documentation Benefits: - No more path resolution issues (__dirname/process.cwd()) - Works identically in dev and production - Type-safe template definitions - Easy to add new templates Closes TASK-009 (Phase 3 - Editor UX Overhaul)
TASK-009: Template System Refactoring
Status: 🟢 Complete (Backend)
Priority: Medium
Complexity: Medium
Actual Effort: 1 day (Backend implementation)
Context
The current project template system has several issues:
- Path resolution fails in webpack bundles (
__dirnamedoesn't work correctly) - No proper template provider for local/bundled templates
- Template loading depends on external URLs or fragile file paths
- New projects currently use a programmatic workaround (minimal project.json generation)
Current Temporary Solution
As of January 2026, new projects are created programmatically in LocalProjectsModel.ts:
// Create a minimal Hello World project programmatically
const minimalProject = {
name: name,
components: [
/* basic App component with Text node */
],
settings: {},
metadata: {
/* ... */
}
};
This works but is not ideal for:
- Creating rich starter templates
- Allowing custom/community templates
- Supporting multiple bundled templates (e.g., "Hello World", "Dashboard", "E-commerce")
Goals
Primary Goals
- Robust Template Loading: Support templates in both development and production
- Local Templates: Bundle templates with the editor that work reliably
- Template Gallery: Support multiple built-in templates
- Custom Templates: Allow users to create and share templates
Secondary Goals
- Template versioning and migration
- Template metadata (screenshots, descriptions, categories)
- Template validation before project creation
- Template marketplace integration (future)
Proposed Architecture
1. Template Storage Options
Option A: Embedded Templates (Recommended)
- Store templates as JSON structures in TypeScript files
- Import and use directly (no file I/O)
- Bundle with webpack automatically
- Example:
export const helloWorldTemplate: ProjectTemplate = {
name: 'Hello World',
components: [
/* ... */
],
settings: {
/* ... */
}
};
Option B: Asset-Based Templates
- Store templates in
packages/noodl-editor/assets/templates/ - Copy to build output during webpack build
- Use proper asset loading (webpack copy plugin)
- Access via runtime asset path resolution
Option C: Hybrid Approach
- Small templates: embedded in code
- Large templates: assets with proper bundling
- Choose based on template size/complexity
2. Template Provider Architecture
interface ProjectTemplate {
id: string;
name: string;
description: string;
category: string;
version: string;
thumbnail?: string;
// Template content
components: ComponentDefinition[];
settings: ProjectSettings;
metadata?: Record<string, unknown>;
}
interface TemplateProvider {
name: string;
list(): Promise<ProjectTemplate[]>;
get(id: string): Promise<ProjectTemplate>;
canHandle(id: string): boolean;
}
class EmbeddedTemplateProvider implements TemplateProvider {
// Returns templates bundled with the editor
}
class RemoteTemplateProvider implements TemplateProvider {
// Fetches templates from Noodl docs/CDN
}
class LocalFileTemplateProvider implements TemplateProvider {
// Loads templates from user's filesystem (for custom templates)
}
3. Template Manager
class TemplateManager {
private providers: TemplateProvider[];
async listTemplates(filter?: TemplateFilter): Promise<ProjectTemplate[]> {
// Aggregates from all providers
}
async getTemplate(id: string): Promise<ProjectTemplate> {
// Finds the right provider and fetches template
}
async createProjectFromTemplate(template: ProjectTemplate, projectPath: string, projectName: string): Promise<void> {
// Creates project structure from template
}
}
Implementation Plan
Phase 1: Foundation (1 day)
- Define
ProjectTemplateinterface - Create
TemplateProviderinterface - Implement
EmbeddedTemplateProvider - Create
TemplateManagerclass
Phase 2: Built-in Templates (1 day)
- Convert current Hello World to embedded template
- Add "Blank" template (truly empty)
- Add "Dashboard" template (with nav + pages)
- Add template metadata and thumbnails
Phase 3: Integration (0.5 days)
- Update
LocalProjectsModelto useTemplateManager - Remove programmatic project creation workaround
- Update project creation UI to show template gallery
- Add template preview/selection dialog
Phase 4: Advanced Features (0.5 days)
- Implement template validation
- Add template export functionality (for users to create templates)
- Support template variables/parameters
- Add template upgrade/migration system
Files to Modify
New Files
packages/noodl-editor/src/editor/src/models/template/ProjectTemplate.tspackages/noodl-editor/src/editor/src/models/template/TemplateProvider.tspackages/noodl-editor/src/editor/src/models/template/TemplateManager.tspackages/noodl-editor/src/editor/src/models/template/providers/EmbeddedTemplateProvider.tspackages/noodl-editor/src/editor/src/models/template/templates/(folder for template definitions)hello-world.tsblank.tsdashboard.ts
Existing Files to Update
packages/noodl-editor/src/editor/src/utils/LocalProjectsModel.ts- Replace programmatic project creation with template system
packages/noodl-editor/src/editor/src/pages/ProjectsPage/ProjectsPage.tsx- Add template selection UI
packages/noodl-editor/src/editor/src/utils/forge/(might be refactored or replaced)
Testing Strategy
Unit Tests
- Template provider loading
- Template validation
- Project creation from template
- Template merging/variables
Integration Tests
- Create project from each bundled template
- Verify all templates load correctly
- Test template provider fallback
Manual Tests
- Create projects from templates in dev mode
- Create projects from templates in production build
- Verify all components and nodes are created correctly
- Test custom template import/export
Success Criteria
- New projects can be created from bundled templates reliably
- Templates work identically in dev and production
- At least 3 high-quality bundled templates available
- Template system is extensible for future templates
- No file path resolution issues
- User can export their project as a template
- Documentation for creating custom templates
Future Enhancements
- Template Marketplace: Browse and download community templates
- Template Packages: Include external dependencies/modules
- Template Generator: AI-powered template creation
- Template Forking: Modify and save as new template
- Template Versioning: Update templates without breaking existing projects
References
- Current implementation:
packages/noodl-editor/src/editor/src/utils/LocalProjectsModel.ts(lines 295-360) - Failed attempt:
packages/noodl-editor/src/editor/src/utils/forge/template/providers/local-template-provider.ts - Template registry:
packages/noodl-editor/src/editor/src/utils/forge/index.ts
Implementation Summary (January 9, 2026)
✅ What Was Completed
Phase 1-3: Backend Implementation (Complete)
-
Type System Created
ProjectTemplate.ts- Complete TypeScript interfaces for templates- Comprehensive type definitions for components, nodes, connections, and settings
-
EmbeddedTemplateProvider Implemented
- Provider that handles
embedded://protocol - Templates stored as TypeScript objects, bundled by webpack
- No file I/O dependencies, works identically in dev and production
- Provider that handles
-
Hello World Template Created
- Structure: App → PageRouter → Page "/Home" → Text "Hello World!"
- Clean and minimal, demonstrates Page Router usage
- Located in
models/template/templates/hello-world.template.ts
-
Template Registry Integration
EmbeddedTemplateProviderregistered with highest priority- Backward compatible with existing HTTP/Noodl Docs providers
-
LocalProjectsModel Updated
- Removed programmatic project creation workaround
- Default template now uses
embedded://hello-world - Maintains backward compatibility with external templates
-
Documentation
- Complete developer guide in
models/template/README.md - Instructions for creating custom templates
- Architecture overview and best practices
- Complete developer guide in
📁 Files Created
packages/noodl-editor/src/editor/src/models/template/
├── ProjectTemplate.ts # Type definitions
├── EmbeddedTemplateProvider.ts # Provider implementation
├── README.md # Developer documentation
└── templates/
└── hello-world.template.ts # Default template
📝 Files Modified
utils/forge/index.ts- Registered EmbeddedTemplateProviderutils/LocalProjectsModel.ts- Updated newProject() to use embedded templates
🎯 Benefits Achieved
✅ No more __dirname or process.cwd() path resolution issues
✅ Templates work identically in development and production builds
✅ Type-safe template definitions with full IDE support
✅ Easy to add new templates - just create a TypeScript file
✅ Maintains backward compatibility with external template URLs
⏳ Remaining Work (Future Tasks)
- UI for Template Selection: Gallery/dialog to choose templates when creating projects
- Additional Templates: Blank, Dashboard, E-commerce templates
- Template Export: Allow users to save their projects as templates
- Unit Tests: Test suite for EmbeddedTemplateProvider
- Template Validation: Verify template structure before project creation
🚀 Usage
// Create project with embedded template (automatic default)
LocalProjectsModel.instance.newProject(callback, {
name: 'My Project'
// Uses 'embedded://hello-world' by default
});
// Create project with specific template
LocalProjectsModel.instance.newProject(callback, {
name: 'My Project',
projectTemplate: 'embedded://hello-world'
});
Related Tasks
- TASK-009-UI: Template selection gallery (future)
- TASK-009-EXPORT: Template export functionality (future)
Created: January 8, 2026
Last Updated: January 9, 2026
Implementation: January 9, 2026 (Backend complete)