Skip to main content
Pick a repository and Levelrail reads its file tree through the provider API (it never clones or runs your code), explains what it found, asks only for what it cannot guess, and then creates the app and starts the first build. Nothing exists until you press Deploy.

The flow

In the dashboard, New app walks through three steps:
  1. Where is it from. A connected provider’s repository list, or a pasted URL (with a one-shot deploy token for a private repository).
  2. What we found. One card per detected field (framework, build type, port, start and build commands, output directory, runtime version, health path), each with a Why popover listing the signals behind it, and a confidence badge for the whole result. Below the cards, every value is an editable field, warnings come with a suggested fix, and the environment variables found in .env.example, .env.sample, a compose file or the README are listed. Required ones must be filled in; values are never read from the repository, and secret-looking names get a masked field.
  3. Review and deploy. The exact list of what will be created. One click creates the databases, the app and its connections, links the repository, and starts the first build. You land on the live deploy view with the step trace and logs.
The flow survives a page reload: the repository and step are kept in sessionStorage (never tokens or env values), and the analysis is simply run again.

Explain it from the CLI

It prints the detection and every reason behind it, and creates nothing. --output json returns the full result, including the detection object: The same result comes from POST /api/v1/git-sources/analyze (body: repo_url, optional ref and directory), which reuses your connected provider credentials. It reads only and persists nothing. The older POST /api/v1/imports/analyze returns the same payload.

What is detected

Next.js (App Router or Pages Router, standalone output, static export), Vite and Create React App single page apps, Astro (static or with the Node adapter), SvelteKit (static adapter or Node), Nuxt, Remix, Express, Fastify, NestJS, Django, FastAPI, Flask, Rails, Laravel, Go net/http, Rust axum, Spring Boot, plain static HTML, and any repository with a Dockerfile. When signals conflict, the most specific framework wins: a Rails app with a package.json for its assets is Rails, and an Express server with a Dockerfile is built from the Dockerfile. A repository with several Dockerfiles uses the shallowest one and warns. A manifest that cannot be parsed falls back to matching its raw text, lowers the confidence, and warns.
Rust has no automatic build here yet. Detection still names it and warns; add a Dockerfile and it is built from that.

Monorepos

When the repository is a workspace (pnpm, npm, yarn, bun, Go workspaces, Nx or Turborepo), the What we found step lists its packages. Select the ones you want and press Create an app for each selected package. Each becomes its own app with the package directory as the build root and its watch paths applied, so a push only redeploys what it changed. You can also press Configure this one to take a single package through the normal steps. See Monorepos. Required environment variables are not asked for in the bulk action; add them on each app and redeploy.

Worked examples

These are the fixtures under test/fixtures. Output is abridged.

smoke/nextjs: a Dockerfile around Next.js

dogfood-nextjs: standalone output

Same as above, plus next.config.mjs sets output: 'standalone', so the server starts from .next/standalone. Port 3000, health /.

smoke/goapi: Go with a Dockerfile

A Go module with no dependencies has no go.sum; the warning only appears when go.mod has a require.

smoke/static: a Dockerfile serving static files

The Dockerfile decides: build type dockerfile, port 8080 from EXPOSE, no framework named. Remove the Dockerfile and the same files are detected as Static site, build type static, served on port 80.

monorepo: a workspace with no app at the root

Use Create an app for each selected package to get one app per service.

failing-build: no recognisable framework

Detection explains the setup; the build still fails at its own RUN step, which is what this fixture exists to show. See When a deploy fails.

Limits

  • Analysis reads at most a few dozen small files per repository (APP_WIZARD_MAX_FILES, APP_WIZARD_MAX_FILE_BYTES), so a huge tree can be partly read; a warning says so.
  • It works through the GitHub, GitLab and Gitea APIs. A host without a file API can still be connected by URL, but analysis answers that it cannot read it.
  • Port and health guesses for Express and Fastify are conventions, not facts. Check them against the server code.
Related: Deploying and managing apps, Git integrations, Monorepos.
Last modified on October 17, 2026