---
title: "Configuration Basics"
description: "Write the microfrontends.json configuration file and wrap each Next.js config with withMicrofrontends."
canonical_url: "https://vercel.com/academy/microfrontends-on-vercel/configuration-basics"
md_url: "https://vercel.com/academy/microfrontends-on-vercel/configuration-basics.md"
docset_id: "vercel-academy"
doc_version: "1.0"
last_updated: "2026-04-09T08:06:03.258Z"
content_type: "lesson"
course: "microfrontends-on-vercel"
course_title: "Microfrontends on Vercel"
prerequisites:  []
---

<agent-instructions>
Vercel Academy — structured learning, not reference docs.
Lessons are sequenced.
Adapt commands to the human's actual environment (OS, package manager, shell, editor) — detect from project context or ask, don't assume.
The lesson shows one path; if the human's project diverges, adapt concepts to their setup.
Preserve the learning goal over literal steps.
Quizzes are pedagogical — engage, don't spoil.
Quiz answers are included for your reference.
</agent-instructions>

# Configuration Basics

# Configuration Basics

Add the routing configuration that tells Vercel which paths go to which apps.

## Outcome

Configure `microfrontends.json` for routing and wrap each Next.js config with `withMicrofrontends` to prevent asset conflicts.

## Two Configuration Files

Microfrontends require two types of configuration:

1. **`microfrontends.json`** - Defines routing (which paths go to which apps)
2. **`next.config.ts` wrapper** - Configures asset prefixes to prevent collisions

## Fast Track

1. Install `@vercel/microfrontends` in each app
2. Create `microfrontends.json` in the marketing (default) app
3. Wrap each `next.config.ts` with `withMicrofrontends`

## Hands-on Exercise 2.1

Configure the Acme Platform for microfrontends.

### Part 1: Install the Package

Add `@vercel/microfrontends` to each application using pnpm's workspace filter:

```bash
pnpm add @vercel/microfrontends --filter @acme/marketing
pnpm add @vercel/microfrontends --filter @acme/docs
pnpm add @vercel/microfrontends --filter @acme/dashboard
```

This installs the package in all three apps.

### Part 2: Create microfrontends.json

Create `apps/marketing/microfrontends.json`:

```json title="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
      }
    }
  }
}
```

Note: application names must match the `name` in each app's `package.json`. The default app uses `development.fallback` instead of `routing`. It catches everything not claimed by other apps.

### Part 3: Wrap Next.js Configs

Update each application's `next.config.ts` to use the wrapper.

**Marketing** (`apps/marketing/next.config.ts`):

```typescript title="apps/marketing/next.config.ts"
import type { NextConfig } from "next";
import { withMicrofrontends } from "@vercel/microfrontends/next/config";

const nextConfig: NextConfig = {
  // Your existing config
};

export default withMicrofrontends(nextConfig);
```

**Docs** (`apps/docs/next.config.ts`):

```typescript title="apps/docs/next.config.ts"
import type { NextConfig } from "next";
import { withMicrofrontends } from "@vercel/microfrontends/next/config";

const nextConfig: NextConfig = {
  basePath: "/docs",
};

export default withMicrofrontends(nextConfig);
```

**Dashboard** (`apps/dashboard/next.config.ts`):

```typescript title="apps/dashboard/next.config.ts"
import type { NextConfig } from "next";
import { withMicrofrontends } from "@vercel/microfrontends/next/config";

const nextConfig: NextConfig = {
  // No basePath - dashboard handles both /app/* and /settings/*
};

export default withMicrofrontends(nextConfig);
```

Use `basePath` when all routes share a common prefix (like `/docs`). Dashboard handles both `/app/*` and `/settings/*`, so no single basePath works. Routes are defined directly in the file structure.

### Part 4: Update App Route Structure

Child apps use `basePath` to set their mount point, so file paths are relative to that base. When a request hits `/docs/getting-started`, it's routed to the docs app (which has `basePath: "/docs"`), and Next.js looks for a route at `/getting-started` within that app.

**Docs app structure** (`apps/docs/app/`):

```
apps/docs/app/
├── page.tsx              # handles /docs (the base path)
├── [slug]/
│   └── page.tsx          # handles /docs/:slug
└── layout.tsx
```

Create `apps/docs/app/page.tsx`:

```tsx title="apps/docs/app/page.tsx"
export default function DocsHomePage() {
  return (
    <div className="max-w-4xl mx-auto p-8">
      <h1 className="text-3xl font-bold mb-2">Documentation</h1>
      <p className="text-gray-600 mb-8">
        Everything you need to build with Acme Platform.
      </p>
      <div className="grid gap-4">
        <a href="/docs/getting-started" className="block p-4 border rounded-lg hover:border-blue-500">
          <h2 className="font-semibold">Getting Started</h2>
          <p className="text-gray-600 text-sm">Learn the basics</p>
        </a>
        <a href="/docs/api" className="block p-4 border rounded-lg hover:border-blue-500">
          <h2 className="font-semibold">API Reference</h2>
          <p className="text-gray-600 text-sm">Complete API documentation</p>
        </a>
      </div>
    </div>
  );
}
```

**Dashboard app structure** (`apps/dashboard/app/`):

Without basePath, routes map directly to the file structure:

```
apps/dashboard/app/
├── app/
│   ├── page.tsx          # handles /app
│   └── projects/
│       └── page.tsx      # handles /app/projects
├── settings/
│   └── page.tsx          # handles /settings
└── layout.tsx
```

Create `apps/dashboard/app/app/page.tsx`:

```tsx title="apps/dashboard/app/app/page.tsx"
export default function DashboardPage() {
  return (
    <div>
      <h1 className="text-2xl font-bold mb-6">Dashboard Overview</h1>
      <div className="grid md:grid-cols-3 gap-4">
        <div className="bg-white p-6 rounded-lg border">
          <h2 className="text-gray-500 text-sm mb-1">Total Projects</h2>
          <p className="text-3xl font-bold">12</p>
        </div>
        <div className="bg-white p-6 rounded-lg border">
          <h2 className="text-gray-500 text-sm mb-1">Active Deployments</h2>
          <p className="text-3xl font-bold">8</p>
        </div>
      </div>
    </div>
  );
}
```

Create `apps/dashboard/app/settings/page.tsx`:

```tsx title="apps/dashboard/app/settings/page.tsx"
export default function SettingsPage() {
  return (
    <div>
      <h1 className="text-2xl font-bold mb-6">Settings</h1>
      <div className="bg-white rounded-lg border p-6 max-w-2xl">
        <h2 className="font-semibold mb-4">Account Settings</h2>
        <p className="text-gray-600">Manage your account settings here.</p>
      </div>
    </div>
  );
}
```

## Why Asset Prefixes Matter

Without `withMicrofrontends`, every app serves static assets at `/_next/`:

```
marketing: /_next/static/chunks/main.js
docs:      /_next/static/chunks/main.js  ← CONFLICT!
dashboard: /_next/static/chunks/main.js  ← CONFLICT!
```

The wrapper adds unique prefixes (an obfuscated hash like `vc-ap-b3331f`):

```
marketing: /_next/static/chunks/main.js
docs:      /vc-ap-a1b2c3/_next/static/chunks/main.js
dashboard: /vc-ap-d4e5f6/_next/static/chunks/main.js
```

This prevents JavaScript and CSS from one app overwriting another's.

## Try It

At this point, the apps still run independently. The configuration prepares them for the microfrontends proxy, which we'll enable in Lesson 2.3.

Run the apps:

```bash
pnpm dev
```

Visit each and verify the Header still renders correctly:

- **<http://localhost:3000>** - Marketing
- **<http://localhost:3001/docs>** - Docs
- **<http://localhost:3002/app>** - Dashboard

## Commit

```bash
git add -A
git commit -m "feat: add microfrontends configuration"
```

## Done-When

- [ ] `@vercel/microfrontends` installed in all three apps
- [ ] `microfrontends.json` created in marketing app with correct schema (using `paths` array)
- [ ] Application names in `microfrontends.json` match `package.json` names
- [ ] All `next.config.ts` files wrapped with `withMicrofrontends`
- [ ] Docs app has `basePath: "/docs"` configured
- [ ] Apps run without console errors

## Troubleshooting

**Asset 404s on `/_next/` paths**: You forgot `withMicrofrontends` in next.config.ts. Easy to miss.

**`does_not_match_schema` error**: You used `path` (string) instead of `paths` (array). The schema validator is picky about this.

**`application not_found` error**: The app name in microfrontends.json doesn't match package.json. Check for typos in `@acme/docs` vs `docs`.

## What's Next

Configuration done. Next lesson covers path routing in detail, including the execution order that trips up most developers.


---

[Full course index](/academy/llms.txt) · [Sitemap](/academy/sitemap.md)
