Bulk import apps from your Airtable table
Drag to reorder. Check to include.
Users are stored in Airtable. You can add their secrets there.
Leave blank for root, or use folders like "src/components/Button.js"
Creates nested folders if path includes "/"
Drop files here or click to browse
Any file type supported
Loading users...
Loading secrets hierarchy...
Select multiple apps or keep Global for all
Send these URLs to your customers so they can access their apps
Loading workspaces...
CSV Format:
UserID,Name,Email,IsAdmin,Status
USR-001,John Doe,john@example.com,true,active
USR-002,Jane Smith,jane@example.com,false,active
Remove process.exit(1) patterns so apps don't crash on missing env vars
Start typing to search across all applications...
Step 1: Click "Get Extractor Script" and run it on Replit to get SSH hosts. Step 2: Import the JSON file here.
App:
New repository name:
Apps serving placeholder page — need re-cloning from GitHub
Scanning apps...
Scans all apps — eliminates duplicates — syncs .env, app-config, tunnel & registry
| App | Registry | .env | Tunnel | Issue |
|---|
All ports fixed successfully!
Give this info to any AI assistant to connect
Hello! I am Loomis. This is my VPS server. I am an AI enthusiast and I see AI as a friend and collaborator. Please refer to me as Loomis. I appreciate your help in managing my server and apps!
Give the AI the following credentials so it can access your VPS through the Cloudflare tunnel and dashboard API. It can read/write files, manage apps, and run commands.
Give this info to any AI assistant to connect
Base ID: appW2k3f5Xw0sU88A · Managed by user-secrets-manager.js
Your personal developer secrets. Injected into every app you own (owner = Loomis / default). Fields: Name, Value. No AppName column — these are global to all your apps.
e.g. OPENAI_API_KEY, STABILITY_AI_API_KEY, GITHUB_ACCESS_TOKEN
One row per customer. Fields: UserID, Name, IsAdmin, Status. The UserID (e.g. loomyloo-BCJDVHA4ZW) is the key that links all other tables.
e.g. Billy Allen, Kaseema Green, Bianka, Teal Warren…
Every secret a customer needs. Fields: CustomerName, AppName, SecretKey, SecretValue. Linked to Users via CustomerName → Users.Name.
A special _APP_OWNER key marks app ownership (which user owns which app).
Note: AppName can be stored inconsistently. The code normalizes all variants and falls back to all user secrets when no app-specific match is found.
Registry of all apps. Fields: Name, Owner (customer name string), Entry Point, Github Repo, Notes. Synced on every deploy.
Source of truth for entry points. Owner connects app → user → their secrets.
safe-start.js.app-meta.json → gets the owner UserIDdefault → loads App Secrets (Loomis’s global keys)process.env — no dotenv neededStatic apps (HTML/CSS/JS served by static-serve.js) get no secrets — only their backend server app needs them.
NEVER push or pull from the GitHub repo without my explicit consent. Always ask before any git push or pull operation.
If something is broken, tell the AI to look at TROUBLESHOOTING.md at /var/www/Loomy-Server/TROUBLESHOOTING.md
The self-healing system is designed to be 100% AUTONOMOUS. It must handle ALL infrastructure issues without manual intervention. The goal is NOT for me to fix apps individually, but for the system to prevent/fix: duplicate ports (causing wrong apps to open), ghost processes, PM2 registration failures, Cloudflare misconfigurations, nginx errors, missing dependencies, hardcoded ports - EVERYTHING. If apps aren't running or wrong apps open when clicked, the self-healing code has failed its primary purpose. The next AI must understand: don't just fix the symptom, make the self-healing smarter to prevent it forever.
The server runs a self-healing monitor (self-healing-monitor.js) every 30 seconds that automatically fixes issues:
CRITICAL: The current self-healing code does NOT fix hardcoded ports well enough. Owner constantly finds apps with blank pages and has to manually fix them. You MUST check: If an app shows "online" in PM2 but displays blank/errors, the port is likely hardcoded. IMMEDIATE ACTION REQUIRED: Find the server file and change ANY hardcoded port (e.g., const port = 5000 or app.listen(3000)) to use process.env.PORT. Dynamic port delegation is KING. NO hardcoded fallback values like process.env.PORT || 3000 - just process.env.PORT. The assigned port is in .env file in the app directory.
PRO TIP: Converting any hardcoded port to backticks (const port = ``) also works really well - this forces the app to use the assigned port from environment variables.
CRITICAL - safe-start.js: The file /var/www/Loomy-Server/scripts/safe-start.js must NEVER have a hardcoded fallback port. The correct line is: const PORT = allSecrets.PORT || process.env.PORT || ; - NO || 3000 or any number. This was the root cause of apps starting on wrong ports causing 502 errors.
const port = process.env.PORT || ``;const port = ``;
const port = 3000;const port = process.env.PORT || 3000;
Key files: /var/www/Loomy-Server/self-healing-monitor.js, /tmp/heal-status.json (dashboard displays heal logs)
What is it?
The port registry is a JSON file that tracks every single port assigned to every single app on this server. Each app has one unique port. No two apps can ever share a port. This file is the master record — everything else (.env, app-config.json, Cloudflare tunnel) must match what this file says. If they drift out of sync, clicking an app URL opens the wrong app entirely.
Exact File Location — Memorize This
/var/www/Loomy-Server/config/port-registry-v2.json
This is NOT port-registry.json. It is port-registry-v2.json. Do not confuse them.
Why This Matters — Real Consequence
Loomis has spent over $2,500 and countless hours dealing with wrong apps opening when URLs are clicked. This happens when two apps get the same port. The first app to start wins the port — the second app silently fails or serves the wrong content. Customers click their app and see someone else's app. This is unacceptable and heartbreaking.
The Rules — No Exceptions
process.env.PORT only. No fallback like || 3000.ss -tlnp before assigning any port.How to Get the Next Free Port Safely
port-registry-v2.jsonss -tlnp to see what is currently listeningForking
Manage your app groups — saved to Airtable
Groups
Fork + open split workstation
Cloning
Compare and cross-edit two apps