Expose localhost via Cloudflare Tunnel with your custom domain. A simple alternative to ngrok.
npm install @tobigami-com/cftunnel> Expose localhost via Cloudflare Tunnel with your custom domain. A simple alternative to ngrok.


- š Persistent URLs - Use your custom domain instead of random URLs
- š Secure by Default - HTTPS via Cloudflare's global network
- ā” Auto-download - cloudflared binary downloads automatically if not present
- šļø Shopify Integration - Built-in support for Shopify CLI development
- ļæ½ Team Ready - Share credentials via git for easy team onboarding
``bash`
npm install -g @tobigami-com/cftunnel
`bash
git clone
cd your-project
$3
`bash
Step 1: Login to Cloudflare (one-time)
cloudflared login
ā Browser opens, select your domain
Step 2: Run setup wizard
cftunnel domain-setup
ā Enter your domain and Account ID
Step 3: Create .env
echo "VITE_HOST=dev-myapp" > .env
echo "VITE_PORT=3000" >> .envStep 4: Run tunnel
cftunnel dev
`Commands
| Command | Description |
| --------------------------- | ------------------------------------------ |
|
cftunnel dev | Start tunnel only (works with any project) |
| cftunnel shopify | Start tunnel + Shopify CLI together |
| cftunnel start | Start tunnel with specific hostname |
| cftunnel domain-setup | Interactive setup wizard |
| cftunnel setup | Quick copy cert.pem from ~/.cloudflared |Usage
$3
`bash
Start tunnel (reads VITE_HOST from .env)
cftunnel devCustom port
cftunnel dev -p 5000Custom hostname (override .env)
cftunnel dev --hostname my-app.example.com
`$3
For Shopify app development with persistent tunnel URL:
`bash
Tunnel + Shopify dev (port 5000)
cftunnel shopifyWith Firebase emulators
cftunnel shopify -eCustom port
cftunnel shopify -p 3000
`This runs:
`bash
shopify app dev --skip-dependencies-installation --tunnel-url https://your-subdomain.domain.com:5000
`$3
`bash
cftunnel start dev-myapp.example.com -p 3000
`Configuration
$3
`env
VITE_HOST=dev-myapp # Subdomain prefix or full hostname
VITE_PORT=3000 # Local port to tunnel
`VITE_HOST formats supported:
| Input | Result |
|-------|--------|
|
dev-myapp | dev-myapp.yourdomain.com |
| https://dev-myapp | dev-myapp.yourdomain.com |
| dev-myapp.yourdomain.com | dev-myapp.yourdomain.com |$3
Your project needs a
.cloudflared/ folder with:`
.cloudflared/
āāā cert.pem # From: cloudflared login
āāā account.json # From: cftunnel domain-setup
`account.json structure:
`json
{
"CF_SECRET_KEY": "auto-generated-secret",
"CF_ACCOUNT_TAG": "your-cloudflare-account-id",
"CF_HOST_PATTERN": "^dev-[a-zA-Z0-9-]+\\.yourdomain\\.com$"
}
`Team Setup
$3
`bash
cloudflared login
cftunnel domain-setup
git add -f .cloudflared/cert.pem .cloudflared/account.json
git commit -m "Add Cloudflare tunnel config"
git push
`$3
`bash
git clone
cd project
npm installCreate personal .env (use unique subdomain!)
echo "VITE_HOST=dev-yourname" > .env
echo "VITE_PORT=3000" >> .envcftunnel dev
`> ā ļø Important: Each team member should use a unique subdomain to avoid conflicts.
How It Works
`
Browser Request
ā
https://dev-myapp.yourdomain.com
ā
Cloudflare Edge (global CDN)
ā
cloudflared (tunnel daemon)
ā
http://localhost:3000
`Requirements
- Node.js 18+
- Cloudflare account with a domain added
- cloudflared (auto-downloaded if not present)
Troubleshooting
$3
Run setup wizard:
`bash
cloudflared login
cftunnel domain-setup
`$3
`bash
npx kill-port 3000
cftunnel dev
``Wait 1-2 minutes for DNS propagation after first tunnel start.
MIT