Theia IDE Integration Options
Avoiding the Iframe Wrapper
Current Production: Theia runs in iframe at /theia with React wrapper around it
Goal: Deep integration with unified studio UI
Option 1: Theia as a Library (Recommended)
Use Theia's browser-only packages to compose your own IDE experience.
// Instead of iframe:
<iframe src="/theia" />
// Use Theia components directly:
import { FileNavigator } from '@theia/navigator/lib/browser';
import { MonacoEditor } from '@theia/monaco/lib/browser';
import { TerminalWidget } from '@theia/terminal/lib/browser';
function UnifiedStudio() {
return (
<div className="studio-layout">
<YourCustomSidebar>
<FileNavigator />
</YourCustomSidebar>
<YourCustomEditorArea>
<MonacoEditor />
</YourCustomEditorArea>
<YourCustomBottomPanel>
<TerminalWidget />
</YourCustomBottomPanel>
</div>
);
}
Pros
- ✅ Full control over layout and styling
- ✅ No iframe boundaries
- ✅ Share state with rest of app
- ✅ Custom chrome/tabs around Theia components
- ✅ Seamless theme integration
Cons
- ⚠️ Requires understanding Theia's DI container (Inversify)
- ⚠️ Must wire up services manually
- ⚠️ Breaking changes in Theia updates
Implementation
// lib/theia-container.ts
import { Container } from '@theia/core/shared/inversify';
import { createFileNavigatorContainer } from '@theia/navigator/lib/browser';
import { createMonacoEditorContainer } from '@theia/monaco/lib/browser';
export function createUnifiedStudioContainer() {
const container = new Container();
// Bind Theia services
container.load(createFileNavigatorContainer());
container.load(createMonacoEditorContainer());
container.load(createTerminalContainer());
// Bind your custom services
container.bind(YourCustomService).toSelf();
return container;
}
Option 2: Custom Theia Extension (What Production Currently Does)
Build a Theia extension that modifies the IDE from within.
// theia-app/src/browser/coditect-unified-module.ts
import { ContainerModule } from '@theia/core/shared/inversify';
import { ShellLayoutRestorer } from '@theia/core/lib/browser/shell/shell-layout-restorer';
import { CoditectShellLayoutRestorer } from './coditect-shell-layout';
export default new ContainerModule((bind, unbind, isBound, rebind) => {
// Replace Theia's default layout with unified studio layout
rebind(ShellLayoutRestorer).to(CoditectShellLayoutRestorer);
// Add custom title bar that communicates with parent
bind(CoditectTitleBar).toSelf().inSingletonScope();
bind(FrontendApplicationContribution).toService(CoditectTitleBar);
});
How It Works
- Theia builds with your custom extension
- Your extension modifies the DOM to match unified studio
- Use
postMessageto communicate with parent window - Hide Theia's default chrome, replace with yours
Pros
- ✅ Leverages Theia's full ecosystem
- ✅ VS Code extensions still work
- ✅ Can customize deeply
Cons
- ⚠️ Still technically in Theia's world
- ⚠️ Requires rebuilding Theia for changes
- ⚠️ Complex build process
Option 3: Monaco + xterm.js Only (Lightweight)
Build custom IDE using just Monaco editor and xterm.js terminal.
// components/monaco-ide.tsx
import Editor from '@monaco-editor/react';
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
export function CustomIDE() {
return (
<div className="ide-layout">
<FileExplorer
onFileSelect={handleFileOpen}
files={fileSystem}
/>
<div className="editor-area">
{openFiles.map(file => (
<Tab key={file.path} active={file.path === activeFile}>
<Editor
path={file.path}
defaultValue={file.content}
language={file.language}
/>
</Tab>
))}
</div>
<Terminal
onData={handleTerminalInput}
ref={terminalRef}
/>
</div>
);
}
Pros
- ✅ Lightweight (no Theia overhead)
- ✅ Full control
- ✅ Easy to customize
- ✅ Fast load times
Cons
- ⚠️ No VS Code extensions
- ⚠️ Must implement debugging, git, etc. yourself
- ⚠️ File system, search, etc. from scratch
Option 4: Reverse Proxy with Path Rewriting
Theia runs at root, unified studio overlays on top.
# nginx.conf
server {
listen 80;
# Theia IDE at /theia/*
location /theia/ {
proxy_pass http://theia:3000/;
proxy_set_header Host $host;
}
# Unified studio UI at /*
location / {
proxy_pass http://unified-studio:5173/;
}
}
Then use CSS to overlay unified studio chrome on Theia:
/* unified-studio-overlay.css */
.unified-header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 40px;
z-index: 9999;
}
/* Push Theia down to make room for header */
.theia-app {
margin-top: 40px !important;
}
Pros
- ✅ Theia runs natively
- ✅ VS Code extensions work
- ✅ Simple-ish setup
Cons
- ⚠️ CSS hacks are fragile
- ⚠️ Theia updates can break overlay
- ⚠️ Two separate apps to maintain
Option 5: Theia "Browser-Only" Composition
Use Theia's new browser-only packages (experimental but promising).
// Import specific Theia packages
import { createFileService } from '@theia/filesystem/lib/browser/file-service';
import { createWorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
import { createEditorManager } from '@theia/editor/lib/browser/editor-manager';
// Compose your own IDE
const fileService = createFileService();
const workspaceService = createWorkspaceService();
const editorManager = createEditorManager();
function MyIDE() {
return (
<TheiaFileTree fileService={fileService} />
<TheiaEditorManager manager={editorManager} />
<TheiaTerminal service={terminalService} />
);
}
Recommendation: Hybrid Approach
Unified Studio Architecture (No Iframe)
│
├─ Core: Next.js 14 + Tailwind (you control this)
│ ├─ Unified Header (CODITECT branded)
│ ├─ Module Tabs (Dev Studio | IDE | AI Studio | ...)
│ └─ State Management (Zustand)
│
├─ Module: Dev Studio (custom, no Theia)
│ └─ Chat + Viz panels (already built)
│
├─ Module: Theia IDE (Option 1 - Library approach)
│ ├─ FileNavigator from '@theia/navigator'
│ ├─ MonacoEditor from '@theia/monaco'
│ ├─ TerminalWidget from '@theia/terminal'
│ └─ Your custom chrome around them
│
├─ Module: AI Studio (custom + Theia Chat)
│ ├─ Custom chat panel
│ └─ TheiaChatWidget from '@theia/ai-chat-ui'
│
└─ Module: Pitch Deck (pure custom)
└─ No Theia needed
Implementation Priority
Phase 1: Keep Iframe (Short Term)
- Continue using iframe for Theia
- Build unified chrome around it
- Get to market faster
Phase 2: Component Extraction (Medium Term)
- Extract Monaco editor as library
- Extract terminal as library
- File explorer from Theia or custom
Phase 3: Full Integration (Long Term)
- Full Theia-as-library approach
- Complete control over IDE experience
- Share state across all modules
Code Example: Monaco Without Iframe
// components/editor/monaco-panel.tsx
'use client';
import Editor from '@monaco-editor/react';
import { useTheme } from 'next-themes';
interface MonacoPanelProps {
path: string;
content: string;
language?: string;
onChange?: (value: string) => void;
}
export function MonacoPanel({
path,
content,
language = 'typescript',
onChange
}: MonacoPanelProps) {
const { theme } = useTheme();
return (
<div className="h-full w-full rounded-lg overflow-hidden border">
<Editor
path={path}
defaultValue={content}
language={language}
theme={theme === 'dark' ? 'vs-dark' : 'light'}
onChange={onChange}
options={{
minimap: { enabled: true },
fontSize: 14,
lineNumbers: 'on',
roundedSelection: false,
scrollBeyondLastLine: false,
readOnly: false,
automaticLayout: true,
}}
/>
</div>
);
}
Decision Matrix
| Approach | Effort | Flexibility | VS Code Ext | Production Ready |
|---|---|---|---|---|
| Iframe (current) | Low | Low | ✅ | ✅ |
| Theia as Library | High | High | ✅ | ⚠️ |
| Custom Theia Ext | Medium | Medium | ✅ | ✅ |
| Monaco + xterm | Medium | Very High | ❌ | ✅ |
| Reverse Proxy | Low | Low | ✅ | ⚠️ |
My Recommendation
For immediate needs: Keep iframe, build unified chrome around it.
For 6-month horizon: Migrate to Monaco + xterm.js for Dev Studio module.
For IDE module: Keep Theia iframe OR invest in Theia-as-library.
The Monaco + xterm.js approach gives you the best balance of control and effort for a unified studio that feels cohesive.