Framework
StacDev/stac avatar
StacDev/stac

Stac: a server-driven UI framework that renders JSON payloads as Flutter widgets

Stac is a Server-Driven UI (SDUI) framework for Flutter, enabling you to create stunning, cross-platform applications dynamically with JSON. Build and update your app's UI in real-time with ease and flexibility!

927 stars110 forksDartMIT

At a glance

What is it?
Stac is a MIT-licensed Flutter framework for server-driven UI, where screens are authored in a Dart DSL that compiles to JSON and is rendered natively on the client at runtime. The trade is deliberate: you give up the compile-time safety of widget code in exchange for shipping UI changes without an app store release.
Who is it for?
Stac suits a product team that needs to change layouts, run A/B tests or personalise screens without going through app store review, and that is willing to give up compile-time checking of its UI code to get that. It does not suit an app where the client must work offline with the UI baked in, where every pixel is legally reviewed, or where a runtime JSON payload is an unacceptable trust boundary.
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 2 days ago.
What is it written in?
Mainly Dart, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The UI becomes a JSON payload your server ships to the client

Stac is a Server-Driven UI framework for Flutter. The stated idea is that instead of hard-coding the interface in the app, you write the interface with Stac's Dart DSL, your server delivers that interface as a JSON payload, and Stac renders it natively on the client at runtime. The claimed benefit is speed to market: tweak the UI in Dart, push it to your server, and users see it immediately, without waiting for app store reviews. The listed reasons to use it are shipping instantly, making A/B testing straightforward because you can try different layouts or personalise the experience without rolling out a new app version, keeping the UI consistent across iOS, Android and Web from one backend schema, and letting the backend dictate layouts without touching the client-side Flutter codebase. The audience is a product organisation with a backend that already owns the data, and a release process where a two-day UI tweak is not acceptable.

A Dart DSL that compiles down to JSON, not a hand-written schema

The authoring model is the interesting part. You write screens using Stac's Dart package, and it feels like writing normal Flutter code, but it compiles down to JSON. The DSL mirrors the Flutter widget vocabulary with a Stac prefix: StacScaffold, StacAppBar, StacColumn, StacRow, StacText, StacTextField, StacFilledButton, StacPadding, StacSizedBox, StacDivider, StacExpanded and StacSpacer all exist, along with a StacThemeData carrying a textTheme. A screen is a function annotated with @StacScreen and a screenName, returning a StacWidget, and navigation is expressed as actions such as StacNavigator.pushStac with a target screen name. The advantage over a raw JSON schema is that the payload is produced by code, so it can be typed, refactored and version controlled, and the schema is generated rather than maintained by hand. The cost is the one inherent to any server-driven approach: the client is now interpreting input at runtime, so a payload problem shows up on a user's device rather than at compile time.

Widgets, actions and navigation are resolved on the client, not fetched blindly

The feature list in the README describes the runtime capabilities the framework provides. Rendering is native: Stac translates the payload into Flutter widgets, so the result is not a web view or a screenshot. Prebuilt components cover a large library of standard Flutter widgets. Network requests can be triggered from the server payload, so a screen can fetch and manage data. Navigation is controllable from the backend, including routing, opening dialogs and triggering bottom sheets. Forms and validation are handled by the framework rather than left to the payload author. Dynamic theming changes colours, fonts and layouts on the fly through StacTheme. Screen caching is built in, which the README frames as making the app feel fast even on flaky networks. Custom widgets can be built and registered, so a chart or a native integration that has no standard counterpart is still expressible. Taken together, these are the pieces that decide whether a server-driven screen is a toy or a real interface.

Initialising Stac is two steps, and the options object is where the real decisions live

The quick start is short: initialize Stac and tell it which screen to load. In main.dart you call Stac.initialize with an options object, then render your app widget whose home is a Stac widget given a routeName, which is the key your server uses to decide what to return. The README shows the whole thing in one snippet:

dart
import 'package:flutter/material.dart';
import 'package:stac/stac.dart';

// import 'package:my_app/default_stac_options.dart';

void main() async {
  // Initialize Stac with optional custom configurations
  await Stac.initialize(options: defaultStacOptions);
  
  runApp(const MyApp());
}

The commented import line is the important hint. The options object is where your base URL, caching behaviour and custom widget registrations live, and the README presents it as an optional custom configuration that you can put in your own file. Because the framework fetches a routeName from a server, that configuration is effectively the trust boundary of the whole system, and a default Stac.initialize call with no options is something to review rather than accept.

A monorepo with its own playground, brick templates and toolchain

The repository is a Dart monorepo rather than a single package. The tree shows a packages directory, a stac_playground directory, a bricks directory with a mason.yaml, a melos.yaml, a docs directory, an examples directory holding a counter_example and a movie_app, a skills directory and a tools directory. Several of those tell you about the project rather than the runtime. melos.yaml, matching the badge saying the project is maintained with melos, means the packages are managed and versioned together by a Dart monorepo tool. The bricks directory with mason.yaml points to Mason brick templates, which is the Dart convention for project scaffolding: you can generate a new project or a new screen with the standard layout rather than hand-writing the file headers. The examples directory is the fastest way to evaluate the framework, since a counter app and a movie app cover both a trivial state case and something with real data flow.

Docs, a console, and a Discord community rather than a formal support path

The project points at a small set of external surfaces. There is a website, a console at console.stac.dev, a quickstart and full documentation at docs.stac.dev, and a Discord invite for community and support. The repository homepage in the package metadata is also docs.stac.dev. The fact that a console exists alongside the docs suggests the workflow includes producing or previewing payloads outside the app, which is what you would need to iterate on a server-driven screen without redeploying a client build. The community channels are Discord and the repository itself, and the topics list includes hacktoberfest, so contributions are seasonally encouraged. None of that replaces a support commitment for a framework you intend to build a product on, so a team evaluating Stac should weigh the documentation and the example code as the real onboarding path.

MIT terms and a release line that moves in step with Flutter

The licence field is MIT, with a LICENSE file at the root and a badge stating it, which is the permissive end of the scale and carries no copyleft obligation on code that merely uses the package. The release history shows steady minor version movement: v1.6.0 on 2026-09-13, v1.5.0 on 2026-05-20 and v1.4.0 on 2026-03-02, with the last push to the repository on 2026-10-19. A minor version every couple of months is a normal cadence for a Flutter package and carries a specific cost: the DSL is the API, so a change in how a widget serialises is a change in the wire format between your server and your shipped app. Older clients must keep working with newer payloads, and that compatibility burden falls on you, because the server is under your control and the installed apps are not. Pin your client version, and treat the server payload as a versioned interface with its own compatibility policy rather than as a file you can change freely.

Editorial conclusion

Stac suits a product team that needs to change layouts, run A/B tests or personalise screens without going through app store review, and that is willing to give up compile-time checking of its UI code to get that. It does not suit an app where the client must work offline with the UI baked in, where every pixel is legally reviewed, or where a runtime JSON payload is an unacceptable trust boundary. Before adopting it, run the counter and movie app examples in the examples directory against your own backend, and check the Stac.initialize options you pass, because that is where network base URL, caching and custom widget registration are configured, and getting it wrong is silent rather than loud.

Frequently asked questions

What is Stac and what problem does it solve?

Stac is a Server-Driven UI framework for Flutter. You write screens with a Dart DSL, the server delivers them as JSON, and the framework renders them as native Flutter widgets, so UI changes ship without an app store release.

How do I start using Stac in a Flutter app?

Call Stac.initialize with your options in main.dart, then set the home widget of your app to Stac with a routeName that your server uses to decide which payload to return. The README shows the full snippet in its quick start.

Does Stac replace Flutter widgets with a web view?

No. The README describes native rendering, where Stac translates the server payload into Flutter widgets on the client, and it ships a prebuilt library of standard Flutter widgets alongside support for registering your own custom components.

Can Stac screens make network requests and handle forms?

Yes. The feature list includes triggering API calls and managing data directly from the server payload, controlling routing and opening dialogs from the backend, and built-in form state and validation handling.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. StacDev/stac on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stacdev-stac.svg)](https://hysenlabs.com/projects/stacdev-stac)

Was this useful?