Library / SDK
dart-frog-dev/dart_frog avatar
dart-frog-dev/dart_frog

Dart Frog: a small Dart backend API, released CLI-first

A fast, minimalistic backend framework for Dart 🎯

2,271 stars181 forksDartMIT

At a glance

What is it?
Dart Frog is a MIT-licensed Dart backend framework built on shelf with code generation from Mason, shipping seven packages from one repository: the core, auth, a CLI, a generator, a shared lint ruleset, a test helper and websockets. Only the CLI is version-tagged, the last CLI release was 2026-03-23, and the production build emits a Dockerfile rather than leaving deployment to you.
Who is it for?
Use Dart Frog if you are a Flutter or Dart developer who needs a backend in the same language and wants the file-based routing, middleware and code generation model you already know from Remix, Next.js or Express rather than a Dart-idiomatic alternative you would have to learn.
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 28 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 September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Seven packages, one tag stream, and the CLI is what gets released

The package table in this README lists seven packages, and the release history tells you that only one of them is versioned.

The packages are dart_frog, the core; dart_frog_auth; dart_frog_cli, the command line tool; dart_frog_gen, the generator; dart_frog_lint; dart_frog_test; and dart_frog_web_socket. Each is published on pub.dev and each has its own subdirectory under packages/ in this repository.

The three most recent release tags are dart_frog_cli-v1.2.14 on 2026-03-23, dart_frog_cli-v1.2.13 on 2026-03-01, and dart_frog_cli-v1.2.12 on 2026-02-28. Every one of them names the CLI. There are no tags for dart_frog itself, and none for auth, gen, lint, test or web_socket.

So the release granularity is one, applied to the whole monorepo, and the thing that is named in the tag is the command line tool. The practical consequences are worth being precise about.

First, you cannot pin the framework independently of the CLI. When you add dart_frog to a pubspec, the resolver picks the highest published version, and that version moves when the next CLI release moves, because they are released together. If you want a reproducible build, you pin dart_frog_cli in your dev dependencies and let the framework version float to whatever pairs with it, or you pin both by hand and accept that you are choosing a combination the maintainers did not explicitly bless.

Second, the version number you see on the framework package tells you nothing on its own. A dart_frog version of 1.2.14 corresponds to a CLI release, and whether the framework's code changed at all in that release is a question about the commit history rather than about the tag.

Third, and this is the part an evaluator has to weigh, the last CLI release was 2026-03-23 and the last push to the repository was 2026-09-01. So the default branch is more than five months ahead of the newest tag, in a project with no CHANGELOG at the root of the repository listing. Whatever has landed since March is invisible to anyone installing from pub.dev, and there is no release notes file to tell them what they are missing.

The cadence within the visible history is brisk. Three CLI releases across February and March 2026, with two of them in the last three days of February. So the project was releasing frequently when the tags stopped, which makes the five-month gap look more like a decision or a circumstance than like a project winding down. Either way, a consumer's practical guidance is the same: read the commit log before upgrading, because the tag will not tell you what changed.

The project is MIT licensed with a LICENSE file at the root, was originally developed by Very Good Ventures, and the community Discord is linked both as a badge and through dart-frog.dev/discord.

dart_frog build emits a Dockerfile, which is a stronger claim than it sounds

The production build section is three lines long and the third line is the interesting one.

Creating a production build which includes a DockerFile so that you can deploy anywhere, with the command dart_frog build.

That is a specific claim with two halves. The build produces a container definition, and the container is portable enough to deploy anywhere.

The first half is a real convenience and it is unusual for a framework to do it. Most frameworks produce a build artefact and leave the container to you, on the theory that your deployment target has opinions about base images, layers, user privileges and health checks. Dart Frog takes the opposite position: it writes the Dockerfile as part of the build output, so the thing you deploy is a directory containing your compiled server and a container definition the framework generated, and you can hand that to any host that runs containers.

The trade is that you have less control over the image than if you wrote it, and a generated Dockerfile is a Dockerfile you did not review. For a framework whose stated goal is a small API surface and a short ramp-up time, that is the right trade for most users and the wrong one for anyone with a hardened image pipeline, a specific distroless base requirement, or a policy about what runs in their build artefacts.

The whole quick-start path, from the README, is four commands:

sh
dart pub global activate dart_frog_cli
dart_frog create my_project
dart_frog dev
dart_frog build

The dev server is the other half of the workflow and it is where the time is actually spent. dart_frog dev starts it, port 8080 by default, changeable with the --port option. Hot reload is in the repository topic list, so state changes are picked up without a restart, which is the feature that determines whether a developer stays in the framework or falls back to running the server directly.

Scaffolding is generated rather than written. dart_frog create my_project makes a new project, dart_frog new route creates a route, and dart_frog new middleware creates middleware for a route. So a developer adds an endpoint by running a command rather than by creating a file and remembering a registration convention, and that is the mechanism behind the framework's claim of a small API surface: there is less to learn because the generator writes the boilerplate and the conventions it follows are the framework's.

The examples directory is the best guide to what the conventions actually are, and there are eight of them: basic_authentication, bearer_authentication, counter, echo, hello_world, kitchen_sink, todos, and web_socket_counter. The naming is informative in two ways. The auth surface is expressed in HTTP scheme terms, basic and bearer, which suggests the framework's authentication story is built on standard schemes rather than on a proprietary session mechanism. And kitchen_sink is the conventional Dart name for the example that exercises everything, so that is where to look for the full feature surface.

The route naming in the quick start, /hello/world with a slash-separated path, is the file-based convention borrowed from the JavaScript frameworks, which is discussed next.

The framework's conventions ship as a lint package, not a style guide

One of the seven packages exists purely to encode how Dart Frog code should be written, and the README's badge row treats it as the project's style identity.

The badge row includes a style: dart frog lint badge linking to the dart_frog_lint package on pub.dev, alongside the Dart version, the CI status, a coverage badge, a Discord badge and the MIT licence badge. So the project that defines the house style is a published package rather than a document.

That is a real and slightly unusual design decision, and it is worth understanding what it does. A shared lint configuration as a dependency means the rules travel with the code: you add dart_frog_lint to your dev dependencies, include it from your analysis_options.yaml, and the analyzer enforces the framework's conventions on every save and in CI. There is no style guide to read, no wiki page to keep in sync, and no way to write code that passes review and fails the tool. A contributor who clones the repository gets the rules automatically.

The mechanism is Dart's analysis_options.yaml, which is at the root of this repository and is the Dart equivalent of a linter configuration file. It can include a shared package by reference, so the framework's ruleset is composed into a project's configuration rather than copied into it. That is the same pattern as a shared ESLint configuration distributed as an npm package, and it is the right way to do it.

There is a companion package in the same family. dart_frog_test is a test helper, so the framework's expectations about how you write and structure tests are also distributed rather than documented. So a new Dart Frog project gets its conventions from two packages and its scaffolding from the generator, which is a coherent picture of a framework that treats tooling as the documentation.

Two other details in the badge row are worth a moment. The coverage badge is a raw file URL pointing at packages/dart_frog/coverage/coverage_badge, which means the coverage badge is a generated SVG committed into the package directory rather than produced on demand by a service. That is a deliberate choice, since it means the badge works without a third-party service and cannot go stale from someone else's outage, at the cost of a generated artefact in version control. And the Dart version badge is a static hex colour rather than a version number, so the badge row does not actually tell you which Dart version the framework targets, which is a real gap given that Dart Frog depends on a current SDK.

The extension story is one VS Code extension, published on the Visual Studio Marketplace under the DartFrog publisher, which extends VS Code with support for Dart Frog and provides tools for effectively managing Dart Frog projects. So the editor support is first-party for the most common editor and absent for the others, which is a reasonable scope decision for a project with a Dart and Flutter user base where VS Code dominates.

shelf underneath, Remix and Next.js on top, Mason for the code

The Goals section states the lineage explicitly, and the choice of names tells you what the design is borrowed from and what it is built on.

Dart Frog is built on top of shelf and mason and is inspired by many tools including remix.run, next.js, and express.js.

Those are two different kinds of dependency and the distinction matters.

shelf is the Dart equivalent of Rack: a small interface specification for a web application, where you return a Response given a Request, and the framework handles the server. Building on shelf means Dart Frog inherits Dart's established minimal server interface rather than inventing one, and it means a Dart Frog handler is close in shape to any other shelf handler. That is a deliberate choice in a language community that already had a Rack equivalent and did not need a new one.

mason is a Dart-specific code generator by felangel, and the README carries a Powered by Mason badge pointing at it. Mason's unit of work is called a brick, and the repository has a bricks/ directory, so the code generation is done in Mason's idiom. That is a Dart-ecosystem-native answer to the problem of scaffolding, and using the community's own generator rather than a bespoke one means Dart Frog's generated code is in a format other Dart tooling understands.

remix.run, next.js and express.js are the inspirations, and all three are JavaScript. That is the clearest statement of the design intent in the repository: the routing and middleware model is borrowed from the JavaScript server framework world rather than from Dart idioms. File-based routing, a middleware chain, a small core, generators for new routes and middleware, and hot reload in development are all recognisably the Next.js and Remix shape, which is exactly the point for a framework whose stated audience is Flutter and Dart developers.

The stated goal follows from that choice. Dart Frog provides a simple core with a small API surface area in order to reduce the learning curve and ramp-up time for developers. And the positioning is explicit about who it is for: it is intended to help Flutter/Dart developers maximize their productivity by having a unified tech stack that enables sharing tooling, models, and more.

So the audience is not Dart backend developers in general. It is people who already write Flutter, who have a mobile app and now need a server, and who would rather not learn a second ecosystem's conventions. The current focus is stated too: optimizing the process of building backends which aggregate, compose, and normalize data from multiple sources, which reads as an API gateway or a data-federation service rather than as a general web backend.

That is a coherent product. It is also a narrow one, and an evaluator should be clear that the inspiration being JavaScript frameworks means the conventions will feel familiar to a web developer and alien to a Dart purist, and that the stated data-aggregation focus means the framework's examples lean towards API composition rather than towards sessions, forms and templates.

bricks/ and tool/: the repository is laid out in Mason's vocabulary

The repository listing is short, and reading it as a Mason project rather than as a Dart project explains most of the directory names.

The top level is .github/, .gitignore, CODE_OF_CONDUCT.md, CONTRIBUTING.md, CREDITS.md, LICENSE, README.md, analysis_options.yaml, assets/, bricks/, docs/, examples/, extensions/, packages/, and tool/.

bricks/ is the interesting one. In Mason, a brick is a code template: a directory with a brick.yaml manifest and template files, and the generator renders it into a new project or a new file. So the framework's route generator, its middleware generator, its project generator and any other scaffolding are all Mason bricks living in one directory. That means they are all testable with Mason's own tooling, they are all independently consumable, and a contributor can write a new one without reading the CLI's source.

tool/ is the Dart tooling, which is the conventional location for a Dart repository's development scripts: the code generators, the analysis driver and the build tasks for the monorepo itself. Having it separate from bricks/ is the right split, because tool/ is code that runs on the repository and bricks/ is code that runs on the user's project.

packages/ holds the seven published packages, one subdirectory each, which is the standard Dart monorepo layout and the reason a single git tag stream is natural: a release publishes several packages from one commit.

examples/ holds the eight example projects, and the fact that they are full projects rather than snippets means each one is something you can dart_frog create into and run. The set is basic_authentication, bearer_authentication, counter, echo, hello_world, kitchen_sink, todos and web_socket_counter, which is a sensible curriculum: two trivial, one that echoes, a counter, two auth shapes, a todo application that presumably has persistence, a websocket example, and the everything-example.

extensions/ holds the Visual Studio Code extension, which is a separate buildable artefact in the repository rather than something in another repo. So the IDE support versions with the framework.

docs/ and assets/ are the site and imagery. There is no CHANGELOG at the root, which is the gap that matters most given the release-granularity situation: with one tag stream and no changelog, a consumer upgrading dart_frog after a five-month gap has no single document telling them what changed.

CREDITS.md is linked from the README as the acknowledgments source, and it is where the Very Good Ventures origin and the individual contributors are recorded. CONTRIBUTING.md and CODE_OF_CONDUCT.md are the standard governance pair, both present, which is more than many projects of this size have.

One metadata observation. The repository's declared homepage is http://dart-frog.dev, plain HTTP, while the README's own documentation link is https://dart-frog.dev. The HTTPS version is what the project uses for its documentation and its Discord redirects, so the homepage field appears to be a leftover from before TLS was set up on the domain. It is a small thing, but the homepage is the field that gets rendered as a clickable link by package tooling and by GitHub, so anyone clicking it gets an unencrypted request first.

Editorial conclusion

Use Dart Frog if you are a Flutter or Dart developer who needs a backend in the same language and wants the file-based routing, middleware and code generation model you already know from Remix, Next.js or Express rather than a Dart-idiomatic alternative you would have to learn. Do not expect to pin the framework version: all three recent release tags are for dart_frog_cli, so the seven packages version together through the CLI and a pub constraint on dart_frog resolves to whatever pub.dev last published. Do not treat the project's activity level as a signal of the framework's, because the last CLI release is 2026-03-23 while the last push is 2026-09-01, so the default branch is more than five months ahead of the newest tag. Verify five things. What version of dart_frog_cli your lockfile actually resolves, since that is the only versioned thing here. Whether your IDE can consume the analysis_options.yaml, since the framework's conventions ship as the dart_frog_lint package rather than as a style document. Whether hot reload in dart_frog dev covers what you need, because the dev server is the centre of the workflow. That dart_frog build produces a Dockerfile, and whether that is the deployment shape you want rather than your own. And whether the auth examples, basic and bearer, cover your case, since that is what the examples imply the auth surface is. The deciding fact is that this is a deliberately small framework whose main risk is not its design but its release granularity, because a monorepo of seven packages with one tag stream gives you less version control than you would assume from the package count.

Frequently asked questions

How do I create a Dart Frog project?

Install the Dart SDK, then run dart pub global activate dart_frog_cli to install the CLI. Create a project with dart_frog create my_project, then cd into it and run dart_frog dev to start the development server, which uses port 8080 by default and can be changed with the --port option. Run dart_frog build for a production build that includes a Dockerfile.

What are the packages in the Dart Frog monorepo?

Seven: dart_frog for the core, dart_frog_auth, dart_frog_cli for the command line tool, dart_frog_gen for the generator, dart_frog_lint for the shared lint ruleset, dart_frog_test for the test helper, and dart_frog_web_socket. Each is published separately on pub.dev and each has its own subdirectory under packages/ in the repository.

How often is Dart Frog released?

Only the CLI is released. The three most recent tags are dart_frog_cli-v1.2.12 on 2026-02-28, v1.2.13 on 2026-03-01 and v1.2.14 on 2026-03-23, and the last push to the repository was 2026-09-01. So the default branch is more than five months ahead of the newest tag, and there is no CHANGELOG at the root of the repository.

What is Dart Frog built on?

shelf, the Dart equivalent of Rack, and mason, the Dart code generator by felangel. The design is inspired by remix.run, next.js and express.js, and the repository has a bricks/ directory because Mason's unit of code generation is called a brick. So the server interface comes from Dart's ecosystem and the routing, middleware and scaffolding conventions come from the JavaScript framework world.

How does Dart Frog enforce its code style?

Through a published package rather than a document. dart_frog_lint is on pub.dev and carries the project's style badge in the README, so a project adds it as a dev dependency and includes it from its analysis_options.yaml, which is the Dart equivalent of composing a shared ESLint configuration. A companion package, dart_frog_test, distributes the testing conventions the same way.

Can I add routes and middleware to a Dart Frog project?

Yes, with the generator: dart_frog new route creates a route and dart_frog new middleware creates middleware for a route, both taking the path as an argument, for example dart_frog new route "/hello/world". The examples directory contains eight runnable projects covering basic and bearer authentication, a counter, an echo server, hello world, kitchen sink, todos and a websocket counter.

Official sources

  1. dart-frog-dev/dart_frog on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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/dart-frog-dev-dart-frog.svg)](https://hysenlabs.com/projects/dart-frog-dev-dart-frog)