For the complete documentation index, see llms.txt
Part 4: Production deployment
The DApp has no server code. The browser talks to Lace and the indexer directly, so any static host can serve it. This part deploys it to Vercel.
Vercel build configuration
vercel.json
sits in examples/leaderboard, which is the Vercel project's root directory:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": null,
"installCommand": "cd ../.. && npm ci",
"buildCommand": "cd ui && npm run build",
"outputDirectory": "ui/dist"
}
installCommandinstalls from the repository root. The example is one workspace of midnight-examples, and its dependencies and their pinned versions come from the rootpackage.jsonand lockfile.buildCommandbuildsui/: a TypeScript check, thenvite build.outputDirectoryis Vite's output. It holds the app and, throughpublicDir, the circuit keys, ZKIR, and integrity manifest.
Compiled contract output
Vercel has no Compact compiler, so the build can't run npm run compile. That is why
contract/managed/leaderboard/ is committed: the build serves the keys from there. If you change
the contract, run npm run compile (not compile:fast, which leaves out the proving keys) and
commit the result before you deploy.
Environment variables
The DApp reads three variables at build time. Vite builds them into the bundle, so they are public once the site is live:
| Variable | Required | Value |
|---|---|---|
VITE_BLOCKFROST_PROJECT_ID | Yes | A Blockfrost Midnight Preprod project ID, for reading the leaderboard. |
VITE_DEFAULT_CONTRACT | No | The address of the leaderboard the page opens with. Without it, visitors deploy or join one. |
VITE_NETWORK_ID | No | The network Lace must be on. Defaults to preprod. |
Deploy a leaderboard from your local DApp first (Part 3) and use its address as
VITE_DEFAULT_CONTRACT, so the site opens on a live leaderboard.
Deploy to Vercel
Fork midnight-examples on GitHub, then import it from the Vercel dashboard:
- Go to vercel.com and sign in with GitHub.
- Click Add New Project and import your fork of
midnight-examples. - Set Root Directory to
examples/leaderboard. Vercel readsvercel.jsonfrom there. - Under Environment Variables, add
VITE_BLOCKFROST_PROJECT_ID, and optionallyVITE_DEFAULT_CONTRACT. - Click Deploy.
Vercel redeploys whenever you push to the fork's default branch, and builds a preview deployment for every pull request.
Test the production deployment
Open your Vercel URL in a browser with Lace installed. The leaderboard loads from the indexer before you connect a wallet. Connect Lace, play a round, and submit a score. When the transaction is confirmed, the new entry appears in the table within a few seconds. Click Prove on it to check the ownership proof end to end.
Summary
| Component | Service |
|---|---|
| Frontend and circuit keys | Vercel (static files) |
| Chain | Midnight Preprod |
| Leaderboard reads | Blockfrost's Midnight Preprod indexer |
| Wallet, fees, and proof generation | Lace (proving is delegated to the wallet) |
| Test tokens | Preprod faucet |
This layout carries over to other Midnight DApps. The contract defines the on-chain logic, an API layer wraps it for TypeScript, and the frontend gets its providers from the wallet, so the site itself stays static.