AvalonAvalon
GitHub

Modules

Organize your app into feature modules with co-located pages, layouts, and components.

Avalon uses a modular architecture where pages, layouts, and components are co-located by feature. Each module is a self-contained directory with its own pages, layouts, and components:

app/
  modules/
    home/
      pages/index.tsx
      layouts/_layout.tsx
      components/Hero.tsx
    blog/
      pages/index.tsx
      layouts/_layout.tsx
      components/PostCard.tsx
    docs/
      pages/introduction.mdx
      layouts/_layout.tsx
      components/Sidebar.tsx
  shared/
    layouts/_layout.tsx
    components/MobileNav.tsx
    styles/main.css

Configuration

Point Avalon at your modules directory in the Vite config:

const avalonPlugins = await avalon({
  modules: 'app/modules',
  layoutsDir: 'app/shared/layouts',
});

Or with full configuration:

const avalonPlugins = await avalon({
  modules: {
    dir: 'app/modules',
    pagesDirName: 'pages',     // default
    layoutsDirName: 'layouts', // default
  },
  layoutsDir: 'app/shared/layouts',
});

Route mapping

Module names map to URL prefixes. A module named blog serves pages under /blog:

ModuleFileURL
homepages/index.tsx/
blogpages/index.tsx/blog
blogpages/[slug].tsx/blog/:slug
docspages/introduction.mdx/docs/introduction

The home, root, main, and index module names are special — they map to / instead of /home.

Shared layouts

The layoutsDir option points to shared layouts that wrap all modules. A root layout at app/shared/layouts/_layout.tsx wraps every page, while module-specific layouts nest inside it.

Module layouts can skip shared layouts using layoutConfig:

export const layoutConfig = {
  skipLayouts: ['_layout'],
};

Shared code

Put components, styles, and utilities used across modules in a shared/ directory. Use path aliases for clean imports:

// vite.config.ts
resolve: {
  alias: [
    { find: '@shared', replacement: resolve('app/shared') },
    { find: '@modules', replacement: resolve('app/modules') },
  ],
}
// In any module
import MobileNav from '@shared/components/MobileNav.tsx';
import '@shared/styles/main.css';