When models from providers like Chutes or Cerebras were added via the admin panel, they didn't work in the builder page because the opencode.json config file only included the Ollama provider configuration. This fix adds Chutes and Cerebras provider configurations to the opencode.json file when their respective API keys are available in environment variables (CHUTES_API_KEY and CEREBRAS_API_KEY). Fixes the issue where chutes/deepseek-ai/DeepSeek-V3.2-TEE and similar models would fail to load from the builder page.
Shopify AI App Builder
An AI-powered platform for building complete, production-ready Shopify apps. Describe your app idea in plain English and let AI build it for you.
✅ Deploying to Portainer? The container now automatically fixes the "unexpected character \u200e" error! Environment variables are sanitized on startup. See the Quick Fix Guide for more details.
Features
- 🤖 AI-Powered Development - Describe your Shopify app and watch it being built in real-time
- 📦 Complete Apps - Get production-ready apps with proper structure, API integrations, and more
- ⚡ OpenCode Integration - Built on SST OpenCode for reliable code generation
- 📤 Easy Export - Download as ZIP or push directly to GitHub
- 🔧 Full Terminal Access - Make manual adjustments through the web terminal
- ☁️ Docker Ready - Deploy anywhere with the included Docker configuration
Quick Start
Prerequisites
- Docker and Docker Compose installed
- (Optional) GitHub Personal Access Token for version control
- (Optional) Dodo Payments API key for payment integration
- (Optional) Google OAuth credentials for authentication
1. Clone and Configure
# Clone the repository
git clone https://github.com/southseact-3d/shopify-ai.git
cd shopify-ai
# Copy environment template
cp .env.example .env
# Edit .env with your configuration (optional)
2. Build and Run
# Build the Docker image
docker compose build
# Start the service
docker compose up -d
3. Access the Application
- Homepage: http://localhost:4000
- App Builder: http://localhost:4000/builder
- Terminal: http://localhost:4001
Architecture
┌─────────────────────────────────────────────────────┐
│ Docker Container │
│ │
│ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Port 4000 │ │ Port 4001 │ │
│ │ Web App UI │ │ ttyd Terminal │ │
│ │ (Node.js) │ │ (PowerShell) │ │
│ └──────────────┘ └──────────────────────┘ │
│ │ │ │
│ └────────┬───────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ OpenCode │ │
│ │ AI Assistant │ │
│ └─────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ /home/web/data│ │
│ │ (Workspace) │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────┘
Configuration
Environment Variables
Payment setup: see the Dodo Payments guide in dodo.md.
| Variable | Description | Default |
|---|---|---|
CHAT_PORT |
Web UI port | 4000 |
ACCESS_PASSWORD |
Terminal password protection (leave empty for none) | - |
GITHUB_PAT |
GitHub Personal Access Token | - |
GITHUB_USERNAME |
GitHub username | - |
GITHUB_CLIENT_ID |
GitHub OAuth app client ID | - |
GITHUB_CLIENT_SECRET |
GitHub OAuth app client secret | - |
OPENROUTER_API_KEY |
OpenRouter API key used for planning mode | - |
OPENROUTER_API_URL |
OpenRouter API endpoint for planning | https://openrouter.ai/api/v1/chat/completions |
OPENROUTER_MODEL_PRIMARY |
Primary OpenRouter model for planning conversations | anthropic/claude-3.5-sonnet (fallback order) |
OPENROUTER_MODEL_BACKUP_1 |
Backup OpenRouter model #1 | openai/gpt-4o-mini (fallback order) |
OPENROUTER_MODEL_BACKUP_2 |
Backup OpenRouter model #2 | mistralai/mistral-large-latest (fallback order) |
OPENROUTER_MODEL_BACKUP_3 |
Backup OpenRouter model #3 | google/gemini-flash-1.5 (fallback order) |
OPENROUTER_DEFAULT_MODEL |
Final fallback model if none of the above resolve | openai/gpt-4o-mini |
OPENROUTER_PLAN_PROMPT_PATH |
Optional path to override the OpenRouter planning prompt file | chat/public/openrouter-plan-prompt.txt |
OPENROUTER_FALLBACK_MODELS |
Comma-separated additional fallback models for planning | - |
OLLAMA_API_URL |
Ollama self-hosted API URL for planning (e.g., http://localhost:11434) |
- |
OLLAMA_API_KEY |
Ollama API key for self-hosted instances (optional) | - |
DODO_PAYMENTS_API_KEY |
Dodo Payments API key | - |
DODO_PAYMENTS_ENV |
Dodo Payments environment (test or live) |
test |
DODO_TOPUP_PRODUCT_FREE |
Dodo product ID for the Free/Starter top-up | - |
DODO_TOPUP_PRODUCT_PLUS |
Dodo product ID for the Plus top-up | - |
DODO_TOPUP_PRODUCT_PRO |
Dodo product ID for the Pro top-up | - |
DODO_TOPUP_TOKENS_FREE |
Token credits for the Free/Starter top-up | 500000 |
DODO_TOPUP_TOKENS_PLUS |
Token credits for the Plus top-up | 1000000 |
DODO_TOPUP_TOKENS_PRO |
Token credits for the Pro top-up | 1000000 |
DODO_MIN_AMOUNT |
Minimum charge (in minor units) to enforce with discounts | 50 |
GOOGLE_CLIENT_ID |
Google OAuth client ID | - |
GOOGLE_CLIENT_SECRET |
Google OAuth secret | - |
PUBLIC_BASE_URL |
Optional base URL override for OAuth redirects | - |
SESSION_SECRET |
Session encryption key | - |
ADMIN_USER |
Admin username for the /admin dashboard |
admin |
ADMIN_PASSWORD |
Admin password for the /admin dashboard |
- |
ADMIN_SESSION_TTL_MS |
Admin session timeout in milliseconds | 86400000 (24h) |
COOKIE_SECURE |
Set to 1 to enable secure cookies (requires HTTPS) |
0 |
SMTP_HOST |
SMTP host for transactional emails | - |
SMTP_PORT |
SMTP port | 587 |
SMTP_SECURE |
Set to 1 to force TLS/SSL (usually port 465) |
0 |
SMTP_USER |
SMTP username | - |
SMTP_PASS |
SMTP password | - |
SMTP_FROM |
From email address for verification/reset emails | - |
EMAIL_VERIFICATION_TTL_MS |
How long verification links remain valid | 86400000 (24h) |
PASSWORD_RESET_TTL_MS |
How long password reset links remain valid | 3600000 (1h) |
⚠️ Emails (verification and password reset) are sent as branded HTML messages matching the app design. For images/assets to render correctly in emails, set
PUBLIC_BASE_URLto your site URL (e.g.https://app.example.com). IfPUBLIC_BASE_URLis not set, assets fallback to relative paths.
The planning prompt sent to OpenRouter can be edited at chat/public/openrouter-plan-prompt.txt (or by pointing OPENROUTER_PLAN_PROMPT_PATH to a different file).
Password Protection
To enable password protection for the terminal:
# In .env file
ACCESS_PASSWORD=your_secure_password
This will require authentication for the terminal (port 4001) with:
- Username:
user - Password:
<your_secure_password>
OAuth Sign-In Setup (Google + GitHub)
- Set redirect URLs
- Google:
https://your-domain.com/auth/google/callback - GitHub:
https://your-domain.com/auth/github/callback - For local testing use
http://localhost:4000/auth/<provider>/callback
- Google:
- Create credentials
- Google: In Cloud Console → APIs & Services → Credentials → OAuth Client ID (Web). Add the redirect URL above.
- GitHub: Go to https://github.com/settings/developers → OAuth Apps → New OAuth App. Set the callback URL above.
- Configure environment
- Add
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRETto.env,docker-compose.yml, or your stack. - If the app is behind a reverse proxy, set
PUBLIC_BASE_URL(e.g.,https://app.example.com) so callback URLs are generated correctly.
- Add
- Restart the service to apply the new credentials.
Building Shopify Apps
Using Templates
The builder includes quick-start templates for common Shopify apps:
- Product Recommendation Engine - Suggest products based on customer behavior
- Bulk Image Optimizer - Optimize product images in bulk
- Custom Shipping Rules - Create advanced shipping logic
- Discount Manager - Manage complex discount campaigns
Custom Apps
Simply describe what you want in the chat input:
Build a Shopify app that shows product recommendations based on
customer purchase history. Include an admin dashboard with analytics
and a theme app extension to display recommendations on the storefront.
The AI will:
- Create a complete app structure with necessary configuration
- Set up API integrations and webhooks
- Build the admin UI for the merchant
- Create storefront components or theme app extensions
- Generate documentation and setup instructions
Exporting Your App
- Click "Download as ZIP" in the sidebar
- Or push directly to GitHub using the version control panel
- The app is ready to deploy to Vercel, Railway, or any Node.js host
Deployment
Docker Compose (Recommended)
docker compose up -d
Portainer Stack
Use the included stack-portainer.yml for Portainer deployment.
📖 See PORTAINER.md for detailed deployment guide and troubleshooting.
Quick start:
- Go to Portainer → Stacks → Add Stack
- Upload or paste
stack-portainer.yml - Set environment variables
- Important: Manually type variable names and values - don't copy-paste to avoid invisible Unicode characters
- See PORTAINER.md for detailed instructions
- Deploy
Production Recommendations
- Use a reverse proxy (NGINX, Traefik, Caddy) for HTTPS
- Set strong
ACCESS_PASSWORDfor terminal authentication - Configure proper firewall rules
- Use Docker secrets for sensitive values
Development
Project Structure
shopify-ai/
├── chat/ # Web application
│ ├── server.js # Express server
│ └── public/ # Frontend files
│ ├── homepage.html # Landing page
│ ├── builder.html # App builder UI
│ ├── styles.css # Shared styles
│ └── app.js # Frontend JavaScript
├── scripts/ # Utility scripts
│ ├── entrypoint.sh # Container startup
│ └── healthcheck.sh # Health monitoring
├── profile/ # PowerShell profile
├── Dockerfile # Container definition
├── docker-compose.yml # Local development
└── stack-portainer.yml # Production deployment
Running Locally (Development)
cd chat
npm install
npm start
Troubleshooting
Portainer Deployment Error: "unexpected character \u200e"
If you see this error when deploying to Portainer:
Failed to deploy a stack: unable to get the environment from the env file:
failed to read /data/compose/42/stack.env: line 8: unexpected character "\u200e"
in variable name "ADMIN_USER\u200e=user"
This is caused by invisible Unicode characters (like U+200E Left-to-Right Mark) in your environment variables. This typically happens when copying and pasting from certain text editors or web pages.
Solution:
-
Option A - Use the cleanup script:
# Clean your .env file ./scripts/clean-env.sh .env -
Option B - Manually recreate the variables:
- In Portainer's environment variables editor, manually type (don't copy-paste) the variable names
- Or export the environment variables to a file, clean it, and re-import
-
Option C - Download a clean template:
# Use the clean .env.example as a starting point cp .env.example .env
OpenCode Not Working
# Inside the terminal, verify OpenCode is installed
opencode --version
# Check the OpenCode installation
ls -la /root/.opencode/
Port Already in Use
# Check what's using the port
lsof -i :4000
lsof -i :4001
# Or change ports in docker-compose.yml
Container Health Issues
# Check container logs
docker compose logs -f
# Check health status
docker compose ps
Security Notes
- This service exposes a web terminal - always use
ACCESS_PASSWORDin production - Never commit
.envfiles or secrets to version control - Use HTTPS in production with a reverse proxy
- Rotate credentials regularly
License
ISC
Support
For issues and feature requests, please open a GitHub issue.