Ionify is intentionally config-light. The goal is: a small, explicit config surface that maps to real pipeline behavior (graph versioning, CAS isolation, deps optimizer).

ionify.config.ts

Ionify looks for one of:

  • `ionify.config.ts`
  • `ionify.config.mts`
  • `ionify.config.js` / `ionify.config.mjs` / `ionify.config.cjs`

You can export an object or use `defineConfig`: ```ts import { defineConfig } from "@ionify/ionify";

export default defineConfig({ entry: "/src/main.tsx", }); ```

create-ionify

Scaffold a new project (optionally monorepo) via:

Common CLI flags:

  • `--template basic|dashboard`
  • `--monorepo` / `--no-monorepo`
  • `--testing vitest|playwright|both`
  • `--pm pnpm|npm|yarn|bun`
  • `--yes` (defaults)

Workspace identity (workspaces + monorepos)

Ionify automatically discovers the workspace root (pnpm/yarn/npm workspaces + Git submodules) and unifies state under the workspace `.ionify/` directory.

Ionify also sets these environment variables for engine components and tooling:

  • `IONIFY_WORKSPACE_ROOT`
  • `IONIFY_PROJECT_ROOT`
  • `IONIFY_STATE_DIR`
  • `IONIFY_WORKSPACE_ID`
  • `IONIFY_PROJECT_ID`

Scaffolding extras

The scaffolder can optionally configure:

  • AI assistant setup: `.cursorrules`, `.github/copilot-instructions.md`, and `docs/ai-prompts/`
  • Performance budget enforcement: Lighthouse config + CI workflow + a `performanceBudget` section in `ionify.config.ts`
  • Visual regression testing: Percy/Chromatic setup + example tests + CI workflow

performanceBudget

When enabled by the scaffolder, `performanceBudget` is used by the generated CI/scripts to fail builds when budgets are exceeded.

```ts import { defineConfig } from "@ionify/ionify";

export default defineConfig({ // Example (preset-based) performanceBudget: "strict", // "moderate" | "relaxed" | false }); ```

Generated files typically include:

  • `lighthouserc.json`
  • `.github/workflows/performance.yml`
  • `scripts/analyze-bundle.js`

Visual regression testing

When enabled by the scaffolder, visual tests run on CI and catch UI diffs before merge.

Generated files typically include:

  • `tests/visual/`
  • `.github/workflows/visual-tests.yml`
  • `percy.config.js` (or Chromatic config)

DX metrics

Ionify build/dev output reflects real engine state (CAS-first hydration + deterministic planning).

  • `ionify build` prints: Modules in plan, CAS hits, transforms needed, and total time.
  • `ionify analyze` summarizes `.ionify/` state (graph + packs + slimming when enabled).

root

`root` sets the project root directory Ionify uses for:

  • Resolving `entry` and imports
  • Locating env files (`.env*`)
  • Storing caches under `.ionify/` (CAS + deps artifacts)

Notes:

  • In a monorepo/workspace, Ionify stores `.ionify/` at the workspace root (shared across apps).

Defaults:

  • If you have an `ionify.config.*`, Ionify uses the config file’s directory
  • If you don’t, Ionify uses `process.cwd()`

Entry

  • `entry`: string or string[] (project-relative, `/src/...` is supported)

This feeds the graph and the build planner.

Resolve

```ts export default { resolve: { alias: { "@core": "/core", }, extensions: [".mjs", ".js", ".mts", ".ts", ".jsx", ".tsx", ".json"], conditions: ["import", "module", "browser", "default"], mainFields: ["module", "jsnext:main", "jsnext", "main"], }, }; ```

optimizeDeps (deps optimizer + packs)

Ionify’s deps optimizer serves node_modules through `/@deps/*` and caches deterministic artifacts under `.ionify/deps//`.

Core options:

  • `optimizeDeps.include: string[]` Pre-optimize these on dev server start (background pre-warm).
  • `optimizeDeps.exclude: string[]` Skip optimization and pack selection for these deps.
  • `optimizeDeps.bundleEsm: boolean` (default `true`) Bundle ESM deps into self-contained files to reduce request waterfalls.
  • `optimizeDeps.sourcemap: boolean` (default `false`) Sourcemaps for optimized deps.

sharedChunks

  • `optimizeDeps.sharedChunks: "auto" | boolean` Build shared chunks when optimizing multiple dep entries as one graph.

Notes:

  • Vendor packs require `sharedChunks !== false` to be effective.
  • For best request reduction, keep `bundleEsm=true` and `sourcemap=false`.

vendor (preloader)

  • `optimizeDeps.vendor: "auto" | string[] | false` Build a `vendor..js` preloader module to start fetching hot deps earlier.

This can improve cold-start waterfalls, but it does not collapse request count by itself.

vendorPacks (few-request mode)

`vendorPacks` is the real “few-request mode”: it bundles many deps into a small number of pack files, then Ionify rewrites imports to route through those packs.

Modes:

  • `false` Disable packs (default)
  • `true` Force one heuristic “app vendor” pack
  • `"auto"` Progressive layered vendor: build core first, then lazy-build feature packs in the background when the graph proves they’re needed
  • `{ [packName]: string[] }` Manual packs

Auto-selection caps:

  • `optimizeDeps.vendorPackMaxBytes: number` (default: 600KB)
  • `optimizeDeps.vendorPackMaxMembers: number` (default: 25)

packSlimming (usage-driven)

  • `optimizeDeps.packSlimming: "auto" | boolean`

When enabled, Ionify writes a deterministic usage index (`deps-usage.v1.json`) and builds usage-minimized pack variants in the background. On warm reload, Ionify prefers the slim pack if it’s ready, otherwise falls back to the base pack or `/@deps/*` wrappers.

Example (recommended progressive config): ```ts import { defineConfig } from "@ionify/ionify";

export default defineConfig({ entry: "/src/main.tsx", optimizeDeps: { sharedChunks: "auto", vendorPacks: "auto", packSlimming: "auto",

// Optional helpers
vendor: "auto",
include: ["lodash"],

}, }); ```

Example (manual packs: core/ui/data): ```ts import { defineConfig } from "@ionify/ionify";

export default defineConfig({ entry: "/src/main.tsx", optimizeDeps: { sharedChunks: true, vendorPacks: { core: [ "react", "react-dom/", "scheduler", "scheduler/", "react/jsx-runtime", "react/jsx-dev-runtime", "react-router", "react-router-dom", "@remix-run/router", "react-refresh", "react-refresh/", ], ui: ["@mui/", "@radix-ui/"], data: [ "@tanstack/react-query", "@tanstack/react-query/", "axios", "axios/", "zod", "zod/", "react-hook-form", "react-hook-form/", "@hookform/resolvers", "@hookform/resolvers/", "zustand", "zustand/*", ], }, packSlimming: "auto", }, }); ```

Env handling (Vite-compatible)

Ionify loads env files (Vite-style):

  • `.env`
  • `.env.local`
  • `.env.`
  • `.env..local`

envPrefix

`envPrefix` controls which env vars Ionify is allowed to expose to the browser via `import.meta.env.*`.

  • Default: `["VITE_", "IONIFY_"]`
  • Ionify always exposes: `MODE`, `NODE_ENV`, plus `DEV` / `PROD`

Ionify auto-exposes env vars to the client as `import.meta.env.*` when they match `envPrefix`.

You can also declare types in your app (example from `react-basic/src/ionify-env.d.ts`): ```ts declare global { interface ImportMetaEnv { readonly MODE: string; readonly NODE_ENV: string; readonly DEV: boolean; readonly PROD: boolean; readonly IONIFY_API_URL: string; } } ```

define (compile-time constants)

```ts export default { define: { __APP_VERSION__: JSON.stringify("1.0.0"), "process.env.NODE_ENV": JSON.stringify("development"), }, }; ```

Engine-level flags (optional)

Ionify also supports env flags for pipeline selection:

  • `IONIFY_PARSER=oxc|swc|hybrid`
  • `IONIFY_MINIFIER=oxc|swc|auto`
  • `IONIFY_OPTIMIZATION_LEVEL=0|1|2|3`

Output directory (today)

Build output defaults to `dist/`. Override via CLI: ```bash ionify build --out-dir dist ```