Frontend Architecture
The apptor flow frontend is an Angular 18+ application built entirely with standalone components. It includes a visual workflow designer, an admin dashboard, AI-powered workflow creation, real-time execution monitoring, and the A2UI dynamic UI system.
Technology Stack
| Concern | Technology |
|---|---|
| Framework | Angular 18+ |
| Language | TypeScript |
| Diagram library | GoJS |
| State management | RxJS observables (service-based) |
| UI icons | react-icons (documentation site) / Angular Material (app) |
| HTTP | Angular HttpClient |
| Real-time | SSE (EventSource), WebSocket |
| Node config | assets/node-configurations.json |
Application Structure
src/app/
├── core/
│ ├── services/ ← Shared API services, auth, notifications
│ └── guards/ ← Route guards (authGuard, adminGuard, superAdminGuard)
├── features/
│ ├── auth/ ← Login, forgot password, reset password, OAuth callbacks
│ ├── dashboard/ ← Flows list, FlowsService
│ ├── workflow-designer/ ← GoJS designer, properties panel, toolbars, builders
│ ├── admin/ ← Admin dashboard, users, API keys, analytics
│ ├── public-workflow/ ← Public form execution, chat interface
│ ├── vector-store/ ← Knowledge base, RAG collections
│ └── ai-workflow-creator/ ← AI chat for workflow generation
└── shared/
└── components/
└── a2ui/ ← A2UI renderer and 24 component types
Routing
Public Routes (no auth required)
| Path | Component | Description |
|---|---|---|
/login | LoginComponent | Login page |
/forgot-password | ForgotPasswordComponent | Password reset request |
/reset-password | ResetPasswordComponent | Password reset form |
/auth/callback | AuthCallbackComponent | OIDC OAuth callback |
/oauth-callback | OAuthCallbackComponent | Integration OAuth callback |
/drive-oauth-callback | DriveOAuthCallbackComponent | Google Drive OAuth |
/w/:urlSlug | PublicFormComponent | Execute a published workflow |
/public/:urlSlug | PublicFormComponent | Execute a published workflow (alt URL) |
Authenticated App Routes
| Path | Component | Description |
|---|---|---|
/flows | DashboardComponent | All workflows list (default home) |
/designer/:processId | WorkflowDesignerComponent | Open a specific workflow in the designer |
/designer | WorkflowDesignerComponent | Open designer with no workflow |
/process-instances | ProcessInstancesComponent | Execution history (all workflows) |
/process-instances/:processId | ProcessInstancesComponent | Execution history (specific workflow) |
/process-instance/:instanceId/raw-data | RawDataViewComponent | Raw execution log data |
/connections | IntegrationsComponent | Integration/connection management |
/secrets | SecretsManagementComponent | Organization secrets |
/knowledge-base | VectorStoreComponent | RAG knowledge base collections |
/knowledge-base/:collectionId | CollectionDetailComponent | Individual collection |
/form-builder/:publishedWorkflowId | FormBuilderComponent | Form builder for published workflows |
/organization | OrganizationComponent | Organization settings |
Admin Routes (requires adminGuard)
| Path | Description |
|---|---|
/admin | Admin dashboard |
/admin/users | User management |
/admin/api-keys | API key management |
/admin/secrets | Secrets management |
/admin/settings | Organization settings |
/admin/integrations | Integration management |
/admin/idps | Identity provider management |
/admin/api-specs | OpenAPI spec management |
/admin/process-analytics | Process execution analytics |
/admin/ai-analytics | AI usage analytics |
/admin/dead-letter-queue | Failed message queue |
/admin/organizations | Super admin: all organizations |
/admin/verticals | Super admin: vertical integrations |
/admin/organizations/:orgId/overview | Org context: overview |
/admin/organizations/:orgId/users | Org context: users |
/admin/organizations/:orgId/api-keys | Org context: API keys |
Key Components
Workflow Designer
The designer is the core feature. It is composed of:
WorkflowDesignerComponent (container — app-workflow-designer)
├── SidebarPanelComponent ← Left: flows list, tabs
├── DesignerComponent ← Center: GoJS diagram canvas
│ └── (GoJS Diagram Library)
├── PropertiesPanelComponent ← Right: node property editor
├── DesignerToolbarComponent ← Top: save, publish, execute, layout toggle
├── ActionBrowserComponent ← Modal: node palette to add new nodes
├── ExecutionConsoleComponent ← Bottom: real-time execution logs (SSE)
├── TabBarComponent ← Multi-tab support (multiple open workflows)
├── VersionHistoryPanelComponent ← Slide-out: version history and publish
└── PublishConfirmationModalComponent ← Modal: publish confirmation
DesignerComponent (GoJS Integration)
The DesignerComponent wraps GoJS and handles:
- Node templates — custom GoJS templates per node type (icon, label, status indicator)
- Connection types — visually distinct line styles per connection type (sequenceFlow, trueFlow, falseFlow, errorFlow, timeoutFlow, toolConnection)
- Layout — left-to-right (LR) or top-to-bottom (TB), switchable from toolbar
- Execution highlighting — nodes flash/highlight as they execute (fed from SSE log stream)
- Events emitted:
- Node selected → PropertiesPanel opens
- Node double-click → PropertiesPanel focused
- Connection drawn → condition config opens if applicable
- Property changed → diagram updates,
hasUnsavedChangesset totrue
- Config:
src/app/features/workflow-designer/config/gojs-config.ts
PropertiesPanelComponent
The PropertiesPanelComponent is a dynamic form driven by the node definition from node-configurations.json. For each selected node it renders:
- The node's type-specific properties as form controls
- Conditional property visibility (properties that only show when another property has a specific value — controlled by
visibleWhenrules in the JSON config) - Common properties: timeout, retry, loop configuration
- For connections: connection type selector + JUEL condition expression editor
- Flow settings (when no node selected): workflow name, description, layout direction, global variables
Special property editors (custom components):
| Property Type | Component | Used For |
|---|---|---|
documentBuilder | DocumentBuilderComponent | MongoDB document construction |
multiDocumentBuilder | MultiDocumentBuilderComponent | Multiple MongoDB documents |
multiQueryEditor | MultiQueryEditorComponent | SQL multi-statement editor |
variableMappings | VariableMappingsComponent | Set Variable / output mappings |
pipelineBuilder | PipelineBuilderComponent | MongoDB aggregation pipeline |
fieldSelector | FieldSelectorComponent | Field selection from schema |
conditionalConfig | ConditionalConfigComponent | Conditional expression builder |
integrationSelect | IntegrationSelectComponent | Connection/integration picker |
connectionSelect | ConnectionSelectComponent | Connection picker (typed) |
collectionSelect | CollectionSelectComponent | Knowledge base collection picker |
domainActionSelect | DomainActionSelectorComponent | Domain action picker |
processDropdown | ProcessDropdownComponent | Workflow picker (for Call Process) |
code | CodeEditorComponent | Script editor (JS/Python) |
Key Services
FlowsService
Central service for workflow CRUD and state management.
API calls:
GET /api/flows→ load all workflowsGET /api/flows/:flowId→ load specific workflow definitionPOST /api/flows→ create workflowPUT /api/flows/:flowId→ save workflowDELETE /api/flows/:flowId→ delete workflow
Observables:
flows$— list of all workflowscurrentFlow$— currently open workflowhasUnsavedChanges$— dirty state flagisSaving$— save in progress
NodeConfigurationService
Loads and caches assets/node-configurations.json. Provides:
getNodeDefinition(nodeType)— get the full definition for a node typegetNodeProperties(nodeType)— get all properties for a node typegetCommonProperties()— timeout, retry, loop available on all nodes
WorkflowStateService
Tracks per-tab editing state:
- Which process is currently being edited
- Draft auto-save
- Multi-tab synchronization via
TabManagerService
PublicWorkflowSSEService
Manages the SSE connection for real-time execution log streaming. Connects to:
GET /process/instance/{processInstanceId}/logs
Returns Publisher<Event<ExecutionLogEntry>> and forwards log entries to the execution console.
A2UI System
A2UI (AI-to-UI) is the system where an AI Task node generates interactive UI components that are rendered live in the chat interface.
How it works
24 A2UI Component Types
Layout
| Component | Props |
|---|---|
A2UIRow | children, gap, align, justify, wrap, padding |
A2UIColumn | children, gap, align, justify, padding, layout |
A2UICard | child, title, subtitle, elevation, padding |
A2UITabs | tabs[], activeTab |
A2UIModal | children, title, open, closeAction, size |
A2UIDivider | orientation, thickness, color |
Display
| Component | Props |
|---|---|
A2UIText | text, usageHint (h1–h5/caption/body), color, align, weight |
A2UIImage | url, alt, usageHint, fit, width, height, borderRadius |
A2UIIcon | name, size (xs/sm/md/lg/xl), color |
A2UIBadge | text, variant (primary/secondary/success/error/warning/info), size |
A2UIProgressBar | value, max, showLabel, color, height |
Interactive
| Component | Props |
|---|---|
A2UIButton | child, action {name, context}, variant, size, disabled, loading, icon |
A2UITextField | text, label, type (shortText/number/date/longText), validationRegexp, required |
A2UITextArea | value, placeholder, label, rows, disabled, required, maxLength, resize |
A2UISelect | value, options[], placeholder, label, disabled, multiple |
A2UIMultipleChoice | selections, options[], maxAllowedSelections, label |
A2UICheckbox | value, label, disabled, indeterminate |
A2UIRadio | value, options[], label, orientation (horizontal/vertical) |
A2UISlider | value, min, max, step, label, marks[] |
A2UIDateTimeInput | value, type (date/time/datetime), label, min, max |
A2UIFileUpload | action, accept, multiple, maxSize, label, dragDrop |
Data
| Component | Props |
|---|---|
A2UIList | items, template, emptyText, keyField, loadMore |
A2UITable | data, columns[], sortable, selectable, pagination, emptyText |
A2UIDataCard | data, children |
Button actions trigger workflow continuation via the A2UIActionController (/a2ui/actions). The action name and context data are posted back to the backend, which resumes the workflow with the user's input.