# Vite Plugin: Automatic File-based Routing 🚦

SigPro provides an optional Vite plugin that automatically generates routes based on your file structure. No configuration needed - just create pages and they're instantly available with the correct paths.

## Why Use This Plugin?

While SigPro's router works perfectly with manually defined routes, this plugin:
- **Eliminates boilerplate** - No need to write route configurations
- **Enforces conventions** - Consistent URL structure across your app
- **Supports dynamic routes** - Use `[param]` syntax for parameters
- **Automatic code-splitting** - Each page becomes a separate chunk
- **Type-safe** (with JSDoc) - Routes follow your file structure

## Installation

The plugin is included with SigPro, but you need to add it to your Vite config:

```javascript
// vite.config.js
import { defineConfig } from 'vite';
import { sigproRouter } from 'sigpro';

export default defineConfig({
  plugins: [sigproRouter()]
});
```

## How It Works

The plugin scans your `src/pages` directory and automatically generates routes based on the file structure:

```
src/pages/
├── index.js              →  '/'
├── about.js              →  '/about'
├── blog/
│   ├── index.js          →  '/blog'
│   └── [slug].js         →  '/blog/:slug'
└── users/
    ├── [id].js           →  '/users/:id'
    └── [id]/edit.js      →  '/users/:id/edit'
```

## Usage

### 1. Enable the Plugin

Add the plugin to your Vite config as shown above.

### 2. Import the Generated Routes

Once you have the generated routes, using them with the router is straightforward:

```javascript
// main.js
import { $, html } from 'sigpro';
import { routes } from 'virtual:sigpro-routes';

// Simple usage
const router = $.router(routes);
document.body.appendChild(router);
```

Or directly in your template:

```javascript
// app.js
import { $, html } from 'sigpro';
import { routes } from 'virtual:sigpro-routes';

const App = () => html`
  <div class="app">
    <header>
      <h1>My Application</h1>
    </header>
    
    <main class="p-4 flex flex-col gap-4 mx-auto w-full">
      <div class="p-4 bg-base-100 rounded-box shadow-sm">
        ${$.router(routes)}
      </div>
    </main>
  </div>
`;

document.body.appendChild(App());
```

This approach keeps your template clean and lets the router handle all the page rendering automatically.

### 3. Create Pages

```javascript
// src/pages/index.js
import { $, html } from 'sigpro';

export default () => {
  return html`
    <div>
      <h1>Home Page</h1>
      <a href="#/about">About</a>
    </div>
  `;
};
```

```javascript
// src/pages/users/[id].js
import { $, html } from 'sigpro';

export default (params) => {
  const userId = params.id;
  
  return html`
    <div>
      <h1>User Profile: ${userId}</h1>
      <a href="#/users/${userId}/edit">Edit</a>
    </div>
  `;
};
```

## 📋 File-to-Route Mapping

### Static Routes

| File Path | Generated Route |
|-----------|-----------------|
| `src/pages/index.js` | `/` |
| `src/pages/about.js` | `/about` |
| `src/pages/contact/index.js` | `/contact` |
| `src/pages/blog/post.js` | `/blog/post` |

### Dynamic Routes

| File Path | Generated Route | Example URL |
|-----------|-----------------|-------------|
| `src/pages/users/[id].js` | `/users/:id` | `/users/42` |
| `src/pages/blog/[slug].js` | `/blog/:slug` | `/blog/hello-world` |
| `src/pages/users/[id]/posts/[pid].js` | `/users/:id/posts/:pid` | `/users/42/posts/123` |

### Nested Routes

| File Path | Generated Route | Notes |
|-----------|-----------------|-------|
| `src/pages/settings/index.js` | `/settings` | Index page |
| `src/pages/settings/profile.js` | `/settings/profile` | Sub-page |
| `src/pages/settings/security.js` | `/settings/security` | Sub-page |
| `src/pages/settings/[section].js` | `/settings/:section` | Dynamic section |

## 🎯 Advanced Examples

### Blog with Posts

```javascript
// src/pages/blog/index.js - Lists all posts
export default () => {
  const posts = $([]);
  
  $.effect(() => {
    fetch('/api/posts')
      .then(res => res.json())
      .then(data => posts(data));
  });
  
  return html`
    <div>
      <h1>Blog</h1>
      ${posts().map(post => html`
        <article>
          <h2><a href="#/blog/${post.slug}">${post.title}</a></h2>
          <p>${post.excerpt}</p>
        </article>
      `)}
    </div>
  `;
};
```

```javascript
// src/pages/blog/[slug].js - Single post
export default (params) => {
  const post = $(null);
  const slug = params.slug;
  
  $.effect(() => {
    fetch(`/api/posts/${slug}`)
      .then(res => res.json())
      .then(data => post(data));
  });
  
  return html`
    <div>
      <a href="#/blog">← Back to blog</a>
      ${() => post() ? html`
        <article>
          <h1>${post().title}</h1>
          <div>${post().content}</div>
        </article>
      ` : html`<div>Loading...</div>`}
    </div>
  `;
};
```

### Dashboard with Nested Sections

```javascript
// src/pages/dashboard/index.js
export default () => {
  return html`
    <div class="dashboard">
      <nav>
        <a href="#/dashboard">Overview</a>
        <a href="#/dashboard/analytics">Analytics</a>
        <a href="#/dashboard/settings">Settings</a>
      </nav>
      <main>
        <h1>Dashboard Overview</h1>
        <!-- Overview content -->
      </main>
    </div>
  `;
};
```

```javascript
// src/pages/dashboard/analytics.js
export default () => {
  return html`
    <div class="dashboard">
      <nav>
        <a href="#/dashboard">Overview</a>
        <a href="#/dashboard/analytics">Analytics</a>
        <a href="#/dashboard/settings">Settings</a>
      </nav>
      <main>
        <h1>Analytics</h1>
        <!-- Analytics content -->
      </main>
    </div>
  `;
};
```

### E-commerce Product Routes

```javascript
// src/pages/products/[category]/[id].js
export default (params) => {
  const { category, id } = params;
  const product = $(null);
  
  $.effect(() => {
    fetch(`/api/products/${category}/${id}`)
      .then(res => res.json())
      .then(data => product(data));
  });
  
  return html`
    <div class="product-page">
      <nav class="breadcrumbs">
        <a href="#/products">Products</a> &gt;
        <a href="#/products/${category}">${category}</a> &gt;
        <span>${id}</span>
      </nav>
      
      ${() => product() ? html`
        <div class="product">
          <h1>${product().name}</h1>
          <p class="price">$${product().price}</p>
          <p>${product().description}</p>
          <button @click=${() => addToCart(product())}>
            Add to Cart
          </button>
        </div>
      ` : html`<div>Loading...</div>`}
    </div>
  `;
};
```

## 🔧 Configuration Options

The plugin accepts an optional configuration object:

```javascript
// vite.config.js
import { defineConfig } from 'vite';
import { sigproRouter } from 'sigpro/vite';

export default defineConfig({
  plugins: [
    sigproRouter({
      pagesDir: 'src/pages',      // Default: 'src/pages'
      extensions: ['.js', '.jsx'], // Default: ['.js', '.jsx']
      exclude: ['**/_*', '**/components/**'] // Glob patterns to exclude
    })
  ]
});
```

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `pagesDir` | `string` | `'src/pages'` | Directory containing your pages |
| `extensions` | `string[]` | `['.js', '.jsx']` | File extensions to include |
| `exclude` | `string[]` | `[]` | Glob patterns to exclude |

## 🎯 Route Priority

The plugin automatically sorts routes to ensure correct matching:

1. **Static routes** take precedence over dynamic ones
2. **More specific routes** (deeper paths) come first
3. **Alphabetical order** for routes at the same level

Example sorting:
```
/users/new           (static, specific)
/users/[id]/edit     (dynamic, deeper)
/users/[id]          (dynamic, shallower)
/users/profile       (static, shallower)
```

## 📦 Output Example

When you import `virtual:sigpro-routes`, you get:

```javascript
// Generated module
import Page_0 from '/src/pages/index.js';
import Page_1 from '/src/pages/about.js';
import Page_2 from '/src/pages/blog/index.js';
import Page_3 from '/src/pages/blog/[slug].js';
import Page_4 from '/src/pages/users/[id].js';
import Page_5 from '/src/pages/users/[id]/edit.js';

export const routes = [
  { path: '/', component: Page_0 },
  { path: '/about', component: Page_1 },
  { path: '/blog', component: Page_2 },
  { path: '/blog/:slug', component: Page_3 },
  { path: '/users/:id', component: Page_4 },
  { path: '/users/:id/edit', component: Page_5 },
];
```

## 🚀 Performance Benefits

- **Automatic code splitting** - Each page becomes a separate chunk
- **Lazy loading ready** - Import pages dynamically
- **Tree shaking** - Only used routes are included

```javascript
// With dynamic imports (automatic with Vite)
const routes = [
  { path: '/', component: () => import('./pages/index.js') },
  { path: '/about', component: () => import('./pages/about.js') },
  // ...
];
```

## 💡 Pro Tips

### 1. Group Related Pages

```
src/pages/
├── dashboard/
│   ├── index.js
│   ├── analytics.js
│   └── settings.js
└── dashboard.js   # ❌ Don't mix with folder
```

### 2. Use Index Files for Clean URLs

```
✅ Good:
pages/blog/index.js      → /blog
pages/blog/post.js       → /blog/post

❌ Avoid:
pages/blog.js            → /blog (conflicts with folder)
```

### 3. Private Components

Prefix with underscore to exclude from routing:

```
src/pages/
├── index.js
├── about.js
└── _components/         # ❌ Not scanned
    └── Header.js
```

### 4. Layout Components

Create a layout wrapper in your main entry:

```javascript
// main.js
import { $, html } from 'sigpro';
import { routes } from 'virtual:sigpro-routes';

// Wrap all routes with layout
const routesWithLayout = routes.map(route => ({
  ...route,
  component: (params) => Layout(route.component(params))
}));

const router = $.router(routesWithLayout);
document.body.appendChild(router);
```

---

> **Note:** This plugin is completely optional. You can always define routes manually if you prefer. The plugin just saves you from writing boilerplate route configurations.

> **Pro Tip:** The plugin works great with hot module replacement (HMR) - add a new page and it's instantly available in your dev server without restarting!
