Platform

@ng-native/platform is the only Angular-aware file in the whole rendering stack. Everything below it, @ng-native/fabric, is a framework-agnostic retained tree with no import from @angular/core anywhere in it. This package is the seam: a Renderer2/RendererFactory2 pair that turns Angular's renderer calls into mutations on that tree, and a mount() function that stands in for bootstrapApplication plus @angular/platform-browser.

Reach for this package exactly once, in your app's entry file, to call mount(). Everything else you write - components, styles, routes - goes through the packages built on top of it, not through this one directly. mount also returns an engine you can hold onto: it carries commit stats (counts and timings) and is what @ng-native/device's watchConditions(engine) re-resolves media queries against on rotation or a system theme change.

The smallest app

// src/main.ts
import { AppRegistry, Image, Platform, processColor } from 'react-native';
import { mount } from '@ng-native/platform';
import { getFabricUIManager, registerPlatformComponents } from '@ng-native/fabric';
import { App } from './app/app.ts';

registerPlatformComponents(Platform.OS);

AppRegistry.registerRunnable('main', ({ rootTag }) => {
  mount(Number(rootTag), App, getFabricUIManager(), {
    processColor,
    resolveAssetSource: (value) => Image.resolveAssetSource(value as never),
  });
});

mount takes a root tag (the number React Native's own runnable handler hands you), your root component, a FabricUIManager (getFabricUIManager() reads global.nativeFabricUIManager, which only exists once the New Architecture is enabled and only inside an AppRegistry runnable), and an options object for the gaps a browser never had - colour conversion, asset resolution, media-query conditions, and the one global stylesheet every element is matched against regardless of which component created it.

How this differs from bootstrapping on the web

There is no bootstrapApplication, no BrowserModule, and no CSS selector naming an element in an index.html - there is no HTML document at all. The root Angular mounts into is engine.root, a plain object standing in for Element, and it becomes a screen's worth of native views the moment the first commit runs rather than by producing markup for a browser to paint. DOCUMENT is provided as a stub, just enough to satisfy the one Angular internal (TransferState, reached the moment a resource() is created) that calls getElementById on it. And there is no zone.js option to reach for: mount() provides zoneless change detection unconditionally, so the change-detection model a zoneless Angular app already uses on the web carries over unchanged.

The bootstrapping page covers mount()'s options, its return value, and what it puts in the injector. The renderer page covers what NativeRendererFactory and NativeRenderer actually do with an Angular template once it exists, including how a commit gets scheduled outside a normal change-detection pass.

HTTP requests

Use provideNativeHttpClient() from @ng-native/platform/http, not provideHttpClient(), in mount's providers:

import { provideNativeHttpClient } from '@ng-native/platform/http';
import { withInterceptors } from '@angular/common/http';

mount(rootTag, App, getFabricUIManager(), {
  providers: [provideNativeHttpClient(withInterceptors([authInterceptor]))],
});

provideNativeHttpClient(...features) takes the same HttpFeatures provideHttpClient() does - withInterceptors() among them - and configures HttpClient with withXhr() instead of the default fetch backend. That is not a style preference. Angular 22's default backend reads a response body only through response.body's stream, and React Native's fetch is whatwg-fetch over XHR, whose Response has no body - so every request resolves with a null body and nothing reports why. React Native's XMLHttpRequest is native and complete, upload progress included, which is what the XHR backend actually uses.

A separate entry point, @ng-native/platform/http, so an app that never makes a request does not pull in @angular/common.

Angular components as native iOS and Android views, built and shipped with Expo.

An alpha. MIT licensed. Sponsor its development.

An independent project, not affiliated with or endorsed by Google, the Angular team or Expo. Angular is a trademark of Google LLC.