mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-12 15:22:55 +01:00
368 lines
15 KiB
Markdown
368 lines
15 KiB
Markdown
# 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
|
|
|
|
1. **No central place for app metadata**: App name, description, and SEO values are scattered or missing
|
|
2. **Global variables require node clutter**: Users create Object/Variables nodes at App level and wire them everywhere, creating visual noise
|
|
3. **No PWA support**: Users must manually create manifest.json and configure service workers
|
|
4. **SEO is an afterthought**: No built-in way to set meta tags, Open Graph, or favicon
|
|
5. **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`:
|
|
|
|
```javascript
|
|
// 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
|
|
|
|
1. **Config is static**: Values are "baked in" at app load - use Variables for runtime changes
|
|
2. **Type-aware editing**: Color picker for colors, array editor for arrays, etc.
|
|
3. **Required defaults**: Core metadata (name, description) always exists
|
|
4. **Expression + Node access**: Both `Noodl.Config.x` in expressions AND an App Config node
|
|
5. **Build-time injection**: SEO tags and PWA manifest generated during build/deploy
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### Data Model
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```json
|
|
{
|
|
"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](./CONFIG-001-infrastructure.md) | Core Infrastructure | 14-18h | None |
|
|
| [CONFIG-002](./CONFIG-002-app-setup-panel.md) | App Setup Panel UI | 18-24h | CONFIG-001 |
|
|
| [CONFIG-003](./CONFIG-003-app-config-node.md) | App Config Node | 10-14h | CONFIG-001 |
|
|
| [CONFIG-004](./CONFIG-004-seo-integration.md) | SEO Build Integration | 8-10h | CONFIG-001, CONFIG-002 |
|
|
| [CONFIG-005](./CONFIG-005-pwa-manifest.md) | PWA Manifest Generation | 10-14h | CONFIG-001, CONFIG-002 |
|
|
| [CONFIG-006](./CONFIG-006-expression-integration.md) | 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
|
|
|
|
1. **Rename existing node**: `Config` → `Noodl Cloud Config`
|
|
2. **Hide cloud nodes when no backend**: If no cloud service is connected, hide ALL nodes in the "Cloud Data" category from the node picker
|
|
3. **Show guidance**: Display "Please add a backend service" message in that category until a service is connected
|
|
4. **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` - Rename
|
|
- `packages/noodl-editor/src/editor/src/views/nodepicker/` - Category visibility logic
|
|
- `packages/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.xxx` access 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.xxx` accessible 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
|
|
|
|
1. **Discoverable**: New users find App Setup easily in sidebar
|
|
2. **Complete**: SEO and PWA work without manual file editing
|
|
3. **Type-safe**: Color variables show color pickers, arrays show array editors
|
|
4. **Non-breaking**: Existing projects work, cloud nodes still function
|
|
5. **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`
|