Lyre / documentation
Get Lyre

Start commands by app type

A ready-to-copy start command for Vite, Next.js, Astro, a Node or Python API, static sites, Expo, Capacitor, Flutter and Docker.

On this page

Choose the stack you already have

First complete host preparation. Every recipe here describes a browser preview built from the tools your project already has installed.

Your project Recipe
React, Vue, Svelte or another Vite app Vite frontend
Next.js or Astro One web server
Frontend plus Node, FastAPI or another API Two services
HTML/CSS/JavaScript or an exported site Static site
React Native with Expo, or Capacitor Mobile project’s web target
Flutter with a web target Flutter web
Docker Compose, databases or several workers Larger stacks
Read these before copying

The commands below are examples for the standard script each project is named for. Open your package.json and your README first, and keep the framework version you already have.

Where the JSON goes

The snippets belong in lyre.json at the selected project root. Merge the relevant entries into a file that already exists. The fixed ports shown allow one local instance per port. See multiple workspaces when running several copies.

Vite: React, Vue, Svelte and similar frontends

  1. Open the folder with package.json

    Install its dependencies using its existing lockfile.

  2. Check that dev runs Vite

    Then add a preview service in the Scripts section of the project’s settings:

    {
      "scripts": {
        "preview": {
          "type": "service",
          "command": "npm run dev -- --host 127.0.0.1 --port 5173 --strictPort",
          "port": 5173
        }
      }
    }
  3. Using pnpm?

    The equivalent command is pnpm run dev --host 127.0.0.1 --port 5173 --strictPort. Keep whichever package manager the project already uses.

  4. Add a backend if you need one

    Add a backend service and a frontend API proxy.

  5. Start and try it

    Start preview, open it on your paired device, then test a click and one saved source edit.

--strictPort stops Vite silently moving to a different port. These commands also apply to SvelteKit projects whose dev script runs Vite. Vite server options →

It worked when

the preview loads at the port you configured and your edits show up.

Next.js or Astro: one web server

  1. Prepare the project

    Install its dependencies and set up its environment and development database using its README.

  2. Save the preview service

    For a Next.js dev script that runs next dev:

    {
      "scripts": {
        "preview": {
          "type": "service",
          "command": "npm run dev -- --hostname 127.0.0.1 --port 3000",
          "port": 3000
        }
      }
    }
  3. Astro instead?

    Use npm run dev -- --host 127.0.0.1 --port 4321 with port: 4321.

  4. Test a page and a server or API action

    Start preview and try both. Routes served by this same process need no second backend service. Add one only if you really have a separate API.

  5. Checking production mode

    Run the project’s build step first, then configure its documented production start command and port. A development preview does not publish a production deployment.

Keep your existing routing and adapters. A pure static export can use the next recipe. References: Next.js CLI and Astro CLI.

It worked when

a page loads and a server-side action or API route still responds.

A separate Node or Python backend

  1. Start from the worked example

    Follow the complete frontend and backend example, and keep its preview service.

  2. Name the backend service

    Call it backend. For Node, use the existing start script and make its listener read process.env.PASEO_PORT.

  3. Add a FastAPI or ASGI backend

    For an existing app at backend/main.py that exports app:

    {
      "scripts": {
        "backend": {
          "type": "service",
          "command": "python -m uvicorn main:app --app-dir backend --host 127.0.0.1 --port 8000",
          "port": 8000
        }
      }
    }
  4. Point Python at the right environment

    Use your environment’s own Python executable if python does not select it, and install its requirements in that environment first. Change main:app and the directory to your real module and application.

  5. Proxy and test

    Configure relative browser API requests and the frontend’s server-side proxy, then test a real API action after starting preview.

The JSON above is the backend entry to merge alongside your frontend. It is not a complete preview by itself. Django, Flask, Rails, Laravel and other HTTP backends follow the same service pattern with their own documented start commands and matching ports; Lyre does not infer their database, migration or authentication setup. Uvicorn settings →

It worked when

an action in the app calls your API and the response comes back.

Plain HTML or an exported static site

  1. Find the folder that holds index.html

    That is the folder with the real browser assets. If your project generates them, run its existing build or export first.

  2. Open the right folder as the project

    Either open that folder directly, or keep your source root and point a manual command at the output folder.

  3. Use the static preview proposal

    In an empty script draft, read Lyre’s static preview proposal, choose Add to draft and Save. It uses the bundled static server, so already-built files need no frontend package installation.

  4. Start it and follow the links

    Start preview, open the app and click through it on the paired device.

  5. Rebuild, then Refresh

    Rebuild when a source change affects generated output. Static serving does not give you hot reload that keeps state.

For manual setup, use your installed Lyre host CLI’s preview serve <output-folder> --port 5173 as a preview service with port: 5173. Replace the CLI path using your build’s CLI instructions. The static helper serves supported web assets, excludes private metadata, and has no SPA route fallback. Use your framework’s own server if refreshing a nested route has to rewrite it to index.html.

It worked when

index.html loads on the paired device and its links work.

Expo or Capacitor: preview the web target

  1. Use a project with web support

    For Expo, use a project with web support and its compatible web dependencies installed. Confirm its start script runs expo start.

  2. Save the preview service

    {
      "scripts": {
        "preview": {
          "type": "service",
          "command": "npm run start -- --web --localhost --port 8081",
          "port": 8081
        }
      }
    }
  3. Capacitor instead?

    Use the underlying web app’s command instead: a Vite frontend follows the Vite recipe, and already-built web assets follow the static recipe.

  4. Start and open it on the phone

    What you see is the web interface inside Lyre.

  5. Test native features separately

    Use the project’s normal native build and device workflow for those.

A native module with no web implementation will not start working because you are viewing it on a phone. Expo Go, a development client, Capacitor native plugins and App Store builds are separate delivery paths. Expo web setup →

It worked when

the web version of your app loads and responds on the phone.

Flutter with a web target

  1. Prepare Flutter

    Install the project’s compatible Flutter SDK, run flutter pub get, and confirm it has a web target. Standard detection expects pubspec.yaml, web/index.html and lib/main.dart.

  2. Save the preview service

    Add your own --target argument if your Dart entry point differs:

    {
      "scripts": {
        "preview": {
          "type": "service",
          "command": "flutter run -d web-server --web-hostname 127.0.0.1 --web-port 5173",
          "port": 5173
        }
      }
    }
  3. Wait for the ready message

    Start preview and wait for the terminal’s “is being served at” message. If the viewer opened early, refresh after that message appears.

  4. Use one preview client at a time

    Test an interaction. Paired Flutter viewing and several simultaneous debug clients need testing with your build.

  5. For a built web version

    Run flutter build web, serve build/web with the static recipe, and rebuild after source changes.

A Flutter web preview does not qualify native plugins and does not promise native hot reload. Flutter web builds →

It worked when

the Flutter app is served and responds to one interaction.

Docker, databases and larger stacks

Keep your existing Compose or task-runner setup if it already owns several processes. Lyre’s automatic app start selects one frontend and one named backend; it is not a general dependency graph.

  1. Prepare the stack

    Set up Docker, the project’s environment and its development data using its existing instructions.

  2. Expose the web entry point

    For an app already served by Compose, publish its web entry point on a known host loopback port, for example 127.0.0.1:8080:80. The container’s web server must listen on its container interface.

  3. Save one preview service for the stack

    {
      "scripts": {
        "preview": {
          "type": "service",
          "command": "docker compose up",
          "port": 8080
        }
      }
    }
  4. Keep Compose attached

    Do not add -d to this managed command. Set dependency order and health checks in Compose, and have the frontend route browser API requests to the backend inside the stack.

  5. Start it and check real data

    After stopping, run docker compose ps to check the stack’s state, and use its normal stop procedure if containers remain. Do not remove volumes to stop the preview.

Do not register a database as the preview

Do not register a database or worker as the app’s HTTP preview. Alternatively, start your existing database or queue separately and use Lyre’s two services for frontend and API. Container lifecycle, image builds and data management follow your existing tool. Verify them for your project. Compose up reference →

Host owners can also inspect containers and logs in Settings on a compatible computer with Docker or Podman installed.

It worked when

the preview serves your app and a real API or database action works.

Multiple workspaces and operating systems

Fixed ports are simple for one checkout. For several copies, leave port out and make the process read Lyre’s LYRE_PORT (or the compatible PASEO_PORT). A Node backend can read it directly; a Vite config can use server.port = Number(process.env.PASEO_PORT || 5173) with strictPort: true. The frontend’s server-side proxy can read PASEO_SERVICE_BACKEND_PORT to follow its companion.

macOS/Linux

In a shell, the variable starts with a dollar sign:

echo $PASEO_PORT

Windows

In Command Prompt, the variable is wrapped in percent signs:

echo %PASEO_PORT%

PowerShell

In PowerShell, the variable uses the env: prefix:

echo $env:PASEO_PORT
Match the shell Lyre actually launches

Reading the variable in your application code avoids shell-specific expansion entirely. Keep commands relative to the workspace, and use package-manager workspace or prefix options, or a quoted directory change, for nested apps.

New worktrees

A new worktree needs the committed project configuration plus its own dependencies and environment files.

It worked when

two copies of your project start at the same time without a port conflict.