Deploying Expo Projects
How to deploy an Expo Project to Freestyle
Expo is a framework for building cross-platform mobile apps.
While primarily used to create iOS and Android Apps, these apps can also be compiled to static websites and hosted on Freestyle.
This guide will walk you through the process of configuring and deploying an Expo app to Freestyle. This guide shows you how to deploy a Static
or SPA
Expo app. If you want to deploy a server-side rendered Expo app, the general same steps should apply, except for the server implementation.
Setup
If you don't have a pre-existing Expo app, run the command below to initialize it. It'll ask you where to put the app, for the purposes of this guide I'll be putting it in my-app
npx create-expo-app@latest
Once you've created the app, install the dependencies necessary for shipping it to website. react-dom
is necessary for React to render on the web, react-native-web
is for React Native to compile its components to html, and @expo/metro-runtime
is for Expo to be able to compile it's structures to web.
npx expo install react-dom react-native-web @expo/metro-runtime
Now you have an expo app ready to be deployed.
Deploying the App
Get your API key from the Freestyle dashboard, and create a .env file with the following content:
FREESTYLE_API_KEY=your-api-key
Install the Freestyle Sandboxes Client
npm i freestyle-sandboxes
Now you need a script to deploy the app. This is an example script that deploys the app.
It first creates a FreestyleSandboxes
client with your Freestyle API Key. then it calls .deployWeb
with two options: source
+ configuration
.
source
is an object of files to their file contents, you can write a custom function that takes your directory and prepares it for uploading, however we provide a series of utilities making it easy.
configuration
comes with anything other than the code you want to configure, that might be the domains, the entrypoint, the environment variables, or the network permissions.
import { FreestyleSandboxes } from "freestyle-sandboxes";
import { prepareDirForDeploymentSync } from "freestyle-sandboxes/utils";
// Create a sandboxes client
const sandboxes = new FreestyleSandboxes({
apiKey: process.env.FREESTYLE_API_KEY!,
});
async function deploy() {
await sandboxes.deployWeb(prepareDirForDeploymentSync("."), {
domains: ["example.style.dev"],
build: true, // This automatically detects the framework and configures/builds for you
});
}
deploy();
Finally, to make the deploy happen, run it
bun run deploy.ts
Preparing the App for Deployment
We run the command below to create a production build of your app for web.
npx expo export --platform web
Now, we slightly modify the output so that it works with freestyle module resolution by changing the dists node_modules
folder to modules
. Freestyle doesn't support uploading node_modules
as we have a special carveout for caching them, however expo build outputs a directory called dist/assets/node_modules
which we can rename to dist/assets/modules
so it will work.
This is an example way to do it
find dist -type f -name "*.js" -exec sed -i '' 's/node_modules/modules/g' {} +
mv dist/assets/node_modules dist/assets/modules
Creating a Server
By default, Expo outputs only static files. In order to serve them on Freestyle, we create a simple server using Hono, a lightweight web framework for Deno. This server will serve the static files generated by Expo.
First install hono
npm i hono
Then you can use the following code to serve the files.
import { Hono } from "hono";
import { serveStatic } from "hono/deno";
const app = new Hono();
app.use("*", serveStatic({ root: "./dist" }));
// fallback to index.html
app.get("*", serveStatic({ path: "./dist/index.html" }));
Deno.serve(app.fetch);
This setup works for both the expo output configurations of "output": "single"
and "output": "static"
, for "output": "server"
, use the server
entrypoint instead of creating a custom one.
If you want to run expo in server mode, with support for Expo API Routes, you can set the output to server
in your app.json
file.
{
"expo": {
"web": {
"bundler": "metro",
"output": "server"
}
}
}
Then, you'll need to create a simple entrypoint to run the server. Freestyle provides first class support for Expo server mode:
import { freestyleExpoServer } from "freestyle-sandboxes/expo";
freestyleExpoServer();
By default, this expects the output to be in the dist
folder, but you can override where the server and client files it pulls from are by passing the options
object to freestyleExpoServer
.
Deploying the App
CLI
Install the Freestyle CLI.
npm i freestyle-sh
Now deploy it
npx freestyle deploy --domain some.style.dev --web main.ts
API
You can also deploy the app using the API.
Get your API key from the Freestyle dashboard, and create a .env file with the following content:
FREESTYLE_API_KEY=your-api-key
Install the Freestyle Sandboxes Client
npm i freestyle-sandboxes
Now you need a script to deploy the app. This is an example script that deploys the app.
It first creates a FreestyleSandboxes
client with your Freestyle API Key. then it calls .deployWeb
with two options: source
+ configuration
.
source
is an object of files to their file contents, you can write a custom function that takes your directory and prepares it for uploading, however we provide a series of utilities making it easy.
configuration
comes with anything other than the code you want to configure, that might be the domains, the entrypoint, the environment variables, or the network permissions.
import { FreestyleSandboxes } from "freestyle-sandboxes";
import { prepareDirForDeploymentSync } from "freestyle-sandboxes/utils";
// Create a sandboxes client
const sandboxes = new FreestyleSandboxes({
apiKey: process.env.FREESTYLE_API_KEY!,
});
async function deploy() {
await sandboxes.deployWeb(prepareDirForDeploymentSync("."), {
entrypoint: "main.ts",
// put whatever domains you want here
domains: ["example.style.dev"],
});
}
deploy();
Finally, to make the deploy happen, run it
bun run deploy.ts
Next Steps
Now that you can deploy Expo apps to Freestyle, you'll probably want to deploy them to custom domains. To deploy to your own custom domains, you can use the UI in the Freestyle dashboard, and to start building self serve to deploy to your users domains you should check out this guide