Skip to main content

Build #23 - theia Localhost Connection Fix - Checkpoint

Date: 2025-10-20 Status: 🟡 Partial Success - WebSocket Connected, UI Incomplete Build ID: 7e63dc06-950d-4ecb-a195-c006d1eab5e8 Image: us-central1-docker.pkg.dev/serene-voltage-464305-n2/coditect/coditect-combined:7e63dc06-950d-4ecb-a195-c006d1eab5e8


🎯 Executive Summary

Problem: User reported "localhost refused to connect" error preventing theia IDE from loading in production.

Root Cause: Hardcoded http://localhost:3000 in layout.tsx:86 and theia-embed.tsx:42. This broke nginx reverse proxy architecture where theia is accessed via /theia path, not direct localhost connection.

Solution: Changed to relative path /theia which nginx proxies to internal localhost:3000.

Outcome:

  • ✅ WebSocket connection successful (green indicator showing)
  • ✅ Tab visibility improved (clear borders, distinct styling)
  • ❌ theia UI incomplete (missing file manager, terminal, open files)

Critical Learning: Dockerfile copies pre-built dist/ from local machine. Must run npm run prototype:build locally before triggering Cloud Build.


📊 Build Saga Timeline

BuildDateStrategyResultRoot Cause
#19Oct 20 03:00Initial fix (layout.tsx, theia-embed.tsx)❌ FailedChanges not committed to git
#20Oct 20 03:15Committed changes❌ FailedDocker layer cache + old local dist/
#21Oct 20 03:30Touched vite.config.ts for cache invalidation❌ FailedOld local dist/ not rebuilt
#22Oct 20 03:45Added --no-cache flag❌ FailedOld local dist/ still not rebuilt
#23Oct 20 04:00Ran npm run prototype:build locally FIRST✅ SUCCESSNew dist/ with /theia fix

Duration: 5 builds, ~60 minutes debugging Key Insight: Dockerfile line 43 COPY dist /app/v5-frontend copies PRE-BUILT bundle from local machine, not from git source.


✅ COMPLETED - What We Fixed

1. Hardcoded Localhost URLs (CRITICAL FIX)

File: src/components/layout.tsx:86

// BEFORE
theiaUrl = 'http://localhost:3000', // ❌ Hardcoded

// AFTER
theiaUrl = import.meta.env.VITE_THEIA_URL || '/theia', // ✅ Relative path

File: src/components/theia-embed.tsx:42

// BEFORE
theiaUrl = 'http://localhost:3000', // ❌ Hardcoded

// AFTER
theiaUrl = import.meta.env.VITE_THEIA_URL || '/theia', // ✅ Relative path

Why This Works:

  • nginx reverse proxy at /theialocalhost:3000 (internal)
  • Browser loads iframe with relative path /theia
  • nginx handles WebSocket upgrade headers for terminal

2. WebSocket Connection Indicator (USER REQUEST)

File: src/components/connection-status.tsx (NEW)

  • 3 states: connected (green), connecting (yellow/pulsing), disconnected (red)
  • Tooltip with connection status
  • Size variants: sm/md/lg
  • Theme-aware styling

Integration: src/components/theia-embed.tsx:136-151

  • Positioned top-right with z-index 10
  • Semi-transparent black background with backdrop blur
  • Shows immediately when theia loads

Result: User confirmed "I have a successful websocket it is green"


3. Session Tab Visibility Improvements (USER REQUEST)

File: src/components/session-tabs/session-tab-manager.tsx

Changes:

  • Active tab: 2px blue border, white/dark-gray background, bold text
  • Inactive tabs: 1px gray border, light-gray background
  • Blue solid "+" button (was ghost - hard to see)
  • Clear hover states (gray.100 background)
  • Fixed duplicate _dark props (TypeScript compilation error)

Lines Modified:

  • 141-147: TabList styling (combined duplicate _dark props)
  • 150-197: Tab component styling (borders, backgrounds, transitions)
  • 201-217: "+" button (changed to solid blue variant)

User Complaint: "tabs not really showing" when created Resolution: Deployed in Build #23, awaiting user testing


4. Environment Variable Configuration

Files Modified: .env, .env.test

# Added
VITE_THEIA_URL=/theia

Purpose: Provides default for import.meta.env.VITE_THEIA_URL fallback


🔍 Critical Learnings

Learning #1: Docker Build Process (MOST IMPORTANT)

dockerfile.local-test Line 43:

# Copy pre-built V5 frontend (must exist from local build)
COPY dist /app/v5-frontend

What This Means:

  1. Cloud Build builds from git repository
  2. BUT Dockerfile copies dist/ from local machine (not git)
  3. Cloud Build executes on GCP builder VM, which has your git files
  4. The COPY dist happens during Docker image build, copying from the git workspace
  5. HOWEVER: If you don't rebuild dist/ locally after changing source, old bundle gets committed to git

Correct Workflow:

# Step 1: Make source code changes
vim src/components/layout.tsx

# Step 2: Build frontend locally (creates new dist/)
npm run prototype:build

# Step 3: Verify the fix is in the bundle
cat dist/assets/index-*.js | grep -o 'theiaUrl[^,}]*'
# Should show: theiaUrl:e="/theia"

# Step 4: Commit BOTH source and built dist/
git add src/components/layout.tsx dist/
git commit -m "fix: Replace localhost:3000 with /theia"
git push

# Step 5: Trigger Cloud Build (which copies committed dist/)
gcloud builds submit --config cloudbuild-combined.yaml .

Why Builds #19-22 Failed:

  • I changed source code ✅
  • I committed source code ✅
  • I did NOT rebuild dist/ locally ❌
  • Old bundle kept getting deployed ❌

Learning #2: Docker Layer Caching Behavior

What We Tried:

  1. Touching vite.config.ts to invalidate cache
  2. Adding --no-cache flag to docker build command

What We Learned:

  • These don't help if the source files being COPIED haven't changed
  • Docker caching is based on file modification times and content
  • If dist/ directory hasn't changed, layer cache is used
  • The REAL issue was that dist/ was old, not cache behavior

Correct Approach:

  • Fix the source problem (rebuild dist/)
  • Don't fight Docker caching

Learning #3: nginx Reverse Proxy Architecture

Configuration: nginx-combined.conf

location /theia {
rewrite ^/theia/(.*)$ /$1 break;
proxy_pass http://localhost:3000;
proxy_http_version 1.1;

# WebSocket support for terminal
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

# Standard headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

How It Works:

  1. Browser requests /theia
  2. nginx rewrites /theia/bundle.js/bundle.js
  3. Proxies to http://localhost:3000/bundle.js (theia Node.js process)
  4. theia responds with bundle
  5. WebSocket upgrade headers enable terminal connection

Critical: Both nginx (:80) and theia (:3000) run in SAME container


Learning #4: Debugging Production Bundles

Verification Commands:

# Check if bundle has the fix
kubectl exec -n coditect-app deployment/coditect-combined -- \
cat /app/v5-frontend/assets/index-*.js | grep -o 'theiaUrl[^,}]*'

# Expected output:
theiaUrl:e="/theia" # ✅ Fixed

# OLD broken output:
theiaUrl:e="http://localhost:3000" # ❌ Broken

Local Verification (before deploying):

npm run prototype:build
cat dist/assets/index-*.js | grep -o 'theiaUrl[^,}]*'

Why This Matters: Catches issues before wasting time on Cloud Build


❌ CURRENT ISSUE - theia UI Incomplete

Symptoms

User Report: "I cannot see the file manager the IDE is not completely functional no open files no command line prompt"

What Works:

  • ✅ WebSocket connection (green indicator)
  • ✅ theia HTML loads (verified with curl)
  • ✅ theia process running ("theia is ready!" in logs)
  • ✅ nginx reverse proxy working (HTTP 200 for /theia/bundle.js)

What Doesn't Work:

  • ❌ File manager/explorer not visible
  • ❌ terminal not showing (despite WebSocket connected)
  • ❌ No open files
  • ❌ IDE UI incomplete

Hypothesis: Asset Loading Path Issue

Investigation:

# Check theia HTML structure
kubectl exec -n coditect-app deployment/coditect-combined -- \
curl -s http://localhost:3000/ | head -50

Finding: theia HTML references assets with relative paths:

<script type="module" src="./bundle.js"></script>
<link rel="preload" href="./resources/preload.html">

Problem: When loaded via iframe at /theia, these relative paths may resolve incorrectly:

  • Browser URL: https://coditect.ai/theia
  • Relative asset: ./bundle.js
  • Browser resolves to: https://coditect.ai/bundle.js
  • Should resolve to: https://coditect.ai/theia/bundle.js

Possible Solutions

Option A: Configure theia Base Path

# In start-combined.sh
node lib/backend/main.js /workspace \
--hostname=0.0.0.0 \
--port=3000 \
--base-path=/theia # ← Add this flag

Option B: Adjust nginx Location Blocks

# Add specific location for theia assets
location /theia/bundle.js {
proxy_pass http://localhost:3000/bundle.js;
}

location /theia/resources/ {
proxy_pass http://localhost:3000/resources/;
}

Option C: Iframe Direct Connection (Not Recommended)

  • Load theia directly without nginx proxy
  • Loses routing flexibility
  • Requires theia to listen on external interface

Next Steps (Immediate)

  1. Ask user for browser console errors - See which assets are failing to load
  2. Test theia base-path option - Check if theia supports --base-path flag
  3. Review theia documentation - Look for reverse proxy configuration guidance
  4. Try nginx location rewrites - Add specific routes for theia assets

File to Modify: start-combined.sh:13 (theia startup command)


🔜 SPRINT 3 - Deferred UI Work

Per user's "Option A" choice, these are deferred until current theia issue is resolved:

Priority 1: SidePanel - Functional Tabs

llm Chat Tab (Currently placeholder text):

  • Create src/components/SidePanel/llmchat-panel.tsx
  • Chat message list (scrollable)
  • Prompt input (multi-line textarea)
  • File attachment button
  • Model selector dropdown
  • Token usage display

Sessions Tab (Currently placeholder text):

  • Create src/components/SidePanel/SessionsPanel.tsx
  • Show list from sessionStore.sessions
  • Highlight current session
  • Click to switch (call setCurrentSession())

Models Tab (Currently placeholder text):

  • Create src/components/SidePanel/ModelsPanel.tsx
  • Fetch from llmService.getModels()
  • Radio buttons for model selection
  • Show model metadata (size, context_length)
  • Mode selection (Single/Parallel/Sequential/Consensus)

Priority 2: Profile Page - Billing Information

File: src/pages/profile-page.tsx

Missing Fields (Backend supports, UI doesn't show):

  • company - Company name
  • phone - E.164 format (+1234567890)
  • address_line1 - Street address
  • address_line2 - Apt/Suite
  • city - City
  • state - 2-letter US state code
  • postal_code - ZIP code
  • country - ISO 3166-1 alpha-2 (US, CA, GB)

Implementation: Add Accordion or Tabs for "Billing Information" section


Priority 3: Navigation

File: src/components/header.tsx

Issue: No way to navigate back to IDE from Profile/Docs pages

Solutions:

  • Add "Back to IDE" button (when not on /ide route)
  • OR: Make logo always navigate to /ide
  • OR: Add breadcrumb navigation component

📚 Reference Documentation

Created During This Session:

  • UI-AUDIT-AND-FIXES.md - Complete audit of missing UI features (233 lines)
  • connection-status.tsx - WebSocket indicator component (85 lines)

Modified Files (Committed to Git):

  • src/components/layout.tsx - Fixed theiaUrl default
  • src/components/theia-embed.tsx - Fixed theiaUrl default, added ConnectionStatus
  • src/components/session-tabs/session-tab-manager.tsx - Improved tab visibility
  • .env, .env.test - Added VITE_THEIA_URL configuration
  • vite.config.ts - Updated build number (Build 21 cache invalidation attempt)
  • cloudbuild-combined.yaml - Added --no-cache flag (Build 22 attempt)

Key Backend Reference:

  • backend/src/models/models.rs:205-213 - User model with billing fields

🎯 Success Metrics

What We Achieved

MetricTargetActualStatus
WebSocket ConnectionWorking✅ Green indicator✅ SUCCESS
theia HTML LoadingHTTP 200HTTP 200✅ SUCCESS
Tab VisibilityClear distinction2px blue border✅ SUCCESS
Bundle Contains Fix/theia in bundleVerified✅ SUCCESS
Full IDE FunctionalityComplete UIPartial UI❌ INCOMPLETE

What User Confirmed Working

  1. ✅ "I have a successful websocket it is green"
  2. ✅ Authenticated and logged in to https://coditect.ai/ide
  3. ❌ "I cannot see the file manager the IDE is not completely functional"

🚨 Blockers & Risks

Current Blocker

Asset Loading Issue: theia UI not rendering completely despite WebSocket connection

Impact:

  • Cannot access file manager
  • Cannot use terminal (despite WebSocket connected)
  • Cannot open files
  • IDE unusable for actual development

Urgency: HIGH - User stated "this is the closest we have been to getting something actually working"

Risk: If not resolved, all other UI improvements are blocked


Technical Debt

Dockerfile Design: Copying pre-built dist/ from local is fragile

  • Pro: Faster builds (frontend pre-compiled)
  • Con: Easy to forget to rebuild locally
  • Con: Source and bundle can get out of sync

Recommendation: Consider multi-stage build that compiles frontend in Cloud Build, not locally


📖 How to Use This Checkpoint

If Resuming After Break

Start Here:

  1. Read "Current Issue - theia UI Incomplete" section
  2. Check browser console for asset loading errors
  3. Try "Possible Solutions" Option A (theia --base-path flag)
  4. Test in production: https://coditect.ai/ide

Quick Context:

  • We fixed localhost:3000 → /theia (DONE ✅)
  • WebSocket working (green indicator ✅)
  • UI incomplete (file manager missing ❌)
  • Hypothesis: Asset paths resolving incorrectly through nginx proxy

If Continuing Sprint 3

Prerequisites:

  • Current theia issue MUST be resolved first
  • Verify file manager, terminal, open files all working

Then Implement (in order):

  1. llmChatPanel component (highest user value)
  2. SessionsPanel component (integrates with existing sessionStore)
  3. ModelsPanel component (LM Studio integration)
  4. ProfilePage billing section (8 form fields)
  5. Header navigation (back to IDE button)

See: UI-AUDIT-AND-FIXES.md for detailed implementation plan


🎓 Lessons for Future Deployments

DO ✅

  1. Always rebuild dist/ locally before Cloud Build

    npm run prototype:build
    cat dist/assets/*.js | grep 'theiaUrl' # Verify fix
    git add src/ dist/
    gcloud builds submit
  2. Verify bundle contents before deploying

    kubectl exec deployment/coditect-combined -- \
    cat /app/v5-frontend/assets/*.js | grep 'searchTerm'
  3. Check browser console for client-side errors

    • Asset loading failures
    • CORS errors
    • WebSocket connection issues
  4. Test incrementally

    • Fix one thing at a time
    • Verify before moving to next issue

DON'T ❌

  1. Don't assume Docker cache is the problem - Check if source files actually changed first

  2. Don't skip local build verification - Always run npm run prototype:build and check bundle

  3. Don't commit code without testing bundle - Grep dist/ for critical values

  4. Don't fight Docker caching with flags - Fix the root cause (rebuild source)


📊 Build Metrics

Build #23 Details:

  • Build ID: 7e63dc06-950d-4ecb-a195-c006d1eab5e8
  • Duration: ~10 minutes (E2_HIGHCPU_32 machine)
  • Steps: 5 (build → push × 2 → deploy → verify)
  • Result: SUCCESS
  • Deployment: Rolled out to 3 pods successfully

Previous Failed Builds:

  • Build #19: 10m15s - SUCCESS (but wrong bundle)
  • Build #20: 10m22s - SUCCESS (but old cache)
  • Build #21: 10m18s - SUCCESS (cache invalidation attempt failed)
  • Build #22: 10m30s - SUCCESS (--no-cache didn't help)

Total Time Debugging: ~60 minutes across 5 builds


  • Main Checkpoint: docs/10-execution-plans/2025-10-16T19:15:00Z-SPRINT-1-TESTING-COMPLETE-SPRINT-2-READY-CHECKPOINT.md
  • UI Audit: UI-AUDIT-AND-FIXES.md (in project root)
  • Architecture: docs/DEFINITIVE-V5-architecture.md
  • Deployment Tracker: docs/10-execution-plans/deployment-step-by-step-tracker.md

Last Updated: 2025-10-20T04:30:00Z Next Session: Start with browser console error analysis for asset loading issue Estimated Time to Resolution: 1-2 hours (if --base-path flag works)

Status: 🟡 Partial Success - Major progress on localhost fix, WebSocket working, but theia UI rendering incomplete. This represents the closest we've been to a fully functional deployment.