Roadmap
This page covers only features as you encounter them. Internal phases, progress percentages, and implementation details live in the GitHub repository.
Planned
Section titled “Planned”Bundler
Section titled “Bundler”Public WASM AST API
Section titled “Public WASM AST API”Expose the ZNTC AST as a WASM module so it can be consumed outside Node and the browser. The WASM build that today powers the Playground and Metafile Analyze pages will be stabilized and published as a user-facing API. Depends on AST schema stabilization.
External Zig plugins
Section titled “External Zig plugins”Zig plugins currently exist only for built-in transforms (worklet, Fast Refresh). User-authored Zig modules will be loadable as plugins, statically linked at build time and called in-process. No JS↔native serialization overhead, but the Zig compiler must be available at build time.
Rollup plugin context API extension (ESTree AST)
Section titled “Rollup plugin context API extension (ESTree AST)”The vitePlugin() adapter supports the main Rollup hooks (resolveId · load · transform · renderChunk · generateBundle) and most fields of getModuleInfo(). Remaining items are parts of the plugin context API (this.parse() · this.resolve() · this.emitFile() · ModuleInfo.meta) and ModuleInfo.ast — an ESTree adapter that exposes each module’s ESTree-compatible AST to plugins. It depends on converting ZNTC’s internal AST to the ESTree shape.
Refined dead-code elimination (innerGraph)
Section titled “Refined dead-code elimination (innerGraph)”Straight-line dead stores on local variables are eliminated. Dead-store analysis across if / for / try control flow is in progress.
lazyBarrel refinement
Section titled “lazyBarrel refinement”Barrel re-exports (export * from, export { X } from, import * as X; export { X }) skip compilation for pure / local / namespace patterns. Wrapper barrels that mutate imported bindings (e.g. lodash-es’s lodash.default.js) currently disable lazy mode entirely as a conservative fallback. Refining this to apply lazy mode to non-mutating parts only is pending. See Tree-shaking for current limits.
mangleProps
Section titled “mangleProps”Cross-module property mangling, esbuild-style. Not implemented yet.
Improved module concatenation
Section titled “Improved module concatenation”Scope-hoisting at the level of rspack / rolldown.
Persistent disk cache
Section titled “Persistent disk cache”Only an in-memory parse cache + resolve cache lives across rebuilds within a watch / serve session. A persistent on-disk cache to speed up cold rebuilds is on the backlog.
Lazy compilation
Section titled “Lazy compilation”On-demand module compilation for faster dev startup. Not implemented yet.
Transpiler
Section titled “Transpiler”.d.ts emission (isolatedDeclarations)
Section titled “.d.ts emission (isolatedDeclarations)”Currently delegated to tsc. Native isolatedDeclarations-based emission is planned.
Dev server
Section titled “Dev server”Converging to a single Zig dev server
Section titled “Converging to a single Zig dev server”Two dev servers coexist today:
- Zig native (
zntc serve/zntc dev) — standalone, no Node required. - JS (
zntc dev <root>app mode) — used to delegate to JS-ecosystem plugins (postcss / sass).
The long-term goal is to vendor BoringSSL, abstract the plugin host, and converge on the Zig server (similar to Bun’s model). This sits behind the stability / CSS / ecosystem milestones.
Ecosystem
Section titled “Ecosystem”Plugin examples
Section titled “Plugin examples”Reference plugins for common cases: PostCSS, Tailwind, SVG, YAML.
Migration guides
Section titled “Migration guides”Expand the esbuild → ZNTC and Vite → ZNTC mapping tables. Some material already lives under Migration.
Framework integration (Next.js · Remix · SvelteKit · Expo)
Section titled “Framework integration (Next.js · Remix · SvelteKit · Expo)”Each of these ships its own bundler tightly coupled to the framework, so an adapter ends up being a partial reimplementation of the framework’s compiler. This is the last milestone.
- Expo: A meta-framework on top of React Native. Plain React Native apps already build via
--platform=react-native, but integrating with Expo Router’s filesystem-routing manifest, theexpo prebuildstep, and the EAS build pipeline requires a dedicated adapter.
NativeWind (React Native + Tailwind)
Section titled “NativeWind (React Native + Tailwind)”NativeWind, which turns Tailwind classes (className) into styles in React Native, currently works by passing nativewind/babel through as a user Babel plugin (on the --platform=react-native build path). First-class support is planned: ① a reference example plus a React Native build E2E regression guard, ② folding Tailwind CSS compilation behind the plugin API (the @tailwind directives in global.css wired as a React Native entry), and ③ zero-config wiring when nativewind is present in package.json so the React Native preset sets it up automatically. Doing the className → style transform natively in the ZNTC transformer (without Babel) is gated on measuring the actual benefit first.
React Native CLI
Section titled “React Native CLI”React Native builds, launches, and debugging are already handled by the ZNTC native core engine (--platform=react-native). What gets added is not a separate bundler but a single react-native.config.js command-plugin entry point — adding that plugin makes the existing react-native start / react-native bundle / react-native run-ios|android go through ZNTC instead of Metro (argument mapping + spinning up the existing RN dev server + wiring up the device launch/debug channels). This entry point lives in @zntc/react-native so the general-purpose zntc CLI stays free of RN dependencies.
React Native Hermes-targeted downleveling
Section titled “React Native Hermes-targeted downleveling”React Native bundles are currently always downleveled to ES5. But modern Hermes (the version shipped with current React Native) natively supports many ES2015+ constructs — classes, let/const, arrow functions, destructuring, and more — so blanket ES5 transformation only inflates the bundle with unnecessary helpers and closures. ZNTC’s engine-target feature (Hermes included, per-feature downleveling) already exists, so the React Native preset will switch from a hardcoded ES5 target to downleveling only what the bundled Hermes version actually needs. Constructs Hermes still lacks (certain regular-expression features, etc.) keep being downleveled, and apps with Hermes disabled (JSC) fall back to ES5.
Chrome CDP bundle verification CLI
Section titled “Chrome CDP bundle verification CLI”Internal tests already run bundles in a real browser via the Chrome DevTools Protocol to verify source maps and runtime errors. This path is being promoted to a user-facing CLI command (zntc verify --browser): run a build’s output in headless Chrome and report console errors, uncaught exceptions, and source-map resolution as an exit code plus JSON (Playwright stays an optional dependency).
Vite-compatible mode
Section titled “Vite-compatible mode”Read vite.config.js directly for zero-cost migration. Long-term goal.
Current limitations
Section titled “Current limitations”Cannot build Next.js / Remix directly
Section titled “Cannot build Next.js / Remix directly”These frameworks bake the bundler into the framework itself — RSC payload serialization, filesystem-routing manifests, loader/action server-client separation. A general-purpose bundler cannot stand in for them. Plain React / Vue / Svelte SPAs and React Native (Metro-compatible output) are supported.
.module.css auto-transform in core --bundle mode
Section titled “.module.css auto-transform in core --bundle mode”App mode (zntc dev / zntc build) supports .module.css class-name hashing / scoping out of the box — see Plugin Recipes / CSS Modules. Core --bundle mode does not auto-transform .module.css; go through the Vite adapter or a user plugin (PostCSS Modules / Lightning CSS Modules) instead.
Persistent disk cache · Lazy compilation · mangleProps
Section titled “Persistent disk cache · Lazy compilation · mangleProps”See the corresponding “Planned” items.
Control-flow-aware dead stores
Section titled “Control-flow-aware dead stores”Dead assignments inside if / for / try may be preserved. Only straight-line dead stores are eliminated today.
Wrapper-barrel mutation pattern
Section titled “Wrapper-barrel mutation pattern”When a barrel module mutates an imported binding (some libraries do this — e.g. lodash-es), the lazy-barrel optimization is disabled wholesale for that module. Correctness is preserved, but the bundle can be larger than necessary.
Large tsconfig paths (hundreds of entries)
Section titled “Large tsconfig paths (hundreds of entries)”Only the first resolve walks the array linearly; subsequent resolves hit the resolver cache. No measurable impact at normal project sizes.
Public WASM AST API
Section titled “Public WASM AST API”@zntc/wasm exposes transpile(), build(), buildChunks(), and VirtualFileSystem for user import; see the WASM section of Installation for the usage surface. Direct module-level access to the ESTree-compatible AST from plugins is the remaining gap — see the “Planned / Public WASM AST API” entry above. AST schema stabilization is the prerequisite.