Vercel Logo

Local Development

The local proxy stitches your apps together so you can test microfrontends routing without deploying.

Outcome

Run all three applications through the microfrontends proxy at localhost:3024 with working cross-app navigation.

The Local Proxy

The @vercel/microfrontends package includes a development proxy that mimics Vercel's production routing locally:

localhost:3024 (proxy)
├── /              → localhost:3000 (marketing)
├── /pricing       → localhost:3000 (marketing)
├── /docs/*        → localhost:3001 (docs)
├── /app/*         → localhost:3002 (dashboard)
└── /settings/*    → localhost:3002 (dashboard)

When you visit localhost:3024/docs, the proxy routes to the docs app at localhost:3001.

Fast Track

  1. Add localProxyPort to microfrontends.json
  2. Run pnpm dev from the root
  3. Visit localhost:3024 to see the stitched application

Hands-on Exercise 2.3

Enable and test the local development proxy.

Part 1: Configure the Proxy Port

Update apps/marketing/microfrontends.json:

apps/marketing/microfrontends.json
{
  "$schema": "https://openapi.vercel.sh/microfrontends.json",
  "applications": {
    "@acme/marketing": {
      "development": {
        "fallback": "http://localhost:3000",
        "local": 3000
      }
    },
    "@acme/docs": {
      "routing": [
        {
          "paths": ["/docs", "/docs/:path*"]
        }
      ],
      "development": {
        "local": 3001
      }
    },
    "@acme/dashboard": {
      "routing": [
        {
          "paths": ["/app", "/app/:path*", "/settings", "/settings/:path*"]
        }
      ],
      "development": {
        "local": 3002
      }
    }
  },
  "options": {
    "localProxyPort": 3024
  }
}

development.local is the port each app runs on. development.fallback points to production when you're not running an app locally.

Part 2: Start All Apps

From the monorepo root:

pnpm dev

You should see output like:

• Packages in scope: @acme/ui, dashboard, docs, marketing
• Running dev in 3 packages

marketing:dev: ready - started server on 0.0.0.0:3000
docs:dev: ready - started server on 0.0.0.0:3001
dashboard:dev: ready - started server on 0.0.0.0:3002

The proxy starts automatically when Turborepo detects microfrontends configuration.

Part 3: Test Cross-App Navigation

Open http://localhost:3024 in your browser.

  1. Marketing homepage loads - You're at / served by marketing app
  2. Click "Docs" in the header - Navigates to /docs served by docs app
  3. Click "Dashboard" in the header - Navigates to /app served by dashboard app
  4. Click "Home" in the header - Back to / served by marketing app

All navigation happens through the same domain (localhost:3024), just like production.

Try It

Verify routing with the browser's network tab:

  1. Open DevTools → Network
  2. Visit localhost:3024/docs
  3. Look at the request - it's to localhost:3024/docs
  4. The proxy forwards it to localhost:3001/docs

You can also test that paths reach the correct app:

URLExpected AppExpected Page
localhost:3024/marketingHome
localhost:3024/pricingmarketingPricing
localhost:3024/docsdocsDocs index
localhost:3024/docs/apidocs(404 - page doesn't exist yet)
localhost:3024/appdashboardDashboard
localhost:3024/settingsdashboardSettings

Debugging Proxy Issues

If something isn't routing correctly, enable debug logging.

Check Proxy Status

The proxy logs which app it routes to:

[proxy] GET /docs → docs (localhost:3001)
[proxy] GET /app → dashboard (localhost:3002)

Common Issues

Proxy not starting: Check that localProxyPort is set in microfrontends.json.

Wrong app serves route: Your path pattern probably doesn't match what you think. Double-check the routing array.

Port 3024 already in use: Something else grabbed that port. Change localProxyPort or kill the other process.

Hybrid Local/Production Development

You can run some apps locally while pointing others to production:

apps/marketing/microfrontends.json
{
  "applications": {
    "@acme/marketing": {
      "development": {
        "fallback": "http://localhost:3000",
        "local": 3000
      }
    },
    "@acme/docs": {
      "routing": [
        {
          "paths": ["/docs", "/docs/:path*"]
        }
      ],
      "development": {
        "fallback": "https://docs.acme-platform.vercel.app"
      }
    }
  }
}

With this config, /docs/* routes to the production docs deployment while you develop marketing locally. Useful when you only need to work on one app.

With Turborepo 2.3.6+, the proxy starts automatically on turbo dev. Run a single app with turbo run dev --filter=marketing.

Commit

git add -A
git commit -m "feat: configure local development proxy"

Done-When

  • All three apps running through proxy at localhost:3024
  • Navigation between apps works (/, /docs, /app)
  • Each path serves content from the correct app
  • You understand hybrid local/production development

What's Next

Notice the hard page reloads when navigating between apps. No shared client-side router. Next, you'll build shared packages for components that need to appear across all apps.