Open-source project
kauemurakami/getx_pattern avatar
kauemurakami/getx_pattern

getx_pattern: a proposed folder layout for GetX in Flutter

Design pattern designed to standardize your projects with GetX on Flutter.

1,035 stars217 forksMakefileLicense varies

At a glance

What is it?
getx_pattern is not a library but a proposal for how to arrange a Flutter project that uses GetX, with a module per screen holding its page, controller, binding and repository, a data layer of services and providers, and a core directory for routes, values, translations and theme. The repository is also a documentation website, and the documentation is a step behind the examples.
Who is it for?
getx_pattern fits a team that has already chosen GetX and wants every feature in the same shape, with the argument for it being that a binding ties a screen to its controller and its disposal, which is the part of GetX that is easy to get wrong.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 35 days ago.
What is it written in?
Mainly Makefile, 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

A layout proposal, not a package

getx_pattern is described as a design pattern designed to standardize your projects with GetX on Flutter, and it is worth being clear from the start that nothing here is a dependency you install. The package it organises is GetX, published on pub.dev, and this repository is a proposal for how to arrange the directories around it.

The objectives are listed in the README and they read as a list of frustrations rather than a feature list. Facilitate the learning of the package, have a solid and standard structure for developing applications with GetX, facilitate the use of GetX in an organized, simple and scalable way, and facilitate the search for information and dissemination of knowledge.

The last two are about the community as much as the code. A standard layout means that when someone asks a question about a GetX project, the answer is in a predictable place, and when someone writes a tutorial, the example matches what other people have.

The repository itself is a website. The top level holds app.js, index.html and styles.css, with images/, examples/ and an exemples/ directory, which is a documentation site rather than a Flutter package. The Flutter material lives in examples/getx_pattern_example/ and examples/getx_pattern_site/. There are no GitHub releases, the licence is not stated in the metadata, and the last push was on 2026-09-18.

The module is the unit of the pattern

The structure the README presents is organised into modules, and each module is one screen.

A module contains a page.dart, its controller.dart, its binding.dart and its repository.dart, and optionally a local_widgets folder for widgets that are reusable inside that module but nowhere else. The README states the rule plainly: each screen is treated as an independent module, with its own controller, and it can also contain its own dependencies.

The repository inside the module is the part that surprises people, and the README explains the reasoning at length. The decision to transfer the repositories globally into the internal modules of each module is so that a function can be used in different modules, but the original problem was having to import more than one repository in the controller. So the same call functions are repeated internally, which maintains faster maintenance and makes everything that gives life to the module reachable through the module itself.

In other words, the trade is explicit duplication for locality. A controller in one module does not import a repository from another module; it has its own local copy of the interface. For a project where a controller needs three different repositories, that is a real cost, and the pattern is asking you to accept it in exchange for a module that can be read, moved and deleted as a unit.

The module structure is also what makes the binding meaningful, since the binding is created per module and the controller is resolved through it.

Bindings are the load-bearing idea

The Binding class is what decouples dependency injection, while binding routes to the state manager and the dependency manager.

That sentence is dense, so it is worth taking it apart, because the README spells out the consequences. The binding lets you know which screen is being displayed when a specific controller is used, and it knows where and how to dispose of it.

This is the practical difference between a GetX project with a pattern and one without. In an unstructured GetX app, a controller is usually created lazily by Get.find or put somewhere in a global scope, and the question of when it is disposed becomes a matter of individual discipline. Each screen's lifetime and its controller's lifetime are supposed to be the same thing, and the binding is the object that ties them together.

On top of that the binding gives you control over the SmartManager configuration, so you can configure how dependencies are organised, and remove a route from the stack, or choose when the widget used for disposal happens, or none of them.

That last option is the useful one in practice. Some controllers hold a subscription or a stream listener that should not be torn down when the route pops, and a binding that controls disposal is what lets you say so in one place instead of in the controller's onClose.

The repository file in the module is described as a class pointing to the controllers of the module, and to which provider is going to be consumed. The same goes for services, since a service that has integration with some provider must have its own repository.

The data layer, and why controllers stay ignorant

The data part of the structure lives in /lib/app/data, and it is where the pattern's central abstraction sits.

Under /provider are the data providers, which the README says can be an API, a local database or Firebase for example, with api_provider.dart, db_provider.dart and storage_provider.dart as the examples. The rule for where things go is stated directly: our asynchronous data request, HTTP and local database functions must remain in the provider layer.

Above that is /services, with an example_service.dart containing a service.dart and a repository.dart. The description of a repository is the heart of it: repositories are classes that mediate the communication between the controller and the data. Our controllers will not need to know where the data comes from, and you can use more than one repository on a controller if you need to.

The repositories must be separated by entities and can almost always be based on their database tables. If there is a user table that will be persisted, edited, added, updated and deleted, and all of those functions are requested from an API, there will be a repository for that object of the API where the functions are called. The controller does not need to know where it comes from.

/enums holds the enumerations and /model holds the classes, the data models responsible for abstracting the objects, with model.dart as the example.

So the layering is provider, then service, then repository, then controller, and the rule is that the controller talks to a repository and never to a provider. If your controller can see an HTTP client, the pattern has been broken.

Core, routes and the pieces meant to be shared

Two directories are explicitly for things used across more than one module.

/global_widgets holds widgets that can be reused by multiple modules. Everything else reusable lives in /core, which has an /errors directory for error handling and classes, and a /values directory with strings.dart for globally reusable strings and colors.dart for reusable colours. There is a /languages directory for applications that use internationalisation, where the translation files are deposited, with a /from subfolder holding pt-br.dart and en-au.dart as the examples.

The /theme directory is where themes for widgets, texts and colours are created, with text_theme.dart, color_theme.dart and app_theme.dart as the three files, each illustrated in the README with a one line example of what goes in it.

The /routes directory is the one with a specific design decision in it. The pattern separates routes into two files and two classes. routes.dart holds the route constants, with the example of a Routes class containing a HOME constant, and pages.dart holds the routing array, with the example of an AppPages class containing a static final list of GetPage entries that name a route and build a page.

Splitting the constants from the page list is the kind of thing that looks fussy until you have a large application, where the two files change for different reasons and a single file becomes a merge conflict magnet.

At the root of the whole thing is /lib/app, which the README describes as where all the application's directories are contained.

The documentation lives in three places and none of them is complete

The state of the documentation is the most useful thing to know about this project, because the pattern is the documentation.

The README notes that it and its examples are more updated than the website's, and that the work in progress is an English and multi-language version. The original article is in Brazilian Portuguese, published on Medium, and the documentation at GitHub Pages is the pt-BR version. A new website is under construction in a separate repository, getx-pattern-site.

There is also a VS Code extension, GetX Snippets, published in the marketplace, made to work with getx_pattern and described as greatly speeding up development with GetX.

And at the top of the README there is a pointer to a new approach, the minimals_architecture repository. That is the author's own signal about where the thinking is going, and it is the first thing to read if you are starting a project today rather than learning an existing one.

The pattern itself is a small idea with a large surface, and the documentation being incomplete is not unusual for that kind of contribution. What it means for an adopter is that the examples directory, not the website, is where you should look for how a module is actually written.

The authorship is worth noting too, since the pattern is presented in the first person throughout, in a voice that assumes you are reading a colleague's proposal rather than a specification.

Editorial conclusion

getx_pattern fits a team that has already chosen GetX and wants every feature in the same shape, with the argument for it being that a binding ties a screen to its controller and its disposal, which is the part of GetX that is easy to get wrong. It does not fit a team that is still choosing a state management approach, since the pattern presupposes GetX, and it does not fit anyone who needs a maintained reference implementation, because the website is behind the README, the examples are the real documentation, and the licence is not stated. Verify three things before you adopt the layout: that your controllers really do not need to know where the data comes from, since the repository boundary is the load-bearing part of the design, that the binding disposal story matches how your screens are popped, and that the language and routing files under core are generated the way you expect, because the pattern puts constants and page lists in two separate files on purpose.

Frequently asked questions

What does the getx_pattern actually provide?

It is a proposal for a standard folder structure for Flutter projects that use GetX, with the stated objectives of facilitating the learning of the package, providing a solid and standard structure, keeping the use of GetX organised, simple and scalable, and making information about the pattern easier to find. Nothing is installed as a dependency; GetX itself is the package being organised.

What goes in a module in the getx_pattern?

Each screen is an independent module containing a page.dart, a controller.dart, a binding.dart and a repository.dart, plus an optional local_widgets folder for widgets reusable only inside that module. The module carries its own repository so that everything giving life to the module is reachable through the module itself, at the cost of repeating the same call functions internally.

What is a Binding class for in getx_pattern?

The Binding decouples dependency injection while routing to the state manager and the dependency manager, so you know which screen is displayed when a controller is used and where and how that controller is disposed. It also gives you SmartManager configuration control, letting you organise dependencies and choose when a route is removed from the stack and when the widget used for disposal happens, or none of them.

Where does data access live in the getx_pattern?

Under lib/app/data. The provider layer holds the API, database or storage providers and is where the asynchronous requests must stay, the services layer holds a service and its repository per entity, and the model layer holds the data classes. The repository mediates between the controller and the data, so controllers never need to know where the data comes from.

Is getx_pattern still the recommended approach?

The README points to a new approach, the minimals_architecture repository, at the top of the page. The documentation site is behind the README and its examples, the original article and the published documentation are in Brazilian Portuguese, and a new website is under construction in the getx-pattern-site repository, with a GetX Snippets extension for VS Code available alongside.

Official sources

  1. Issues
  2. kauemurakami/getx_pattern on GitHub
  3. Project website
  4. README
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/kauemurakami-getx-pattern.svg)](https://hysenlabs.com/projects/kauemurakami-getx-pattern)

Was this useful?