Skyroc: a layered React 19 monorepo for admin and Expo apps
Skyroc 是一个基于 React 19 + TypeScript 的跨端前端工程化 monorepo:既提供开箱即用的 Web 中后台模板(Admin / RuoYi 对接版)和 Expo 移动端业务模板,也把请求、状态、日志、主题、双端 UI 组件库等能力沉淀为边界清晰的 workspace 包。
At a glance
- What is it?
- Skyroc is a cross platform frontend engineering monorepo built on React 19 and TypeScript that ships a web admin template, a RuoYi and FastAPI integration variant, an Expo business template, and a set of workspace packages for requests, state, logging, theming and dual platform UI. It suits teams that want one engineering baseline across web and native, and it is a template rather than a product.
- Who is it for?
- Adopt Skyroc when your team needs a working admin interface today and a second target later, because the value is the layering that lets the same request, state, logging and theme packages serve a web admin app and an Expo app, and the standalone projects that `pnpm create skyroc` emits let you leave the monorepo without losing the conventions.
- 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 last received commits 52 days ago.
- 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
An engineering platform rather than an admin template
Skyroc describes itself as a cross platform, layered and reusable modern frontend engineering platform, and the description matters. The repository is not a single admin application. It is a pnpm workspace with a set of applications, a platform layer and a foundation layer, plus the tooling that keeps the three apart.
The concrete outputs are two templates. The web side is a ready to use admin console, with a variant wired for RuoYi with FastAPI. The mobile side is a complete Expo business template in which login state, the network layer, theming, internationalisation, deep links and native packaging scripts are already in place. A live preview of the current admin console is published, along with separate documentation sites for the admin app, the Web UI and the Native UI.
Underneath those sit the workspace packages, and this is where the design decisions live. Requests, state, logging, scheduling, types, colour, general utilities, the Web component library and the Native component library are each separate packages with explicit boundaries. The stated goal is that platform differences collapse inside a small number of adapters so the same capability code can be reused by Web, by React Native and, later, by a mini program.
The current version is v3 of the admin line. The earlier versions are still documented, and the version table in the README is the clearest statement of how fast the stack moves. v3 is React 19 with Vite 8, TanStack Router, Jotai and Ant Design 6. v2 was React 19 with Vite 6, React Router 7, Redux Toolkit and Ant Design 5. v1 was React 18 with Vite 5, React Router 6, Redux Toolkit and Ant Design 5.
Two changes there are worth pausing on. The router moved from React Router to TanStack Router, which is a change in how routes are declared rather than a drop in replacement. The state layer moved from Redux Toolkit to Jotai, which is a change in the shape of the store. Both are migration work, not configuration work, and the earlier documentation sites are kept alive so that a team on v2 can still find the answers.
Three layers with a one way dependency direction
The architecture is the clearest part of the repository, and the README states it as a diagram with three boxes and an arrow between each, plus a fourth area for shared configuration.
Applications sit at the top. These are admin, admin-example, ruoyi-plus-fast and expo-templete, along with the Web and Native playgrounds. Their job is business pages, route assembly, service adaptation and application configuration. Nothing else.
The Platform layer sits below, made up of `packages/web/*` and `packages/native/*`. It is responsible for layout, theming, UI, internationalisation, notifications, the runtime and build presets.
The Foundation layer is the bottom, made up of `packages/@core/*`, `packages/hooks` and `packages/primitives/*`. It handles requests, state, logging, scheduling, colour, types and general utilities.
The arrows point in one direction only, and the README labels them as depends on. Applications depend on Platform, Platform depends on Foundation. Nothing in the diagram points back up. That is the mechanism that keeps the layers honest, because an application that reaches around Platform into Foundation breaks the arrangement without anything failing loudly.
A fourth area sits outside the three boxes: `internal/*`, which provides TypeScript, test, lint and UnoCSS configuration for the workspaces.
The practical consequence is that an application is a thin assembly layer. The README puts it directly: the idea is that applications assemble, and stable capabilities move into the Core, Web Kit and Native UI packages. A team adopting this is adopting a dependency direction, not just a set of screens, and the two are not separable.
The five constraints and the naming convention
The architecture comes with five stated constraints, and they read like rules for a codebase that already exists rather than aspirations for one.
First, the application layer handles business and assembly, and must not duplicate capabilities that the shared packages already provide. Second, the Web and Native UI, themes and platform APIs are maintained separately. Third, cross platform packages confine platform differences to explicit subpaths or adapters. Fourth, public types keep a single source, and the design tokens are generated in one place by `@skyroc/tailwind-plugin` and then emitted per platform.
The fifth is procedural and matters as much as the others: before changing package layout or dependency direction, read `packages/ARCHITECTURE.md`. A repository that asks you to read a document before restructuring is a repository where the structure has been argued over and settled.
The token pipeline is the piece with the widest effect. The Web and Native UI packages share design tokens, and each keeps an implementation that fits its platform habits. The tokens are generated from one source and output per platform, which means a colour change is a change in one place rather than a search across two component libraries. Combined with the constraint that public types have a single source, the intent is clear: the platform differences are meant to be narrow and enumerable.
Naming reinforces this. The convention table gives `@skyroc/<capability>` for cross platform infrastructure, shared capabilities and platform independent primitives, with examples such as `@skyroc/utils`, `@skyroc/service`, `@skyroc/form` and `@skyroc/uno-config`, and a separate `@skyroc/web-*` prefix for web specific packages.
The repository also carries a set of files that show how much of the workflow is codified. There is `AGENTS.md`, `CLAUDE.md`, a `.agents/` directory, a `.claude/` directory, a `.cursor/` directory, a `skills-lock.json`, a `design/` directory and a `docs/` directory, alongside `.changeset/` for versioning, `turbo.json` for task orchestration, `pnpm-workspace.yaml` for the workspace definition and `vitest.config.ts` for tests.
Choosing an entry point with pnpm --filter
A monorepo with six applications is only usable if picking one is trivial, and Skyroc solves this with a table that maps a goal to an application and a start command. The commands are plain pnpm filter invocations:
pnpm --filter skyroc-admin dev
pnpm --filter admin-example dev
pnpm --filter ruoyi-plus-fast dev
pnpm --filter expo-templete startThe mapping reads like a menu. To develop an admin console on a clean skeleton, start at `apps/admin`. To see the full range of admin capabilities, use `apps/admin-example`. To work against a RuoYi or FastAPI backend, use `apps/ruoyi-plus-fast`. To build the Expo business app, use `apps/expo-templete`, which uses `start` rather than `dev` because that is the Expo convention. The two playground applications, `apps/web-ui-playground` and `apps/native-ui-playground`, exist for developing the Web and Native component libraries in isolation.
The distinction between `apps/admin` and `apps/admin-example` is the one worth understanding before you start. The first is a skeleton where you write the business pages. The second is a filled in demonstration of what the platform can do. Starting from the example and deleting what you do not need is a common approach, and it is also how you find out which of the platform's capabilities you actually want.
Everything above runs through Turborepo, which is why the root scripts are so short. The root package defines `dev` as `turbo run dev`, `build` as `turbo run build`, and the same pattern for lint, test and typecheck. Turborepo works out which packages need rebuilding for the app you asked for, which is the reason a monorepo of this size remains usable rather than becoming a build bottleneck.
The repository also keeps a `design/` directory and a `docs/` directory at the top level, which is a hint that the design system is treated as a first class output rather than a byproduct of the components.
Generating a project that leaves the monorepo behind
The feature list includes an out of the box promise that is unusual for a template repository: `pnpm create skyroc` can create an Admin or Expo project that stands alone, installed and run independently of the monorepo.
The root scripts show how that is wired. The `create-skyroc` package is a workspace in its own right, and the root scripts call it with a template argument:
"create:admin": "pnpm --filter create-skyroc create:workspace --template admin",
"create:expo": "pnpm --filter create-skyroc create:workspace --template expo",That is the difference between a template repository and a template generator. A repository that only contains templates leaves you with a copy of the whole workspace, including every package, the internal tooling and the design system. A generator that can emit a standalone project leaves you with an application that depends on published packages, and it leaves the monorepo behind.
That distinction matters for how the platform is used in practice. The monorepo is where the capabilities are developed, and the generated project is where a product is built. A team that later wants a change in the request layer or the theme pipeline makes it in the monorepo and publishes it, rather than editing a vendored copy inside one application.
The release history shows this generator is the actively versioned part of the project. The three most recent releases are create-skyroc 2.0.2, 2.0.3 and 2.0.4, all published on 2026-08-30 within the same evening. The last push to the repository was on 2026-09-01, and the repository is not archived.
The Expo template is the more complete of the two in terms of pre-wired concerns. The README describes it as providing login state, the network layer, theme, internationalisation, deep links and native packaging scripts. For a mobile application, that list covers most of the decisions that would otherwise occupy the first week of a project.
One quality pipeline for every workspace
The engineering story is told by the tooling rather than by prose, and the tooling list is specific. pnpm catalog manages versions, Turborepo orchestrates the tasks, and oxlint, oxfmt, Vitest and Playwright form the shared quality process.
The root package scripts show the shape of it. Formatting is `oxfmt` with a `format:check` counterpart, linting and building and testing are all delegated to Turborepo, and there are separate end to end and unit test paths with `test:ui` and `test:watch` for local loops.
Two entries are worth a second look. `postinstall` runs a shell script that fetches a prebuilt Skia binary for iOS only, and there is a `skia` script for the general case. Skia is the rendering engine that React Native draws with, and shipping a prebuilt copy rather than compiling it is the difference between a workable install and a very slow one. The `postinstall` hook being limited to iOS with a soft flag suggests the project accepts that not every environment needs it.
The release process is changesets based and scripted. There is `changeset` for adding a changeset, `release:status` for `changeset status`, `release:version` which builds a release plan, versions the packages and then updates the lockfile with `--lockfile-only --ignore-scripts`, and `release:publish` which publishes. A separate `release:plan` script calls a TypeScript file under `scripts/release`, so the release flow is code rather than a checklist in a wiki.
The licence is MIT, with the licence file at the repository root, and the repository is private as a workspace root, which is the normal arrangement for a monorepo whose packages are published individually.
One gap to note. The README describes a mini program directory as reserved for a later extension, so the cross platform claim currently covers Web and React Native rather than a third target, and the repository entry list does not show that directory as a finished app.
Editorial conclusion
Adopt Skyroc when your team needs a working admin interface today and a second target later, because the value is the layering that lets the same request, state, logging and theme packages serve a web admin app and an Expo app, and the standalone projects that `pnpm create skyroc` emits let you leave the monorepo without losing the conventions. Do not adopt it if you want a component library you can drop into an existing build, since the packages are published around a specific workspace layout and a token pipeline. Verify first the stack version you are getting, since v3 moved to Vite 8, TanStack Router, Jotai and Ant Design 6 while v2 and v1 documentation still describe React Router and Redux Toolkit, then read packages/ARCHITECTURE.md before you move a package, because the dependency direction is a stated constraint.
Frequently asked questions
What is Skyroc and what does it include?
Skyroc is a cross platform frontend engineering monorepo built on React 19 and TypeScript. It includes a web admin template, a RuoYi and FastAPI integration variant, an Expo business template, and workspace packages covering requests, state, logging, theming and the Web and Native UI component libraries.
How do I create a standalone Skyroc project?
The project states that pnpm create skyroc can create an Admin or Expo project that stands alone, installed and run independently of the monorepo. Inside the repository the same generator is driven by the create:admin and create:expo scripts, which call the create-skyroc workspace with a template argument.
What are the three layers of the Skyroc architecture?
Applications handle business pages, route assembly, service adaptation and configuration. The Platform layer, in packages/web and packages/native, handles layout, theme, UI, i18n, notifications, runtime and build presets. The Foundation layer, in packages/@core, packages/hooks and packages/primitives, handles requests, state, logging, scheduling, colour, types and utilities, with dependencies pointing in one direction only.
What changed between Skyroc v2 and v3?
The version table shows v3 on React 19 with Vite 8, TanStack Router, Jotai and Ant Design 6, while v2 used Vite 6, React Router 7, Redux Toolkit and Ant Design 5. Moving between them means changing the router and the state layer rather than only updating dependencies, and documentation for the earlier versions is still published.
Which tools does Skyroc use for linting, formatting and tests?
The README names pnpm catalog for version management, Turborepo for task orchestration, and oxlint, oxfmt, Vitest and Playwright as the shared quality process. Root scripts delegate to turbo run for build, lint, test and typecheck, with oxfmt as the formatter.
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/ohh-889-skyroc)Was this useful?