|
| 1 | +# Deploying to Freestyle |
| 2 | + |
| 3 | +Deploy RivetKit app to [Freestyle.sh](https://freestyle.sh/), a cloud platform for running AI-generated code with built-in security and scalability. |
| 4 | + |
| 5 | +Freestyle provides built-in security for running untrusted AI-generated code, making it ideal for AI agent applications. Using Rivet, it is easy to deploy your vibe-coded or user-provided RivetKit backends straight to Freestyle. |
| 6 | + |
| 7 | +<CardGroup> |
| 8 | +<Card title="Freestyle + Rivet" href="https://github.com/rivet-dev/rivetkit/tree/main/examples/freestyle" target="_blank"> |
| 9 | +Complete example of deploying RivetKit app to Freestyle.sh. |
| 10 | +</Card> |
| 11 | +</CardGroup> |
| 12 | + |
| 13 | +## Setup |
| 14 | + |
| 15 | +<Steps> |
| 16 | +<Step title="Install packages"> |
| 17 | + |
| 18 | +Install RivetKit and Hono and create your registry: |
| 19 | + |
| 20 | +```bash |
| 21 | +npm install rivetkit hono |
| 22 | +``` |
| 23 | + |
| 24 | +</Step> |
| 25 | + |
| 26 | +<Step title="Configure serverless driver"> |
| 27 | + |
| 28 | +Update your server code to run the registry serverless with Deno. |
| 29 | + |
| 30 | +```typescript {{"title":"server.ts"}} |
| 31 | +import { registry } from "./registry"; |
| 32 | +import { createEngineDriver } from "npm:rivetkit/engine"; |
| 33 | +import { upgradeWebSocket } from "hono/deno"; |
| 34 | + |
| 35 | +const { fetch } = registry.start({ |
| 36 | + // Lets us serve the registry via our Deno.serve |
| 37 | + // as supported by Freestyle. |
| 38 | + disableDefaultServer: true, |
| 39 | + getUpgradeWebSocket: () => upgradeWebSocket, |
| 40 | + |
| 41 | + // Provide RivetKit address of our server |
| 42 | + overrideServerAddress: `${process.env.FREESTYLE_ENDPOINT ?? "http://localhost:8080"}/api`, |
| 43 | +}); |
| 44 | + |
| 45 | +// Freestyle uses Deno under the hood for web deployments |
| 46 | +// @ts-ignore |
| 47 | +Deno.serve(fetch); |
| 48 | +``` |
| 49 | + |
| 50 | +</Step> |
| 51 | + |
| 52 | +<Step title="Deploy to Freestyle"> |
| 53 | + |
| 54 | +Deploy your application to Freestyle with the correct configuration. Create a deployment script or add this to your existing deployment process: |
| 55 | + |
| 56 | +```typescript |
| 57 | +const FREESTYLE_DOMAIN = "my-domain.style.dev"; // Change to your desired Freestyle domain |
| 58 | + |
| 59 | +const res = await freestyle.deployWeb(buildDir, { |
| 60 | + envVars: { |
| 61 | + FREESTYLE_ENDPOINT: `https://${FREESTYLE_DOMAIN}`, |
| 62 | + RIVET_RUNNER_KIND: "serverless", |
| 63 | + // For self-hosted instances: |
| 64 | + // RIVET_ENDPOINT: "http://127.0.0.1:6420", |
| 65 | + RIVET_ENDPOINT: "api.rivet.gg", |
| 66 | + }, |
| 67 | + timeout: 60 * 5, // Increases max request lifetime on the runner |
| 68 | + entrypoint: "server.ts", // File which starts serverless runner |
| 69 | + domains: [FREESTYLE_DOMAIN], |
| 70 | + build: false, |
| 71 | +}); |
| 72 | +``` |
| 73 | + |
| 74 | +Details on `buildDir` and other settings are available on [Freestyle docs](https://docs.freestyle.sh/web/web). |
| 75 | + |
| 76 | +Run this deployment script to push your application to Freestyle. |
| 77 | + |
| 78 | +**Deployment Configuration:** |
| 79 | + |
| 80 | +- `timeout: 60 * 5` - Set timeout to 5 minutes for actor operations - it's important to keep this high |
| 81 | +- `entrypoint: "server.ts"` - Entry point file with your serverless setup |
| 82 | +- `domains` - Your Freestyle domain(s) |
| 83 | +- `build: false` - Disable build if you're pre-building your assets |
| 84 | + |
| 85 | +</Step> |
| 86 | + |
| 87 | +<Step title="Configure runner"> |
| 88 | + |
| 89 | +Update the runner configuration on the Rivet side to connect with your Freestyle deployment. Create a configuration script and run it after your Freestyle deployment is live: |
| 90 | + |
| 91 | +```typescript |
| 92 | +import { RivetClient } from "rivetkit/client"; |
| 93 | + |
| 94 | +const rivet = new RivetClient({ |
| 95 | + endpoint: "api.rivet.gg", |
| 96 | + token: process.env.RIVET_API_TOKEN, |
| 97 | +}); |
| 98 | + |
| 99 | +const FREESTYLE_DOMAIN = "my-domain.style.dev"; // Change to your desired Freestyle domain |
| 100 | +const RIVET_NAMESPACE = "my-rivet-namespace"; // Change to your Rivet namespace |
| 101 | + |
| 102 | +await rivet.runnerConfigs.upsert("freestyle-runner", { |
| 103 | + serverless: { |
| 104 | + url: `https://${FREESTYLE_DOMAIN}/start`, |
| 105 | + runnersMargin: 1, |
| 106 | + minRunners: 1, |
| 107 | + maxRunners: 1, |
| 108 | + slotsPerRunner: 1, |
| 109 | + // Must be shorter than Freestyle request `timeout` config |
| 110 | + requestLifespan: 60 * 5 - 5, |
| 111 | + }, |
| 112 | + namespace: RIVET_NAMESPACE, |
| 113 | +}); |
| 114 | +``` |
| 115 | + |
| 116 | +Execute this configuration script to register your Freestyle deployment with Rivet. |
| 117 | + |
| 118 | +**Runner Configuration:** |
| 119 | + |
| 120 | +- `url` - Freestyle deployment URL with `/start` endpoint |
| 121 | +- `runnersMargin` - Buffer of runners to maintain |
| 122 | +- `minRunners/maxRunners` - Scaling limits |
| 123 | +- `slotsPerRunner` - Concurrent actors per runner |
| 124 | +- `requestLifespan` - Request timeout (slightly less than Freestyle timeout) |
| 125 | + |
| 126 | +Once executed, Rivet will be connected to your Freestyle serverless instance. |
| 127 | + |
| 128 | +</Step> |
| 129 | + |
| 130 | +</Steps> |
0 commit comments