ADR-008: EmProps Open Interface UI Integration into Monorepo
Date: 2025-10-18 Status: 🤔 Proposed Decision Makers: Architecture Team Related ADRs: None
Executive Summary
This ADR proposes integrating the emprops-open-interface (Next.js UI application) from its standalone repository into the emp-job-queue Turborepo monorepo. The integration consolidates the entire EmProps stack - from job queue and ComfyUI workers to the user-facing studio interface - into a single, unified codebase.
Current State:
- ✅ Job Queue & Workers - Fully integrated in monorepo (
apps/api,apps/worker,apps/monitor) - ✅ Machine Services - ComfyUI workers and connectors in monorepo (
apps/machines) - ❌ User Interface - Separate repo at
/Users/the_dusky/code/emprops/core-services/emprops-open-interface
Target State:
- ✅ Complete Stack - All components in single monorepo for unified development, deployment, and versioning
Key Decision: Should we migrate emprops-open-interface into the monorepo as apps/emprops-studio or apps/ui?
Table of Contents
- Context
- Problem Statement
- Decision
- Technical Architecture
- Implementation Strategy
- Dependency Analysis
- Migration Challenges
- Consequences
- Alternatives Considered
- Related Documentation
Context
Current System Architecture
The EmProps platform consists of three main components currently split across repositories:
┌─────────────────────────────────────────────────────────────┐
│ MONOREPO: emerge-turbo (emp-job-queue) │
│ │
│ apps/api → Job broker API (Express + Redis) │
│ apps/worker → Job workers (ComfyUI connectors) │
│ apps/monitor → Real-time monitoring UI (Next.js) │
│ apps/machines → ComfyUI container deployments │
│ packages/core → Shared types & Redis functions │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ SEPARATE REPO: emprops-open-interface │
│ │
│ Studio UI (Next.js 14) → User-facing creative studio │
│ - Workflow builder (Studio V2) │
│ - Asset management │
│ - NFT collection publishing │
│ - User authentication & profiles │
│ - Credit/payment system │
│ │
└─────────────────────────────────────────────────────────────┘Why They're Currently Separate
Historical reasons:
- Different teams/ownership (platform vs. UI)
- Different release cycles (backend stability vs. UI iteration)
- Different hosting platforms (Railway vs. Vercel)
- Different package managers (pnpm vs. yarn)
Why Integration Makes Sense Now
Technical benefits:
- Shared Types - Direct TypeScript type sharing for job definitions, API contracts
- Unified API Client - Studio UI can import
@emp/coretypes directly - Consistent Tooling - Single pnpm workspace, unified linting/formatting
- Atomic Commits - API + UI changes in single commit with type safety
- Simplified CI/CD - One pipeline, consistent deployment process
Developer Experience benefits:
- Single Repository - No context switching between repos
- Type Safety - Compile-time errors for API/UI mismatches
- Faster Iteration - Test full stack locally with single
pnpm devcommand - Better Documentation - All docs in one place
Problem Statement
Current Pain Points
1. Type Duplication
// emprops-open-interface/types/job.ts (duplicated)
interface GenerationRequest {
workflowId: string;
parameters: Record<string, any>;
}
// packages/core/src/types/job.ts (source of truth)
export interface JobRequest {
workflowId: string;
params: Record<string, unknown>;
}2. API Contract Sync Issues
- UI makes assumptions about API responses
- Breaking changes require coordinated PRs across repos
- No compile-time validation of API/UI integration
3. Development Workflow Friction
- Must run multiple repos simultaneously for full-stack development
- Changes to job queue require manual type updates in UI repo
- Testing requires coordinating versions across repositories
4. Deployment Complexity
- Separate CI/CD pipelines
- Versioning coordination challenges
- Environment variable duplication
Decision
PROPOSED: Migrate emprops-open-interface into the monorepo as apps/emprops-studio
Key Technical Decisions
1. Directory Structure
apps/
studio/ ← emprops-open-interface migrated here
pages/
components/
hooks/
clients/ ← Will use @emp/core types
public/
package.json ← Updated dependencies2. Package Management
- Convert from Yarn → pnpm to match monorepo
- Leverage workspace: packages for shared code
- Preserve existing dependencies where possible
3. API Client Integration
// apps/emprops-studio/clients/job-api-client.ts
import { JobRequest, JobStatus } from '@emp/core'; // ← Direct import
export class JobApiClient {
async submitJob(req: JobRequest): Promise<JobStatus> {
// Type-safe API calls
}
}4. Build & Development
// apps/emprops-studio/package.json
{
"scripts": {
"dev": "next dev --port 3001",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@emp/core": "workspace:*", // ← Monorepo dependency
"next": "^14.2.3",
// ... existing dependencies
}
}5. Environment Configuration
- Preserve existing .env structure for Studio
- Consolidate shared env vars (API URLs, Redis connection)
- Use monorepo env management patterns from other apps
Technical Architecture
emprops-open-interface Tech Stack (Current)
Framework & Core:
- Next.js 14.2.3 - React framework with App Router support
- TypeScript 5.0.4 - Type safety
- React 18.3.1 - UI library
State Management:
- Jotai 2.1.0 - Atomic state management
- SWR 2.2.5 - Data fetching and caching
UI & Styling:
- TailwindCSS 3.3.2 - Utility-first CSS
- Radix UI - Headless component primitives
- Framer Motion 11.3.28 - Animations
- Lucide React 0.396.0 - Icons
Blockchain Integration:
- Dynamic Labs - Web3 authentication
- Ethers.js 6.7.1 - Ethereum interactions
- Taquito - Tezos blockchain client
- Viem 2.28.4 - Ethereum utilities
Custom Packages (CRITICAL):
- @stakeordie/emprops-clients 0.1.6 - EmProps API clients
- @stakeordie/emprops-ui 0.4.23 - Shared UI components
- @stakeordie/sk8kit-ui-react 0.3.31 - UI component library
Analytics & Monitoring:
- PostHog - Product analytics
- Google Tag Manager - Marketing analytics
- OpenTelemetry - Observability
Integration Points
1. API Connections
// Current: apps/emprops-studio will connect to apps/api
Environment Variables:
- NEXT_PUBLIC_OPEN_API_URL=http://localhost:3000 // apps/api
- NEXT_PUBLIC_PLATFORM_API_URL=https://api.emprops.ai/api2. WebSocket Connections
// apps/emprops-studio will connect to apps/api WebSocket for real-time updates
- Job progress updates
- Machine status changes
- Generation completion events3. Type Sharing
// apps/emprops-studio/clients/job-client.ts
import {
JobRequest,
JobStatus,
WorkflowDefinition
} from '@emp/core';
// Direct type safety with job queueImplementation Strategy
Phase 1: Pre-Migration Setup ✅
1.1 Copy codebase to analysis directory
mkdir -p .refcode
cp -r /path/to/emprops-open-interface .refcode/1.2 Analyze dependencies
- Identify conflicts with existing monorepo packages
- Map custom packages (@stakeordie/*)
- Document environment variables
1.3 Create ADR (this document)
- Technical architecture analysis
- Migration strategy
- Risk assessment
Phase 2: Dependency Resolution 🔄
2.1 Convert package manager
# Remove Yarn artifacts
rm yarn.lock
rm -rf node_modules
# Initialize pnpm
pnpm install2.2 Update package.json
{
"name": "@emp/emprops-studio",
"dependencies": {
"@emp/core": "workspace:*",
// Keep existing Next.js dependencies
// Keep @stakeordie/* packages (external)
}
}2.3 Resolve dependency conflicts
- Check TypeScript version compatibility (core uses 5.x, studio uses 5.0.4) ✅
- Verify React version consistency (18.3.1) ✅
- Test build with monorepo structure
Phase 3: Code Migration 🔄
3.1 Create apps/emprops-studio directory
mkdir -p apps/emprops-studio3.2 Move source code
# Move all source directories
cp -r .refcode/emprops-open-interface/{pages,components,hooks,lib,public,styles,utils} apps/emprops-studio/
# Move configuration files
cp .refcode/emprops-open-interface/{next.config.js,tailwind.config.js,tsconfig.json} apps/emprops-studio/3.3 Update import paths
// OLD: import { Something } from '@/clients/emprops-api-client'
// NEW: import { JobRequest } from '@emp/core'
// Search and replace for core type imports3.4 Configure TypeScript
// apps/emprops-studio/tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"paths": {
"@/*": ["./"],
"@emp/core": ["../../packages/core/src"]
}
}
}Phase 4: Environment Configuration 🔄
4.1 Consolidate environment variables
# apps/emprops-studio/.env.local
NEXT_PUBLIC_OPEN_API_URL=http://localhost:3000 # Local apps/api
NEXT_PUBLIC_CDN_URL=https://cdn.emprops.ai
# ... preserve existing Studio env vars4.2 Update API client connections
// apps/emprops-studio/clients/job-api-client.ts
const apiUrl = process.env.NEXT_PUBLIC_OPEN_API_URL || 'http://localhost:3000';Phase 5: Testing & Validation 🔄
5.1 Local development
# Terminal 1: Start API
pnpm dev:api
# Terminal 2: Start Studio
pnpm dev:studio
# Verify: Full-stack workflow works5.2 Type safety validation
# Verify TypeScript compilation
pnpm typecheck
# Verify no type errors in Studio
cd apps/emprops-studio && pnpm typecheck5.3 Build validation
# Verify production build
pnpm build
# Verify Studio builds successfully
cd apps/emprops-studio && pnpm buildPhase 6: CI/CD Integration 🔄
6.1 Update GitHub Actions
# .github/workflows/ci.yml
jobs:
build-and-test:
steps:
- name: Build Studio
run: pnpm build --filter=@emp/emprops-studio6.2 Update deployment scripts
# scripts/deploy-studio.sh
pnpm build --filter=@emp/emprops-studio
# Deploy to Vercel or RailwayDependency Analysis
Critical External Dependencies
Custom Packages (Must Preserve):
{
"@stakeordie/emprops-clients": "^0.1.6", // EmProps API clients
"@stakeordie/emprops-ui": "^0.4.23", // Shared UI components
"@stakeordie/sk8kit-ui-react": "0.3.31" // UI component library
}These are external packages NOT in monorepo - must remain as npm dependencies
Monorepo Package Integration
New Dependencies (From Monorepo):
{
"@emp/core": "workspace:*" // Job types, Redis functions, shared utilities
}Potential Conflicts
1. TypeScript Version
- Monorepo: TypeScript 5.x
- Studio: TypeScript 5.0.4
- Resolution: ✅ Compatible - no conflict
2. React Version
- Monorepo: React 18.3.1
- Studio: React 18.3.1
- Resolution: ✅ Exact match - no conflict
3. Next.js Version
- Monitor app: Next.js 15.x
- Studio: Next.js 14.2.3
- Resolution: ⚠️ Different versions - Studio stays on 14.x until ready to upgrade
4. Package Manager
- Monorepo: pnpm (workspace protocol)
- Studio: yarn (currently)
- Resolution: 🔄 Convert Studio to pnpm
Migration Challenges
1. Custom Package Compatibility
Challenge: Studio depends on @stakeordie/* packages not in monorepo
Solution:
- Keep as external npm dependencies
- Document version requirements
- Consider future migration to monorepo if source available
2. API Client Type Mismatches
Challenge: Studio API client types may not match @emp/core
Solution:
// Create adapter layer if needed
// apps/emprops-studio/clients/api-adapter.ts
import { JobRequest as CoreJobRequest } from '@emp/core';
import { GenerationRequest as StudioRequest } from './types';
export function toJobRequest(req: StudioRequest): CoreJobRequest {
return {
workflowId: req.workflowId,
params: req.parameters,
// ... type mapping
};
}3. Environment Variable Management
Challenge: Studio has complex env configuration (.env, .env.local.dev, .env.staging, .env.prod)
Solution:
- Preserve Studio's env structure
- Use monorepo's encrypted env pattern for secrets
- Document env vars in
CRITICAL_ENV_VARS.md
4. Build Process Differences
Challenge: Studio has prebuild step (scripts/fetchContent.js)
Solution:
// apps/emprops-studio/package.json
{
"scripts": {
"prebuild": "node ./scripts/fetchContent.js || true",
"build": "next build"
}
}5. Asset/CDN Management
Challenge: Studio expects CDN for static assets
Solution:
- Preserve
NEXT_PUBLIC_CDN_URLenvironment variable - Keep existing asset structure
- Document CDN requirements
Consequences
Benefits ✅
1. Type Safety
- Compile-time validation of API/UI integration
- No more type duplication/drift
- Refactoring across stack with confidence
2. Developer Experience
- Single
git clonefor full stack - Unified development commands
- Consistent tooling (ESLint, Prettier, TypeScript)
3. Deployment Simplification
- Single CI/CD pipeline
- Coordinated releases
- Consistent versioning
4. Code Reuse
- Share utilities between apps
- Common UI components
- Unified error handling patterns
5. Documentation
- All docs in one place
- Clear architecture visibility
- Easier onboarding for new developers
Drawbacks ⚠️
1. Larger Repository
- More code to clone/maintain
- Longer CI/CD times (mitigated by Turborepo caching)
2. Migration Effort
- Initial setup time
- Risk of breaking existing Studio functionality
- Need comprehensive testing
3. Deployment Coupling
- Can't deploy Studio independently (actually can with Turbo filters)
- Version coordination required
4. Package Manager Change
- Convert from Yarn → pnpm
- Team must learn pnpm workspace patterns
Alternatives Considered
Alternative 1: Keep Separate Repositories
Approach: Maintain current split architecture
Pros:
- No migration effort
- Independent deployment cycles
- Smaller repository size
Cons:
- Type duplication continues
- API/UI integration errors at runtime only
- Development workflow friction
- Deployment coordination complexity
Decision: ❌ Rejected - Benefits of integration outweigh migration cost
Alternative 2: Git Submodule
Approach: Add emprops-open-interface as git submodule
Pros:
- Keep separate git history
- Can still have independent releases
Cons:
- Submodules are notoriously difficult to manage
- Still can't share types directly
- Developer experience worse than monorepo
- Deployment still complex
Decision: ❌ Rejected - Submodules add complexity without benefits
Alternative 3: Separate npm Package
Approach: Publish Studio as npm package, import in monorepo
Pros:
- Studio stays independent
- Clear versioning
Cons:
- Can't share types (npm package boundary)
- Additional build/publish step
- Defeats purpose of monorepo
Decision: ❌ Rejected - Doesn't solve type sharing problem
Related Documentation
Monorepo Documentation
- CLAUDE.md - Development guidelines
- DEPLOYMENT.md - Deployment procedures
- CRITICAL_ENV_VARS.md - Environment configuration
EmProps Open Interface Documentation
.refcode/emprops-open-interface/CLAUDE.md- UI architecture guide.refcode/emprops-open-interface/STUDIO_V2_REFACTOR_PLAN.md- Studio V2 architecture
Related ADRs
- None yet - this is the first UI integration ADR
Next Steps
- Review & Approval - Architecture team review this ADR
- Create Implementation Plan - Detailed task breakdown with estimates
- Proof of Concept - Test migration with minimal subset of Studio
- Full Migration - Execute phases 2-6
- Documentation Update - Update CLAUDE.md with Studio development patterns
- Team Training - Onboard team on monorepo Studio development
Decision Log
| Date | Decision | Rationale |
|---|---|---|
| 2025-10-18 | Proposed integration as apps/emprops-studio | Full-stack type safety, unified development |
| TBD | Approved/Rejected | After architecture review |
