create-exotel-omni-app
v2.4.5
Published
CLI to generate Exotel Omni custom apps
Downloads
3,054
Readme
create-exotel-omni-app
CLI that scaffolds an Exotel Omni custom app as a Vite + React project using @exotel-npm-dev/signal-design-system (Exotel theme + MUI) and the Omni SDK (dynamic import() of ameyo-sdk.js).
Docs maintainers / Archbee: docs/ARCHBEE_OMNI_NPM_AND_AI_SECTION.md — paste into the Omni Custom Apps – Developer Guide. Generated apps ship DEVELOPER.md as the single on-disk doc (commands, AI rules, “do not touch” SDK wiring).
Requirements
- Node.js 18+
Usage
npx create-exotel-omni-appOr:
npm create exotel-omni-appGlobal install (command on your PATH is create-exotel-omni-app, not create-omni-app):
npm install -g create-exotel-omni-app
create-exotel-omni-appCheck which build you are running (global installs go stale easily):
create-exotel-omni-app --versionYou want 2.3.0+ to see “What do you want to create?” (new app vs template). If prompts jump straight to “Select use case:”, your shell is still using an older global package — run npm install -g create-exotel-omni-app@latest. Installing with npm i create-exotel-omni-app inside a repo folder only adds a local dependency; it does not update the global create-exotel-omni-app command unless you run it via npx create-exotel-omni-app from that folder or node node_modules/.bin/create-exotel-omni-app.
You will be prompted for an app folder name (no spaces — use hyphens/underscores, e.g. crm-configuration), then New app or Use a template. The CLI checks Node 18+ and npm, then asks to run npm install (default: yes).
- Template apps: choosing Yes runs
npm installand thennpm run shipautomatically, producingomni-upload.aaex(needszipon PATH). - New/blank app: choosing Yes runs
npm installonly (no auto-ship).
Use create-exotel-omni-app --skip-install to skip install and run commands manually.
Each generated app includes DEVELOPER.md (full guide + AI contract), docs/OMNI_TOOLBAR_SDK_REFERENCE.md (Omni Toolbar events/methods + sample payloads for agents), and a short GETTING_STARTED.md pointer. UI is responsive for different ECC slot widths; overlays use Signal (Drawer, StructuredDialog, Popover, Snackbar, etc.).
| Use case | UI | SDK registration (generated) |
|----------|----|------------------------------|
| New app | Blank placeholder; SDK line from OmniProvider | No event subscriptions |
| CRM Integration | Dummy CRM API after interaction detail; dispose summary on interactionDisposed | interactionConnected + interactionDisposed; merges getCurrentInteraction + one-shot hydration |
| Send SMS | Name/phone from merged interaction detail; send enabled after that | interactionConnected + merge / hydration (same as CRM) |
| Check order status | Order ID → sample order payload | No event subscriptions |
| Raise support ticket | Name/phone from merged interaction detail; create enabled after that | interactionConnected + merge / hydration (same as CRM) |
| Event listener | Full event timeline + invoke-method tab (debugger) | All interaction + session events |
Every app shows a compact top bar (about / environment icons with popovers) and SDK load / registration status below it.
After generate
Project folder = the directory that contains package.json. See DEVELOPER.md there for commands, AI instructions, and troubleshooting.
Fast path (after dependencies are installed):
cd <your-app-name>
npm run dev # local preview
npm run ship # build + omni-upload.aaex in one stepnpm run ship runs npm run build then npm run pack-omni.
Manual steps (same as before)
Replace <your-app-name> with the folder you created.
| Step | Where to run it | Command |
|------|-----------------|---------|
| 1 | Anywhere | cd <your-app-name> |
| 2 | Project folder | npm install (unless the CLI already ran it) |
| 3 | Project folder | npm run build |
| 4 | Project folder (not inside dist/) | npm run pack-omni |
Step 4 writes omni-upload.aaex next to package.json. It runs zip on dist/ for you (needs zip on your PATH — standard on macOS/Linux; on Windows use Git Bash or WSL).
Manual alternative (same archive layout): from the project folder, cd dist, then zip -r ../myapp.aaex . — the .aaex appears back in the project folder. Use any filename; keep the .aaex extension.
Upload: Admin → App Manager → upload the .aaex → select the slot for this app.
Local development (hot reload): npm run dev in the project folder only (not from dist/).
npm install must succeed before npm run build or npm run dev — otherwise Vite is missing.
Do not use npm audit fix --force
--force can upgrade Vite to v8 while @vitejs/plugin-react@4 only supports Vite 4–7, which breaks npm run dev / npm run build. Prefer ignoring moderate dev advisories or npm audit fix without --force.
If you already used --force: restore package.json (Vite 5.4.x, @vitejs/plugin-react 4.7.x, overrides), delete node_modules and package-lock.json, then npm install again.
npm run build runs Vite → dist/, copies manifest.json + logos, and writes asset-manifest.json.
dist/ layout (aligned with OmniSampleApp / CRA)
index.htmlstatic/js/— bundled JS (notassets/)static/css/— CSS (if any)static/media/— fonts/images from the bundlemanifest.json,asset-manifest.jsonlogo-small.png,logo-medium.png,logo-large.png
Build base and ECC URLs (fixes 404 on index-*.js)
Production builds use /si/{manifest.name}/{manifest.version}/ as Vite base when manifest.json in the project root has name and version (same path pattern as typical ECC custom apps). Example: name test, version 1.0.0 → script URLhttps://your-host/si/test/1.0.0/static/js/index.xxxxx.js.
Upload the entire
dist/tree — especiallystatic/js/. Ifindex.htmlis updated but old or missing JS is on the server, you get 404.Keep
manifest.jsonin sync with what you register on the server (name/versionmust match the/si/.../.../path), thennpm run buildagain.Override base if paths differ:
VITE_OMNI_BASE=/si/YourApp/1.0.0/ npm run buildvite devalways usesbase: '/'so localhost is unaffected.
Why ameyo-sdk.js might not appear in Network
If the main bundle (static/js/index-*.js) 404s, the React app never runs, so dynamic import() of the SDK never runs — fix the bundle URL / deploy first, then check for .../omniapp/sdk/ameyo-sdk.js.
Why zip from inside dist/?
ECC expects index.html and static/ at the root of the .aaex. Running zip -r ../app.aaex . after cd dist does that. Zipping a folder named dist from the parent often puts dist/ inside the archive and breaks paths.
Check the bundle: unzip -l omni-upload.aaex | grep static/js
Theme in Omni
The app uses exotelTheme from @exotel-npm-dev/signal-design-system with MUI ThemeProvider (CSS variables), same tokens as Signal’s ExotelThemeProvider, with iframe-friendly options (colorSchemeNode, noSsr, forceThemeRerender). The shell is light-only (no dark mode toggle).
SDK URL
Same as the static debugger: sdkBaseUrl or origin query param, else window.location.origin, then /omniapp/sdk/ameyo-sdk.js.
Breaking change (v2)
Scaffold is no longer a single static index.html. It is always a React + Vite app with Signal Design System.
Source lives under app/ (not src/) so the published npm package is not stripped by common .gitignore rules that ignore src/ — which caused incomplete installs in v2.0.0–2.0.1 if those files were never packed.
Maintainers: npm publish runs prepublishOnly to assert template/vite-app/app/** exists.
License
ISC
