Dartvel, home
Docs
Features
Studio
Cloud
Compared

Search the site

GitHub
pub.dev

GETTING STARTED

Getting started
Existing Flutter apps
Existing Native apps
Run on your phone

APP

UI and styling
Routing
State
Accessibility
Keyboard shortcuts
Localization
Devices and desktop
Native device access
Media, 3D and XR

DATA

Data models
Forms
Search
Sync and offline
Import and export
Change capture
Database
Cache
File storage
Images
Privacy and erasure

BACKEND

Backend functions
Auth and sessions
Authorization
Queues and jobs
Workers and memory
Notifications and mail
Outbound HTTP
AI
Webhooks
GraphQL and OpenAPI
API keys and OAuth
Multi-tenancy
Billing and commerce
Modules

OPERATIONS

Edge security
Secrets and environments
Monitoring
Releases

SHIPPING

Build targets
Telegram Mini Apps
Static web hosting
Servers and deploying

REFERENCE

Testing
CLI reference
Coding agents

SHIPPING

Servers and deploying

Run the generated backend as a web server, a job worker or a cron process.

Deploy it with dartvel deploy, or provision your own servers with dartvel infra.

ON THIS PAGE

Serve each page with its data and head tags

Run as web, worker or cron

Build one file with dartvel build web-server

dartvel build web-server writes build/server: one executable with your backend, the native server, the web app and the admin dashboard inside it.

The server reads each bundled asset when a request needs it. Compressed files are sent in that encoding when the browser accepts it; other requests use a decoded copy. Public files have ETags and byte ranges. Studio files stay private and are never kept in the asset cache.

DARTVEL_CACHE_DIR moves the disposable asset cache. Linux builds can also load deferred backend code from inside the executable on first use. Other hosts compile one code unit; the app uses the same page render path on every host.

$ dartvel build web-server
$ scp build/server you@host:/srv/shop/
$ ssh you@host "cd /srv/shop && ./server"

Copy code to clipboard

With no DATABASE_URL, the first run creates /srv/shop/dartvel_data/data.db next to the binary, with your models' tables in it. Back up that one folder.

DARTVEL_DATA_DIR moves dartvel_data somewhere else, such as a mounted volume.

Set DATABASE_URL to use PostgreSQL or MySQL. The binary does not migrate those on start: run dartvel db migrate.

With dartvel.admin.enabled on, the binary serves the admin at /__studio. dartvel.admin.path moves it.

Nobody can open the admin until you grant access. Being signed in is not enough, because every customer who signs up is signed in. Grant access to your own account, by the user id you sign in as, in the database the binary uses:

$ dartvel admin grant <user-id> --database /srv/shop/dartvel_data/data.db
$ dartvel admin list --database /srv/shop/dartvel_data/data.db
$ dartvel admin revoke <user-id> --database /srv/shop/dartvel_data/data.db

Copy code to clipboard

With DATABASE_URL set, leave out --database. Add --tenant when the account signs in on a tenant other than default.

Studio signs people in at /__studio/login, against your app's accounts, and does not need your app's own /login page. Signed in without a grant, it tells them the account may not open Studio; its files and API answer a stranger as a page that does not exist.

If your app already knows who its operators are, register your own rule instead: DV.Auth.authorization.registerAction('Studio.access', (caller, _) => ...). It replaces the grants.

A --profile development build serves the admin to anyone who can reach it, for local work. Never deploy one.

Build it on the kind of machine it runs on

build/server runs on the operating system and CPU it was built on. CI builds and runs it on Linux x64 and arm64, macOS arm64 and x64, and Windows x64 and arm64, where the file is build/server.exe. To deploy to a Linux arm64 server, build on Linux arm64.

macOS signing

The macOS binary has only the ad-hoc signature the Dart compiler gives it. CI runs a copy of it on the Mac that built it. A copy downloaded through a browser has not been tested.

Serve each page with its data and head tags

The server resolves the route, loads the page's data and writes the title, description, image, canonical link and JSON-LD before the app starts, so crawlers and link previews see the real page.

A hidden or unpublished record answers 404, and one the visitor may not see answers 401, without its data.

Page data can be awaited, cached for a while, served stale and refreshed, or left to the app. With a shared cache such as Redis, every instance serves what one of them resolved.

Public GET pages with compiled content keep the rendered HTML after the first request. Cookies, authorization, guarded routes and runtime data bypass this cache. Studio saves and publishes and successful OTA updates purge it. Set cache: false on a DVRoute in route config to opt out.

Safe pages send an ETag and require revalidation. Browsers and CDNs can reuse the same document with a 304 response, while a content change reaches the next request. The cache is bounded and local to each server process.

Partial

Spec section: Web Server Rendering

Planned work and implementation limits

Widgets are not rendered to HTML on each request. Crawlers get the text, links and headings the build captured from each page, and for a record's page the head tags and text written from its data.

Run as web, worker or cron

The generated backend reads its role and port from the environment.

DARTVEL_ROLE

Effect: web, worker or cron. With none, it serves HTTP and runs schedules

DARTVEL_PORT

Effect: The HTTP port. Else the host's PORT, else dartvel.backendPort

DARTVEL_QUEUE

Effect: The queues a worker works, comma separated

DARTVEL_HEALTH_PORT

Effect: /healthz for a worker or cron process

DATABASE_URL

Effect: The shared job queue and schedule leases

A value it cannot use, such as a port that is not a number, stops the process at startup.

Deploy with dartvel deploy

dartvel deploy --target web --provider vercel
dartvel deploy --target web --provider firebase-hosting
dartvel deploy --target server --environment staging
dartvel deploy --functions --function-target cloud-run

Copy code to clipboard

firebase-hosting

Runs: firebase deploy, from the firebase CLI

vercel

Runs: vercel --prod

netlify

Runs: netlify deploy --prod --dir=build/web

cloudflare

Runs: wrangler pages publish build/web

custom

Runs: Nothing. It builds, and you ship build/ yourself

--target is web, server or all. server builds web-server first.

It builds first, unless you pass --no-build.

Secrets the environment requires must resolve before anything ships.

--functions writes a deployment artifact per backend function into build/deploy: lambda, cloud-run, container, edge, fly, railway or bare-metal.

Uploads to Google Play, the App Store, TestFlight and Firebase App Distribution use dartvel deploy --store. See App stores.

Built

Spec section: Deployment

Implementation notes

dartvel deploy calls each host's own CLI. It holds no cloud credentials itself.

There is no plan or rollback step for dartvel deploy yet.

Provision servers with dartvel infra

# pubspec.yaml
dartvel:
  infra:
    production:
      hosts: [app1.example.com, app2.example.com]
      ssh: { user: deploy, knownHosts: infra/known_hosts }
      proxy: { adapter: caddy }
      tls:
        domains: [example.com]
        acme: { email: ops@example.com }
      services:
        backend: { instances: 2 }
        workers: { queues: [default, mail], instances: 1 }
        cron: { enabled: true }
      database:
        adapter: postgres
        backup: { schedule: "0 2 * * *", retain: 30d }

Copy code to clipboard

dartvel infra plan production --out plan.json
dartvel infra provision production --plan plan.json
dartvel infra check production

Copy code to clipboard

It connects over ssh and sets up Caddy, a firewall and a systemd unit per backend instance, worker and cron process.

An unknown key under dartvel.infra is refused.

provision asks before it removes anything, unless you pass --confirm-destructive.

Partial

Spec section: Server Provisioning

Planned work and implementation limits

It does not install the backend binary. Services stay stopped until something puts the server on the host.

Only the ssh adapter works, and it has not been run against a real host.

PREVIOUS Static web hosting dartvel build web on Apache or LiteSpeed
NEXT Testing DV.Test fakes, model factories and test modes
GitHub
pub.dev
npm
Acknowledgements
Privacy
Terms

FSL-1.1-MIT licensed. Built with Dartvel.

Dartvel is made by

SigmaDev Digital

To the bottom