Deploying

Everything deloc deploy does, and how to bend it for monorepos, CI, custom build outputs, restricted access, and link previews.

The deploy pipeline

Every deploy goes through these steps:

  • Auth check — read token from config or DELOC_TOKEN; prompt login if missing.
  • Detect source — use --dir if given, otherwise look for a build output directory near the current folder.
  • Build if needed — if no build output exists and --no-build wasn't passed, run the project's build command.
  • Zip — archive the build output, skipping ignored patterns.
  • Validate — ensure an index.html is present, warn on suspicious filenames, check import maps.
  • Upload — POST to /api/upload with the zip and metadata.
  • Poll — wait for the API to finish processing (usually ~1s).
  • Output — print the URL and copy it to clipboard.

Framework detection

Deloc auto-detects common frameworks by scanning package.json scripts and checking for known output directories:

  • dist/ — Vite, Svelte, Vue, library builds
  • build/ — Create React App, Remix
  • out/ — Next.js static export
  • .next/ — Next.js (needs static export mode)
  • build-statics/ — custom builds

If your build output is elsewhere, pass --dir. If you already built it yourself, pass --no-build.

shell
deloc deploy                      # Detect everything
deloc deploy --dir ./public       # Custom output folder
deloc deploy --no-build           # Skip build, upload what's there
deloc deploy ./already-built      # Positional: treat dir as the deploy root
Next.js note
Next.js needs to be configured for static export (output: 'export' in next.config.js) to work with Deloc. Deloc serves static assets only — no server-side rendering at request time.

Naming and updating

The app name comes from --name, or falls back to your package.json name, or the current folder. It's slugified into the URL path.

shell
deloc deploy --name "Q3 Revenue Dashboard"
# → https://your-username.deloc.dev/q3-revenue-dashboard

Re-deploying from the same directory with the same name updates in place.The URL, password, domain restrictions, OG image, and data files all survive. Pass a new --name to publish a second copy.

Visibility and access control

Public (default)

No flags = public. Anyone with the URL can view. The free-tier Deloc branding badge renders in the bottom corner.

Password-protected

shell
deloc deploy --password              # Auto-generates a strong password
deloc deploy --password "Rev2026!"   # Set a specific password
deloc password my-app                # Change on an existing app
deloc password my-app --remove       # Remove protection

Viewers see a password gate served by the Cloudflare Worker before any static asset loads. Enter the password once per browser session.

Domain-restricted (Pro Unlimited and above)

shell
deloc deploy --domain-restrict company.com,partner.com

Viewers sign in with Google or Microsoft; only addresses under the allowed domains are granted access. No IT setup required on the customer side — anyone with a Google/Microsoft account at an allowed domain can view.

Flags
--password [value]Viewer password. Omit the value to auto-generate a strong one.
--publicRemove any existing password.
--domain-restrict <csv>Comma-separated email domains. Pro Unlimited+ only.

OG images for link previews

When someone pastes your URL into Slack, Teams, or iMessage, a preview card renders. Set a custom image with the og command:

shell
deloc og my-dashboard ./preview.png

PNG only. Max 2MB. Recommended 1200×630 (the standard Open Graph aspect). The image is served with proper OG and Twitter Card meta tags at every URL in the app.

What gets uploaded

The zip includes everything under your build output except:

  • node_modules/
  • .git/
  • .DS_Store and other OS junk
  • Patterns in any .gitignore at the root
Suspicious filename check
The CLI scans for files that look like secrets — .env, credentials.json, service-account.json, keys, certificates — and warns before upload. If one slips through, the static site is served as-is (these are readable). Always deploy a build output, not your source tree.

Tier-based size limits

TierPer-deploy capTotal storageBandwidth / app / month
Free50MB100MB1GB
Pro100MB1GB10GB
Pro Unlimited250MB5GB25GB
Team500MB10GB50GB
Enterprise1GBcustomcustom

Deploys over your per-deploy cap fail with a 413. Deploys that would push total storage over the cap fail with "Storage limit exceeded". Bandwidth overruns don't kill the app on paid tiers — they show a friendly upgrade page. On free tier, the Deloc badge upgrades to a prominent banner.

Deploying from CI

GitHub Actions example:

.github/workflows/deploy.yml
name: Deploy to Deloc
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: "20" }
      - run: npm ci
      - run: npm run build
      - run: npx @deloc/cli deploy --no-build --dir ./dist --name "main-dashboard"
        env:
          DELOC_TOKEN: ${{ secrets.DELOC_TOKEN }}

Create the token with deloc tokens create "GitHub Actions" on your machine, then store it in the repo's DELOC_TOKEN secret. See Account & tokens.