Blogs/Technology

What is Flutter Widget Tree: A Comprehensive Guide

Written byDevesh Mhatre
Aug 4, 2026
16 Min Read
What is Flutter Widget Tree: A Comprehensive Guide Hero
Too Long? Read This First
- A widget is an immutable description of part of the interface.
- The widget tree represents those descriptions through parent-child relationships.
- Flutter inflates widgets into elements, which provide stable identity and manage the underlying tree.
- Stateful widgets do not contain mutable state themselves; their associated State objects do.
- Render objects perform layout, painting, and hit testing for widgets that participate in rendering.
- A rebuild creates new widget configurations, but Flutter can reuse existing elements and render objects.
- Flutter matches a new widget with an existing element primarily by position, runtime type, and key.
- Keys are needed when position alone cannot preserve the correct identity, particularly when similar children move or are reordered.const Widgets can help Flutter reuse identical widget instances, but they do not make all parent rebuilding disappear.
- A deeply nested widget tree is not automatically slow. Profile build, layout, paint, and raster work before optimising.

Flutter applications are built by composing widgets. A screen may appear to contain a simple app bar, list, and button, but Flutter represents that interface as a hierarchy of many small configuration objects.

That hierarchy is commonly called the widget tree.

Understanding it changes how developers approach Flutter. It explains why widgets are immutable, why build() may run frequently, how setState() affects a subtree, how Flutter preserves a State object, and why keys become important when widgets move.

The widget tree is only one part of the framework’s internal model. Flutter also maintains an element tree and a render tree. These three structures work together to turn declarative widget configurations into the interface displayed on the screen.

This guide explains the Flutter widget tree, its relationship with elements and render objects, how rebuilding works, when keys matter, and how to diagnose performance problems without applying misleading rules.

What Is the Flutter Widget Tree?

The Flutter widget tree is a hierarchical description of an application’s user interface. Each widget occupies a position in that hierarchy, with parent widgets configuring or containing child widgets.

Flutter’s official API describes a widget as an immutable description of part of a user interface. A widget is not the rendered object on the screen and does not hold mutable visual state. Instead, it describes the configuration Flutter should use at that position in the interface.

This distinction is central to Flutter’s declarative model.

In an imperative UI system, developers may locate an existing view and mutate its properties directly. In Flutter, the application normally changes state and produces a new widget description. The framework compares that description with the previous configuration and updates the persistent internal structures.

The widget tree is therefore better understood as a configuration blueprint than as a collection of permanent UI objects.

Is Everything in Flutter a Widget?

“Everything is a widget” is a helpful introduction, but it is not literally true of every object in a Flutter application.

The interface is composed through widgets, including:

  • Layout
  • Text
  • Images
  • Buttons
  • Themes
  • Navigation
  • Padding
  • Alignment
  • Gestures
  • Animation configuration

However, Flutter also contains objects that are not widgets, including:

  • Elements
  • Render objects
  • State objects
  • Controllers
  • Focus nodes
  • Animation objects
  • Routes
  • Services
  • Models and repositories

The phrase is useful because Flutter expresses most UI composition through widgets. Developers should nevertheless understand the non-widget objects that maintain state, calculate layout, paint pixels, and manage application behaviour.

The Two Main Widget Categories

Flutter commonly introduces widgets through two categories: StatelessWidget and StatefulWidget.

StatelessWidget

A StatelessWidget does not own mutable state that changes during its lifetime. Its build() output depends on its current configuration and the ambient information available through BuildContext.

Examples include Text, Icon, and Container.

“Stateless” does not mean the widget is built only once. A stateless widget can rebuild when:

  • Its parent supplies a new configuration.
  • An inherited dependency changes.
  • Its parent rebuilds and Flutter visits that position.
  • It is removed and inserted again.

The important distinction is that the widget does not maintain a separate mutable State object.

StatefulWidget

A StatefulWidget is also immutable. It creates a separate State object that can hold mutable data across widget replacements at the same location.

The two objects have separate responsibilities:

  • StatefulWidget stores immutable configuration.
  • State stores mutable state and implements lifecycle behaviour.

Examples include TextField, Checkbox, and AnimatedContainer.

When setState() is called, Flutter marks the corresponding element as requiring another build. The associated State object is not automatically recreated. It can survive repeated widget configurations as long as Flutter continues to identify that location as the same stateful component.

Widgets can also be categorised according to function:

Widget categoryExamplesResponsibility
LayoutRow, Column, Stack, ExpandedPosition and constrain children
Painting and displayText, Image, IconDescribe visible content
InputTextField, ElevatedButton, GestureDetectorAccept or interpret interaction
StylingTheme, DefaultTextStyle, DecoratedBoxSupply or apply presentation
ScrollingListView, CustomScrollViewPresent scrollable content
State propagationInheritedWidget and related abstractionsMake values available to descendants
Application structureMaterialApp, Navigator, ScaffoldConfigure major application behaviour
Layout
Examples
Row, Column, Stack, Expanded
Responsibility
Position and constrain children
1 of 7

The Structure of a Flutter Widget Tree

A Flutter application begins with the widget passed to runApp(). That widget becomes the root configuration from which Flutter builds the rest of the interface.

In a Material application, the root is often MaterialApp. In a Cupertino application, it may be CupertinoApp. These are conventions rather than requirements.

A simple structure may look like this:

MaterialApp
  └── Scaffold
       ├── AppBar
       ├── Center
       │    └── Text
       └── FloatingActionButton

The corresponding developer example is:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Widget Tree Example'),
        ),
        body: Center(
          child: Text('Hello, Flutter!'),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {},
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

In this hierarchy:

  • MaterialApp establishes application-level Material configuration.
  • Scaffold provides the basic visual page structure.
  • AppBar describes the top application bar.
  • Center positions its child.
  • Text describes the displayed text.
  • FloatingActionButton represents an interactive action.

The code looks deeply nested because the hierarchy expresses relationships. Center must know which widget it centres, while Scaffold must know which widgets occupy its app bar, body, and floating-action-button slots.

A production application can contain hundreds or thousands of widget instances. Flutter is designed for this form of composition.

The Three Trees in Flutter

The phrase “widget tree” can create the impression that widgets themselves remain attached to the screen. Internally, Flutter coordinates three related structures:

TreeMain purposeCharacteristics
Widget treeDescribes the desired UI configurationImmutable and frequently recreated
Element treeMaintains identity, lifecycle, and tree positionPersistent and mutable
Render treePerforms layout, painting, and hit testingPersistent and mutable
Widget tree
Main purpose
Describes the desired UI configuration
Characteristics
Immutable and frequently recreated
1 of 3

These are conceptually related but not necessarily identical one-to-one visual trees.

1. Widget Tree

The widget tree contains widget instances produced by build() methods and other widget constructors.

Widgets are intentionally lightweight and immutable. Creating another Text, Padding, or custom widget configuration does not mean Flutter immediately discards and recreates the corresponding rendered content.

A widget tells Flutter:

  • Which element configuration belongs at this position
  • Which child or children it contains
  • Which values have changed
  • Which properties the underlying implementation should use

Because widgets contain immutable configuration, the framework can reason predictably about changes.

2. Element Tree

When Flutter incorporates a widget into the active application, it inflates that widget into an element.

The element provides stable identity at a position in the tree. It maintains the relationship between the latest widget configuration and the underlying framework structures.

Elements are responsible for work such as:

  • Holding a reference to the current widget
  • Maintaining parent-child relationships
  • Providing BuildContext
  • Tracking dependencies on inherited widgets
  • Managing lifecycle transitions
  • Associating a State object with a stateful widget
  • Creating and updating render objects where appropriate
  • Marking parts of the tree dirty for rebuilding

This is why BuildContext should be understood as a handle to a widget’s location in the element tree, not as the widget itself.

When a new widget is produced at an existing position, Flutter decides whether the current element can be updated or must be replaced.

3. Render Tree

Render objects perform the lower-level work of displaying and interacting with visual content.

Depending on their role, they may:

  • Receive constraints from a parent
  • Select a size
  • Position children
  • Paint content
  • Perform hit testing
  • Provide semantic information
  • Mark themselves for layout or painting

Let’s Build Your Flutter App Together!

Work with our expert team to turn your app idea into a fast, stunning Flutter product.

Not every widget creates a render object directly. Widgets such as StatelessWidget and StatefulWidget build other widgets. Widgets derived from RenderObjectWidget connect more directly to render objects.

Flutter’s architectural overview explains how widget, element, and render-object responsibilities remain separated.

How the Three Trees Work Together

The relationship can be summarised as follows:

Application state
       ↓
New widget configurations
       ↓
Elements reconcile old and new widgets
       ↓
Render objects are updated where required
       ↓
Layout, paint, compositing, and display

A state change does not necessarily mean every phase runs for the entire screen.

For example:

  • A rebuild may produce the same widget instance for a child, allowing traversal to stop there.
  • A changed text value may update an existing render object without replacing it.
  • A colour change may require painting but not layout.
  • A size change may require layout and painting.
  • A state change unrelated to the visible UI may produce no render change.

Rebuild, layout, paint, and rasterisation are different kinds of work. Developers should avoid using “rebuild” as a general label for every performance problem.

How the Widget Build Process Works

A widget’s build() method returns another widget or subtree describing the UI for the current state and dependencies.

Flutter can call build() when:

  • The widget is first inserted.
  • setState() marks a stateful element dirty.
  • A parent supplies a new widget configuration.
  • An inherited dependency changes.
  • An element is moved or reactivated.
  • The framework requires the subtree to update.

A build() method should therefore be:

  • Fast
  • Free from expensive repeated computation
  • Free from network requests
  • Free from irreversible side effects
  • Deterministic for the current inputs

Developers should not treat build() as a one-time initialization function.

How Flutter Reconciles a New Widget

When a parent produces a new child widget, Flutter compares it with the widget currently associated with the child element.

The existing element can normally be updated when the new and old widgets have the same runtime type and key. If either differs, Flutter removes the old element and inflates the new widget into a different element.

This decision affects state retention.

If a StatefulWidget remains in the same location with the same type and key, the existing State object can continue. If Flutter determines that the new widget represents a different identity, the old state is disposed and new state is created.

Rebuild Does Not Mean Re-render Everything

Creating widget objects is generally inexpensive. The cost becomes important when a build performs expensive work, updates a very large affected subtree, triggers unnecessary layout, or causes costly painting and rasterisation.

This is why “number of rebuilds” alone is not a sufficient performance metric.

A small widget that rebuilds frequently may be harmless. A single rebuild that performs synchronous parsing, rebuilds a complex list, or triggers expensive intrinsic layout can cause visible jank.

How setState() Affects the Widget Tree

Calling setState() tells Flutter that the internal state used by a State object has changed and that its UI description may need to be rebuilt.

A useful simplified sequence is:

  1. The callback passed to setState() changes state synchronously.
  2. Flutter marks the corresponding element dirty.
  3. During the next build phase, Flutter calls that State object’s build() method.
  4. The new subtree is reconciled with the existing elements.
  5. Render objects are updated only where the resulting configuration requires it.

It is common to say that setState() rebuilds the entire subtree. More precisely, it initiates a build at that stateful element. Descendant build methods may run, but Flutter can stop traversal when it encounters an unchanged widget instance.

The main optimisation is to place changing state close to the smallest part of the interface that depends on it.

Is setState() Bad?

No. setState() is the standard mechanism for managing local state in Flutter.

Problems appear when:

  • State is stored much higher than the UI that consumes it.
  • One state object owns many unrelated concerns.
  • Expensive work is performed inside build().
  • Changes occur repeatedly within a frame.
  • Large collections are recreated unnecessarily.
  • Widgets depend on broad inherited state when they need one small value.

Provider, Riverpod, Bloc, and other state-management approaches can help organise dependencies and control notifications. They do not automatically improve performance. Poorly scoped provider or bloc updates can still rebuild more UI than necessary.

Understanding const Widgets

The supplied example is:

const Text('Hello, Flutter!'),

A constant widget can be created at compile time and canonicalised. When Flutter encounters the same widget instance during reconciliation, it can avoid visiting that child subtree.

This can reduce object allocation and rebuilding work, particularly for unchanged sections beneath a frequently rebuilding parent.

However, several nuances matter:

  • A parent’s build() method can still run.
  • const does not prevent state higher in the tree from changing.
  • A widget cannot be constant when its constructor arguments are runtime values.
  • Adding const everywhere does not fix expensive layout, painting, images, or business logic.
  • The practical benefit varies with the subtree and update frequency.

Use const where it correctly describes immutable configuration. Treat it as one small optimisation and a clarity improvement, not as the foundation of all Flutter performance.

How Keys Preserve Widget Identity

Without keys, Flutter usually matches children according to their position and runtime type.

That works well for stable structures. If the first child remains the first child and the types are unchanged, Flutter can update the existing elements naturally.

Keys become important when similar widgets:

  • Change order
  • Are inserted in the middle
  • Are removed
  • Move between locations
  • Need state associated with a domain object
  • Participate in an animated list or transition

Local keys

Common local key types include:

ValueKey

A ValueKey identifies a widget using a value such as a database ID or stable item identifier. It is often appropriate for lists of domain objects.

ObjectKey

An ObjectKey uses object identity to distinguish a widget. It can be useful when the object instance itself represents identity.

UniqueKey

A UniqueKey is equal only to itself. Creating a new UniqueKey during every build tells Flutter that the widget is always different, which destroys rather than preserves the previous element identity.

Use it only when intentionally forcing distinct identity.

GlobalKey

A GlobalKey is unique across the application and can support capabilities that local keys do not, such as accessing a particular state or moving a subtree while preserving state.

That power comes with lifecycle and performance costs. Reparenting a globally keyed subtree can trigger deactivation and dependency updates through its descendants.

Do not create a new GlobalKey inside build(). Own it from a longer-lived object when it is genuinely required.

Prefer local keys when identity only needs to be unique among siblings.

How to Manage a Flutter Widget Tree

The objective is not to produce the shallowest possible tree. The objective is to create a tree whose structure reflects UI responsibilities and update boundaries.

1. Compose widgets according to responsibility

Nested Padding, Align, Row, Column, and other widgets are normal Flutter code. Do not combine or remove them solely to reduce tree depth if doing so makes the layout less accurate or readable.

Extract a widget when it represents:

  • A meaningful interface component
  • A reusable pattern
  • An independent state boundary
  • A separately testable unit
  • A subtree that changes for different reasons from its parent

Composition is one of Flutter’s core design patterns.

2. Keep expensive work out of build()

Avoid parsing large data structures, sorting substantial collections, running network requests, or performing expensive synchronous transformations inside build().

Prepare or cache derived values at an appropriate layer. If computation is genuinely heavy, profile it and consider moving it away from the UI isolate where suitable.

3. Localise changing state

If only a counter changes, the entire screen does not need to own that counter’s state. Moving state closer to the affected component narrows the area that begins rebuilding.

The same principle applies to inherited state and reactive state-management libraries. Subscribe as close as practical to the value being consumed.

4. Extract widgets rather than only helper methods

Moving markup into a helper function improves readability, but the returned widgets are still built as part of the same parent method.

Extracting a dedicated widget gives Flutter a separate element boundary. If the parent reuses the same child widget instance, the framework can stop traversal at that point.

The decision should still be driven by responsibility and change patterns, not arbitrary file size.

5. Use builder widgets for their actual roles

Builder, LayoutBuilder, and Consumer solve different problems.

  • Builder introduces a new BuildContext.
  • LayoutBuilder builds according to constraints supplied during layout.
  • Consumer subscribes part of a tree to provider changes.

These widgets do not automatically improve performance. LayoutBuilder can rebuild when constraints change, while a broadly scoped Consumer can still update a large subtree.

Use each tool because its behaviour matches the requirement.

6. Build long collections lazily

For long or unbounded collections, builder constructors create children as needed rather than constructing the entire collection eagerly.

This reduces initial build work and memory use. The benefit is not that the overall tree becomes shallow; it is that only the currently required list children are materialised.

7. Profile before changing architecture

Use Flutter DevTools to identify the actual expensive stage.

Let’s Build Your Flutter App Together!

Work with our expert team to turn your app idea into a fast, stunning Flutter product.

The Performance view can track:

  • Widget builds
  • Layout operations
  • Paint operations
  • Raster time
  • Shader activity
  • Garbage collection
  • HTTP timing
  • Expensive clipping, opacity, or physical-shape layers

Flutter’s DevTools performance documentation explains how to enable enhanced tracing. These options can add overhead, so use them for diagnosis rather than leaving them enabled during ordinary measurement.

Common Widget-Tree Mistakes

Mistake 1: Treating every rebuild as a defect

Rebuilding is a normal part of Flutter’s declarative design. Optimise rebuilds that produce measurable cost, not every widget highlighted by a debug overlay.

Mistake 2: Keeping all state at the top of a screen

High-level state can be appropriate when many descendants require it. Local interaction state should usually remain closer to the component that changes.

Mistake 3: Adding keys everywhere

Keys are not a general performance flag. Unnecessary or unstable keys can cause Flutter to discard reusable elements and state.

Use a key when identity cannot be inferred correctly from type and position.

Mistake 4: Recreating GlobalKeys during build

A newly created GlobalKey loses its connection to the previous subtree. It can also reset state and disrupt gestures or focus. A global key should normally be owned outside the frequently running build method.

Mistake 5: Assuming a shallow tree is always faster

Flutter’s own widget library creates deeply composed structures. Flattening a clear widget hierarchy into custom painting or oversized widgets can make the application harder to maintain without solving the real performance problem.

Mistake 6: Forgetting lifecycle cleanup

Objects owned by a State instance may require cleanup, including:

  • TextEditingController
  • AnimationController
  • ScrollController
  • FocusNode
  • Stream subscriptions
  • Timers
  • Change-notifier listeners

Release them in dispose() when the state object owns their lifecycle.

Mistake 7: Confusing build, layout, and paint

A widget rebuild can be inexpensive while layout or painting is expensive. Conversely, an animation can repaint without rebuilding a broad widget subtree.

Use profiling evidence to determine which phase is responsible for dropped frames.

Practical Example: A Dynamic Widget Tree

The developer’s todo application demonstrates a widget tree that changes in response to state:

import 'package:flutter/material.dart';

void main() {
  runApp(TodoApp());
}

class TodoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: TodoScreen(),
    );
  }
}

class TodoScreen extends StatefulWidget {
  @override
  _TodoScreenState createState() => _TodoScreenState();
}

class _TodoScreenState extends State<TodoScreen> {
  final List<String> _todos = [];
  final TextEditingController _controller = TextEditingController();

  void _addTodo() {
    if (_controller.text.isNotEmpty) {
      setState(() {
        _todos.add(_controller.text);
        _controller.clear();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Todo List'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      hintText: 'Enter a todo',
                    ),
                  ),
                ),
                const SizedBox(width: 8.0),
                ElevatedButton(
                  onPressed: _addTodo,
                  child: const Text('Add'),
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: _todos.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(_todos[index]),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

What happens when a todo is added?

The interaction follows this sequence:

  1. The button calls _addTodo().
  2. The input is checked for content.
  3. The callback passed to setState() updates _todos and clears the controller.
  4. Flutter marks _TodoScreenState’s element dirty.
  5. Its build() method runs again.
  6. Flutter reconciles the new widget descriptions with the existing elements.
  7. ListView.builder reflects the increased itemCount.
  8. A new ListTile is built when required by the list viewport.

The State object and TextEditingController survive the rebuild. They are not recreated because the stateful component retains its identity.

Why ListView.builder matters

ListView.builder creates list children on demand. This is appropriate when a collection may become large because Flutter does not need to build every item immediately.

In this example, todos are only appended, so position-based identity is sufficient for the simple text rows. If rows gained their own mutable state and could be reordered or removed, stable keys based on todo identity would become important.

Why dispose() matters

_TodoScreenState creates and owns the TextEditingController. Disposing it when the state leaves the tree releases the resources and listeners associated with the controller.

This is a lifecycle responsibility, not a widget-tree optimisation.

Widget Tree vs Element Tree vs Render Tree

QuestionWidget treeElement treeRender tree
What does it represent?Desired UI configurationActive identity and lifecycleLayout and visual output
Is it immutable?YesNoNo
Is it frequently recreated?YesUsually updated and reusedUsually updated and reused
Does it hold State?NoConnects state with a positionNo
Does it provide BuildContext?NoYesNo
Does it calculate layout?NoCoordinates framework relationshipsYes
Does it paint?NoNoYes
Does every entry have a direct visual object?NoNoRender entries participate in rendering
What does it represent?
Widget tree
Desired UI configuration
Element tree
Active identity and lifecycle
Render tree
Layout and visual output
1 of 8

Frequently Asked Questions

1. What is the Flutter widget tree?

The Flutter widget tree is the hierarchy of immutable widget configurations that describes an application’s user interface. Parent-child relationships express layout, content, styling, interaction, and application structure.

2. Why is the widget tree important?

It is the starting point of Flutter’s declarative UI system. Understanding it helps developers reason about rebuilding, state retention, context, keys, component boundaries, and the framework’s rendering pipeline.

3. What are the three trees in Flutter?

Flutter coordinates a widget tree, element tree, and render tree. Widgets describe configuration, elements maintain active identity and lifecycle, and render objects perform layout, painting, and hit testing.

4. What is the difference between a widget and an element?

A widget is an immutable configuration. An element is the persistent object created when that widget is incorporated into the active tree. The element stores the widget’s location, lifecycle relationships, dependencies, and associated state.

5. Does Flutter rebuild the entire widget tree after every change?

No. A state change marks a particular element for rebuilding. Flutter then reconciles the resulting subtree and can reuse elements and render objects where identity remains compatible.

6. How does setState() affect the tree?

setState() changes local state and marks the corresponding element dirty. Flutter calls its build() method during the next build phase and reconciles the new widget subtree with the existing elements.

7. When should keys be used?

Use keys when sibling position and runtime type are insufficient to identify widgets correctly. Common cases include reordered lists, inserted items, removed items, and widgets whose state must follow a domain object.

8. Is a deep widget tree bad for performance?

Not by itself. Flutter is designed for nested widget composition. Performance depends more on expensive build work, broad updates, layout, painting, rasterisation, and resource use. Measure before flattening a tree.

9. Do const constructors stop widgets from rebuilding?

They can allow Flutter to reuse identical widget instances and stop traversal into unchanged subtrees. They do not prevent ancestors from running build() or eliminate layout, painting, and other performance costs.

10. How does the widget tree relate to rendering?

Flutter inflates widgets into elements. Those elements create or update render objects where needed. Render objects then perform layout, painting, hit testing, and related rendering work.

Conclusion

The Flutter widget tree is an immutable description of what the application interface should be for the current state. It is not the final rendered UI and does not independently preserve mutable state.

Flutter converts those configurations into a persistent element tree. Elements maintain identity, lifecycle, BuildContext, inherited dependencies, and state relationships. Render objects perform the lower-level layout, painting, and hit-testing work.

This separation explains why Flutter can rebuild widget configurations frequently without recreating the entire interface. It also explains why type, position, and keys influence state retention.

The most useful performance lessons are not “avoid nesting” or “never rebuild.” They are:

  • Keep expensive work out of build().
  • Place state close to the UI that consumes it.
  • Use stable keys when widgets move.
  • Use const where the configuration is genuinely constant.
  • Build long collections lazily.
  • Dispose of owned resources correctly.
  • Measure build, layout, paint, and raster work independently.

Once developers understand these relationships, Flutter behaviour becomes easier to predict. Rebuilds stop looking mysterious, keys become a deliberate identity tool, and performance optimisation becomes an evidence-based process rather than an attempt to make every widget tree smaller.

Author-Devesh Mhatre
Devesh Mhatre

Tech enthusiast with a passion for open-source software and problem-solving. Experienced in web development, with a focus on React, React Native and Rails. I use arch (and neovim) btw ;)

Share this article

Phone

Next for you

8 Best GraphQL Libraries for Node.js in 2025 Cover

Technology

Aug 4, 202613 min read

8 Best GraphQL Libraries for Node.js in 2025

8 Best GraphQL Libraries for Node.js in 2026 Too Long? Read This First - Choose Apollo Server when you need a mature ecosystem, GraphOS integration, plugins, or Apollo Federation. - Choose GraphQL Yoga for a modern, portable server with Fetch API compatibility and built-in support for subscriptions over Server-Sent Events. - Choose Mercurius when your application already uses Fastify and runtime efficiency is a major priority. - Use GraphQL.js when you need the official JavaScript implementati

9 React Native Animation Libraries and Tools Compared Cover

Technology

Aug 4, 202615 min read

9 React Native Animation Libraries and Tools Compared

Too Long? Read This First - Use React Native Reanimated for gesture-driven, interruptible, and performance-sensitive interface animations. - Use the built-in Animated API for simple fades, transforms, and timed sequences without another dependency. - Pair React Native Gesture Handler with Reanimated for swipes, dragging, pinching, rotation, and other touch-driven experiences. - Use Lottie React Native for non-interactive motion graphics supplied by designers. - Choose React Native Skia for cust

9 Critical Practices for Secure Web Application Development Cover

Technology

Aug 4, 202616 min read

9 Critical Practices for Secure Web Application Development

Too Long? Read This First - Define security requirements and model threats before implementation begins. - Treat authentication, account recovery, and MFA as one complete identity system. - Apply server-side authorization to every protected action and object. - Prevent injection with parameterized APIs, structured validation, safe output handling, and restricted outbound requests. - Protect sessions and tokens throughout their complete lifecycle. - Minimise sensitive data and manage encryption