15 KiB
TASK-007: App Configuration & Environment System
Overview
A new "App Setup" sidebar panel for defining app-wide configuration values (Noodl.Config), SEO metadata, PWA manifest generation, and an App Config node for accessing values without expressions.
Estimated effort: 64-86 hours
Priority: High - Foundation for theming, SEO, PWA, and deployment features
Phase: 3 (Editor UX Overhaul)
Problem Statement
Current Pain Points
- No central place for app metadata: App name, description, and SEO values are scattered or missing
- Global variables require node clutter: Users create Object/Variables nodes at App level and wire them everywhere, creating visual noise
- No PWA support: Users must manually create manifest.json and configure service workers
- SEO is an afterthought: No built-in way to set meta tags, Open Graph, or favicon
- Theming is manual: No standard pattern for defining color palettes or configuration values
User Stories
- "I want to define my app's primary color once and reference it everywhere"
- "I want my app to appear correctly when shared on social media"
- "I want to add my app to home screen on mobile with proper icons"
- "I want a simple way to access config values without writing expressions"
Solution
New Namespace: Noodl.Config
A static, immutable configuration namespace separate from Noodl.Variables:
// Static - set once at app initialization, cannot change at runtime
Noodl.Config.appName // "My Amazing App"
Noodl.Config.primaryColor // "#d21f3c"
Noodl.Config.apiBaseUrl // "https://api.example.com"
Noodl.Config.menuItems // [{name: "Home", path: "/"}, ...]
// This is NOT allowed (throws or is ignored):
Noodl.Config.primaryColor = "#000000"; // ❌ Config is immutable
Design Principles
- Config is static: Values are "baked in" at app load - use Variables for runtime changes
- Type-aware editing: Color picker for colors, array editor for arrays, etc.
- Required defaults: Core metadata (name, description) always exists
- Expression + Node access: Both
Noodl.Config.xin expressions AND an App Config node - Build-time injection: SEO tags and PWA manifest generated during build/deploy
Architecture
Data Model
interface AppConfig {
// Required sections (non-deletable)
identity: {
appName: string;
description: string;
coverImage?: string; // Path or URL
};
seo: {
ogTitle?: string; // Defaults to appName
ogDescription?: string; // Defaults to description
ogImage?: string; // Defaults to coverImage
favicon?: string;
themeColor?: string;
};
// Optional section
pwa?: {
enabled: boolean;
shortName?: string;
startUrl: string; // Default: "/"
display: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser';
backgroundColor?: string;
sourceIcon?: string; // Single source, auto-scaled to required sizes
};
// User-defined variables
variables: ConfigVariable[];
}
interface ConfigVariable {
key: string; // Valid JS identifier
type: ConfigType;
value: any;
description?: string; // Tooltip in UI
category?: string; // Grouping (defaults to "Custom")
validation?: {
required?: boolean;
pattern?: string; // Regex for strings
min?: number; // For numbers
max?: number;
};
}
type ConfigType = 'string' | 'number' | 'boolean' | 'color' | 'array' | 'object';
Storage Location
Stored in project.json under metadata:
{
"metadata": {
"appConfig": {
"identity": {
"appName": "My App",
"description": "An amazing app"
},
"seo": {
"themeColor": "#d21f3c"
},
"pwa": {
"enabled": true,
"display": "standalone"
},
"variables": [
{
"key": "primaryColor",
"type": "color",
"value": "#d21f3c",
"category": "Theme"
}
]
}
}
}
UI Design
App Setup Panel
New top-level sidebar tab (migrating some project settings here):
┌─────────────────────────────────────────────────┐
│ App Setup [?] │
├─────────────────────────────────────────────────┤
│ │
│ APP IDENTITY │
│ ┌─────────────────────────────────────────────┐ │
│ │ App Name [My Amazing App ] │ │
│ │ Description [A visual programming... ] │ │
│ │ [that makes building easy ] │ │
│ │ Cover Image [🖼️ cover.png ][Browse] │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ SEO & METADATA │
│ ┌─────────────────────────────────────────────┐ │
│ │ OG Title [ ] │ │
│ │ └ defaults to App Name │ │
│ │ OG Description [ ] │ │
│ │ └ defaults to Description │ │
│ │ OG Image [🖼️ ][Browse] │ │
│ │ └ defaults to Cover Image │ │
│ │ Favicon [🖼️ favicon.ico ][Browse] │ │
│ │ Theme Color [■ #d21f3c ] │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ▶ PWA CONFIGURATION [Enable] │
│ ┌─────────────────────────────────────────────┐ │
│ │ Short Name [My App ] │ │
│ │ Display Mode [Standalone ▼ ] │ │
│ │ Start URL [/ ] │ │
│ │ Background [■ #ffffff ] │ │
│ │ App Icon [🖼️ icon-512.png][Browse] │ │
│ │ └ 512x512 PNG, auto-scaled │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ CONFIGURATION VARIABLES [+ Add New] │
│ ┌─────────────────────────────────────────────┐ │
│ │ ┌─ Theme ─────────────────────────────────┐ │ │
│ │ │ primaryColor color [■ #d21f3c ][⋮]│ │ │
│ │ │ secondaryColor color [■ #1f3cd2 ][⋮]│ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ ┌─ API ───────────────────────────────────┐ │ │
│ │ │ apiBaseUrl string [https://... ][⋮]│ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ ┌─ Custom ────────────────────────────────┐ │ │
│ │ │ maxUploadSize number [10 ][⋮]│ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────┘
App Config Node
┌──────────────────────────────┐
│ App Config │
├──────────────────────────────┤
│ Variables │
│ ┌──────────────────────────┐ │
│ │ ☑ primaryColor │ │
│ │ ☑ apiBaseUrl │ │
│ │ ☐ secondaryColor │ │
│ │ ☑ menuItems │ │
│ └──────────────────────────┘ │
├──────────────────────────────┤
│ ○ primaryColor │──→
│ ○ apiBaseUrl │──→
│ ○ menuItems │──→
└──────────────────────────────┘
Subtasks
| Task | Description | Estimate | Dependencies |
|---|---|---|---|
| CONFIG-001 | Core Infrastructure | 14-18h | None |
| CONFIG-002 | App Setup Panel UI | 18-24h | CONFIG-001 |
| CONFIG-003 | App Config Node | 10-14h | CONFIG-001 |
| CONFIG-004 | SEO Build Integration | 8-10h | CONFIG-001, CONFIG-002 |
| CONFIG-005 | PWA Manifest Generation | 10-14h | CONFIG-001, CONFIG-002 |
| CONFIG-006 | Expression System Integration | 4-6h | CONFIG-001, TASK-006 |
Total: 64-86 hours
Cloud Service Node UX Improvement
Prerequisite cleanup task (can be done as part of CONFIG-003 or separately):
Problem
The existing "Config" node accesses Noodl Cloud Service (Parse Server) configuration. This will cause confusion with the new App Config system.
Solution
- Rename existing node:
Config→Noodl Cloud Config - Hide cloud nodes when no backend: If no cloud service is connected, hide ALL nodes in the "Cloud Data" category from the node picker
- Show guidance: Display "Please add a backend service" message in that category until a service is connected
- Preserve existing nodes: Don't break legacy projects - existing nodes continue to work, just hidden from picker
Files to modify:
packages/noodl-runtime/src/nodes/std-library/data/confignode.js- Renamepackages/noodl-editor/src/editor/src/views/nodepicker/- Category visibility logicpackages/noodl-runtime/src/nodelibraryexport.js- Update node name in exports
Integration Points
With DEPLOY-003 (Environment Profiles)
DEPLOY-003 can override Config values per environment:
App Setup Panel DEPLOY-003 Profiles
───────────────── ───────────────────
apiBaseUrl: "dev" → Production: "https://api.prod.com"
Staging: "https://api.staging.com"
Development: (uses default)
The App Setup panel shows canonical/default values. DEPLOY-003 shows environment-specific overrides.
With TASK-006 (Expression System)
The enhanced expression system will provide:
Noodl.Config.xxxaccess in expressions- Autocomplete for config keys
- Type hints
With Phase 5 (Capacitor Deployment)
PWA icon generation will be reused for Capacitor app icons:
- Same 512x512 source image
- Generate iOS/Android required sizes
- Include in platform-specific builds
Component Export Behavior
When exporting a component that uses Noodl.Config.primaryColor:
| Variable Type | Export Behavior |
|---|---|
| Custom variables | Hard-coded to current values |
| Default variables (appName, etc.) | Reference preserved |
The importer is responsible for updating hard-coded values if needed.
Testing Checklist
Manual Testing
- App Setup panel appears in sidebar
- Can edit all identity fields
- Can edit SEO fields (with defaults shown)
- Can enable/disable PWA section
- Can add custom variables with different types
- Color picker works for color type
- Array editor works for array type
- Categories group variables correctly
- App Config node shows all custom variables
- Selected variables appear as outputs
- Output types match variable types
Noodl.Config.xxxaccessible in expressions- SEO tags appear in built HTML
- manifest.json generated with correct values
- PWA icons auto-scaled from source
Build Testing
- Export includes correct meta tags
- manifest.json valid and complete
- Icons generated at all required sizes
- Theme color in HTML head
- Open Graph tags render correctly
Success Criteria
- Discoverable: New users find App Setup easily in sidebar
- Complete: SEO and PWA work without manual file editing
- Type-safe: Color variables show color pickers, arrays show array editors
- Non-breaking: Existing projects work, cloud nodes still function
- Extensible: DEPLOY-003 can override values per environment
Open Questions (Resolved)
| Question | Decision |
|---|---|
| Namespace name? | Noodl.Config |
| Static or reactive? | Static (immutable at runtime) |
| Panel location? | New top-level sidebar tab |
| PWA icons? | Single 512x512 source, auto-scaled |
| Categories required? | Optional, ungrouped → "Custom" |
| Loaded signal on node? | No, overkill for static values |
| ENV node name? | "App Config" |
References
- Existing project settings:
views/panels/ProjectSettingsPanel/ - Port type editors:
views/panels/propertyeditor/DataTypes/Ports.ts - HTML build processor:
utils/compilation/build/processors/html-processor.ts - Expression system:
TASK-006-expressions-overhaul/ - Deploy settings:
TASK-005-deployment-automation/DEPLOY-003-deploy-settings.md - Cloud config node:
noodl-runtime/src/nodes/std-library/data/confignode.js