Stackflow: a stack navigator for hybrid apps where the UI is a plugin
🧱 Mobile-first stack navigator framework with composable plugin system
At a glance
- What is it?
- Stackflow implements iOS-style stack navigation in JavaScript so hybrid apps and webviews can keep scroll state, animate pushes and support swipe back, with the core logic separated from any React binding. The catch is that React is currently the only supported frontend.
- Who is it for?
- Stackflow suits a team building a hybrid app whose screens are webviews and who need native-feeling push and pop transitions with retained scroll position, or a team that wants to share one navigation codebase between mobile and desktop.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Stack navigation without a native runtime
Stackflow implements what the project calls Stack Navigation UX, mainly used on mobile devices, in a JavaScript environment. The stated benefit is that it helps you develop hybrid apps and webviews.
The feature set is the familiar iOS stack behaviour, and it is worth being precise about it. Screens stack, and the scrolling state is kept, so going back to a list returns you to the same scroll offset rather than the top. It supports transition effects that stack up the screen, and the matching effect that plays when you go back, so the animation is not a single effect played in both directions. It supports iOS-style swipe back, the edge gesture that pops the current screen. And it passes the necessary parameters to the screen being switched to, which is the part most hand-rolled implementations leave to chance.
This is a deliberately narrow domain. A hybrid app, in the sense used here, is a native shell containing webviews, and the navigation between those webviews is what the framework provides. It is not a router for a single page application, and it does not replace React Router or anything similar. It sits at the layer above, deciding what is on the screen stack and how the transition plays.
The project comes from daangn and it is published under the MIT licence, with the full documentation and a demo at stackflow.so.
The core is separate from the UI, and that is the whole idea
The advantages the project lists over existing navigation libraries are all consequences of one architectural decision: the stack state and the transitions live in a core that knows nothing about how screens are drawn, and the UI is one implementation that plugs into it.
The first advantage is that you can use the state for stacks and transitions separately, without the UI. You can tear off the UI and use it as you like, which in practice means the navigation model is testable on its own and usable in a headless environment.
The second is the plugin interface, which lets you inject additional extensions between lifecycles. Whatever the lifecycle hooks are, a plugin can sit between them, so cross-cutting concerns like analytics, logging or session expiry are added by attaching to a lifecycle rather than by editing every screen.
The third is that core logic and integration layers are separated, so the framework can be integrated with various frontend frameworks. The catch arrives immediately after: only React is supported now. So the separation is real and architecturally sound, but you are not choosing the frontend, React is choosing you.
The fourth advantage is the one with the widest reach. Because render logic and UI can be injected from outside, mobile webview and desktop development can be done in one codebase. A team with a web app and a hybrid app wrapping it can share the navigation model rather than maintaining two. The fifth is server-side rendering, supported through ReactDOMServer.renderToString.
Installing the three packages and declaring your activities
The install is three packages, and the split between them matters because it is the same separation as the architecture:
$ yarn add @stackflow/config @stackflow/core @stackflow/reactThe config package holds the declarative description of the app, the core holds the navigation state machine, and the react package is the binding that turns that state into React elements.
A minimal app declares its activities, picks an initial one, sets a transition duration, and hands the components to the stackflow function:
import ReactDOM from "react-dom";
import { defineConfig } from "@stackflow/config";
import { stackflow } from "@stackflow/react";
import MyActivity from "./MyActivity";
const config = defineConfig({
activities: [
{
name: "MyActivity",
},
],
initialActivity: () => "MyActivity",
transitionDuration: 350,
});
const { Stack } = stackflow({
config,
components: {
MyActivity,
},
plugins: [],
});
const App = () => {
return (
<Stack />
);
};
ReactDOM.render(<App />, ...)Three things in that snippet are worth noting. Activities are named in the config and their components are supplied separately to stackflow, so the config is a pure description and the components are the implementation. initialActivity is a function rather than a value, which means the starting screen can be computed, for example from a route or a session. And plugins is an empty array in the starter, so the extension points are part of the basic setup rather than an advanced add-on.
The transition duration is expressed in milliseconds, and 350 is a starting point you tune to taste.
Framework integration, and why the Next.js example is discouraged
The integration examples in the project documentation are a standalone demo, a Gatsby example and a Next.js example, and the third one carries a warning marker and the label Not Recommended.
The reason is stated directly. To integrate Stackflow with a specific framework with routing capabilities, the framework requires an extension to manually call the preload API. Next.js does not officially support the preload API. So the incompatibility is not about React, it is about a specific hook that Stackflow needs and that Next.js does not expose.
This tells you something about how the framework composes with routing. Stackflow is a navigation model with its own stack, and a host framework with its own router will fight over control of history and URL state. The preload API is the seam: the host router tells Stackflow what is about to be displayed so the transition can be prepared before the user sees it, and if the host framework will not call it, you are left with a patch or a workaround.
Gatsby is presented without that caveat, and the standalone demo is the way to see the thing working without a router at all.
The monorepo layout reflects the same separation at the source level. The workspaces include docs, config, core, demo, integrations, packages and extensions, and there is a separate extensions directory, which is where the plugin implementations live. The integrations directory holds the framework bindings, one per host framework, which is the correct place for the preload API wiring.
A monorepo with changesets and a canary release path
This is a monorepo with a modern toolchain, and the details tell you about the project's maturity. The package manager is yarn 4.3.1, using Plug'n'Play as indicated by the .pnp.cjs and .pnp.loader.mjs files, with the .yarn directory checked in and a .yarnrc.yml. The build runs through ultra-runner, so a single yarn build fans out across every workspace, and there are separate tasks for building type declarations, cleaning, and running the dev server with high concurrency.
Releases are managed with changesets, and the release script shows the full sequence: clean, build, changeset, then changeset version which regenerates the changelog and updates versions, then changeset publish. There is a separate canary path, release:canary, that enters the canary pre-release mode, publishes, and exits it. That means a consumer can install a prerelease of any package in the monorepo, which matters for a framework where the core, the config package and the React binding have to move together.
Lint and format are handled by Biome rather than ESLint and Prettier, with biome.json at the root and separate lint and format scripts. TypeScript is at 5.5.3, and the recent releases show the packages moving independently: @stackflow/react-ui-core at 1.3.8 and @stackflow/plugin-basic-ui at 1.19.1, both on 2026-10-12.
There is also an AGENTS.md, a CLAUDE.md, a .changeset directory and a .coderabbit.yaml, plus a biome.json and a tsconfig.json, which points to a repository that has been set up with automated tooling in a fairly deliberate way.
Where this is the wrong tool
The first limitation is React-only support. The separation between core and integration is the design's best feature and it is also incomplete: the project states that only React is supported now, so a Vue or Svelte team cannot use the core without writing their own binding, which means writing the very integration layer the architecture promises to make unnecessary.
The second limitation is the scope. This is navigation, not an application framework. It does not give you routing for a site, a data layer, or a screen lifecycle beyond what the plugin interface exposes. A team that expected it to replace React Navigation for a native React Native app is on the wrong track, because the target environment is JavaScript in a webview, not native views.
The third limitation is the router seam, and it is the one with the sharpest edges. The preload API requirement means integration with a routing framework is not automatic, and the project's own Next.js example is marked as not recommended. Hybrid apps that already have a router-driven navigation scheme will find this is an overlay on top of it rather than a replacement.
On maintenance, the repository is not archived and the last push was on 2026-10-19, with releases on 2026-10-12, so the project is actively worked on. It is MIT licensed, with a LICENSE file at the root of the monorepo.
Editorial conclusion
Stackflow suits a team building a hybrid app whose screens are webviews and who need native-feeling push and pop transitions with retained scroll position, or a team that wants to share one navigation codebase between mobile and desktop. It is a poor fit for a React Native app, since the target here is JavaScript in a webview rather than native views, and a poor fit for a project that is not already on React, because the project states that React is currently the only supported frontend. Before adopting, read the integration notes for your framework, and note that the Next.js example is marked as not recommended because Next.js does not officially support the preload API the framework requires.
Frequently asked questions
What is Stackflow and what problem does it solve?
Stackflow implements Stack Navigation UX, mainly used on mobile devices, in a JavaScript environment, so hybrid apps and webviews can be developed with native-feeling navigation. It stacks screens and keeps their scrolling state, supports stacking transitions and iOS-style swipe back, and passes the necessary parameters to the screen being switched to.
How do I install Stackflow and set up a first screen?
Install the three packages with yarn add @stackflow/config @stackflow/core @stackflow/react, declare your activities in a config built with defineConfig, set an initialActivity and a transitionDuration, then pass the config, your components and a plugins array to stackflow and render the returned Stack component.
Which frontend frameworks does Stackflow support?
React only, as the project states. The core logic and the integration layers are separated so that other frontends can be supported, and the monorepo has an integrations directory for framework bindings, but React is currently the only supported frontend.
Why is the Stackflow Next.js example marked as not recommended?
Integrating Stackflow with a framework that has routing capabilities requires an extension that manually calls the preload API, and Next.js does not officially support the preload API. The project links a Gatsby example and a standalone demo instead.
How is Stackflow released?
The repository is a yarn 4 monorepo using changesets for versioning, with a release script that cleans, builds, creates a changeset, versions and publishes, plus a separate canary path that publishes pre-release versions. Recent releases include @stackflow/react-ui-core 1.3.8 and @stackflow/plugin-basic-ui 1.19.1 on 2026-10-12.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/daangn-stackflow)Was this useful?