Successfully translating a Figma design into a Flutter application requires more than just placing elements on the screen. The objective is to achieve pixel-perfect fidelity, meaning that the Flutter app must precisely mirror the designer's original vision. This involves paying close attention to every detail, from shadows and curve radii to line heights and spacing. A small discrepancy in any of these areas can alter the intended look and feel of the user interface.

This comprehensive guide provides actionable strategies and practical methods for developers. It covers the specific steps and considerations needed to bridge the gap between design files and functional code. By following the practices outlined here, you will be able to transform static Figma artboards into high-quality, fully functional Flutter UIs that exactly match the design specifications.

Table of Contents

Prerequisites

To effectively follow and implement the strategies outlined in the comprehensive guide for pixel-perfect Figma to Flutter replication, you should ideally possess the following prerequisites:

I. Foundational Programming & Framework Knowledge

  1. Dart Programming Language:

    • Core Concepts: Solid understanding of Dart's syntax, data types, variables, control flow (if/else, loops), functions, classes, objects, and asynchronous programming (Futures, async/await).

    • Null Safety: Familiarity with Dart's null safety features.

  2. Flutter SDK & Development Environment:

    • Installation & Setup: Flutter SDK correctly installed and configured on your machine.

    • IDE Proficiency: Familiarity with a Flutter-compatible IDE like VS Code or Android Studio, including running/debugging apps, using hot reload/restart.

    • Basic Project Structure: Understanding of a typical Flutter project's directory structure (lib, assets, pubspec.yaml, etc.).

  3. Fundamental Flutter Concepts:

    • Widget Tree: A clear understanding of how Flutter's widget tree works, including parent-child relationships and widget composition.

    • StatelessWidget & StatefulWidget: Ability to differentiate and appropriately use StatelessWidget for static UI and StatefulWidget for dynamic/interactive UI.

    • Build Context: Understanding of BuildContext and its role in the widget tree.

II. Essential Figma Knowledge

  1. Figma Interface Navigation:

    • Ability to open and navigate Figma files and artboards.

    • Understanding of layers, groups, and frames.

  2. Figma "Inspect" Panel Mastery:

    • Crucial: Proficient use of the "Inspect" panel to extract precise values for:

      • Dimensions (width, height)

      • Spacing (padding, margin, gap between elements)

      • Colors (hex codes, RGB, opacity)

      • Typography (font family, weight, size, line height, letter spacing)

      • Borders (radius, width, color)

      • Shadows (offset, blur, spread, color, opacity)

      • Gradients (colors, stops, angle)

    • Understanding Auto Layout: Basic comprehension of how Auto Layout works in Figma, as it often dictates Flutter's Column/Row and Spacer/Expanded usage.

  3. Figma Asset Export:

    • Knowledge of how to select and export various assets from Figma (images, SVGs) in the correct formats and resolutions.
  1. Version Control (Git):

    • Basic understanding of Git commands (clone, add, commit, push, pull, branch). This is essential for collaborative development and managing code changes.
  2. Debugging Skills:

    • Ability to use your IDE's debugger to inspect widget trees, variable values, and diagnose issues.

    • Familiarity with Flutter DevTools for UI inspection and performance profiling.

  3. Problem-Solving:

    • A logical approach to breaking down complex problems into smaller, manageable parts.

    • Patience and persistence in troubleshooting visual discrepancies.

Use the Figma "Inspect" Panel: Your Blueprint for Precision

The "Inspect" panel in Figma is your single most valuable resource. Before you write a single line of code, spend significant time dissecting every element here. Think of it as your precise blueprint.

  • Exact Dimensions: Don't approximate. Note down exact width and height values, even if they have decimals (for example, 123.45px). Flutter's double values perfectly accommodate this precision.

  • Granular Spacing: Examine margin and padding from all four sides. Are they uniform, or is there asymmetry? This dictates whether you use EdgeInsets.all(), EdgeInsets.symmetric(), or the more specific EdgeInsets.fromLTRB().

  • Positioning Logic: Understand if an element is absolutely positioned or part of an Auto Layout frame. This crucial distinction determines whether you'll employ Positioned widgets within a Stack or rely on Column/Row with mainAxisAlignment and crossAxisAlignment.

  • Typographical Deep Dive: Extract the exact font family, weight (for example, "Inter Medium," "Inter Bold"), size, line height, letter spacing, and color. Every one of these properties has a direct counterpart in Flutter's TextStyle.

  • Color Codes: Copy the hex codes exactly. Always use Color(0xFFRRGGBB) in Flutter to ensure exact color matching, including the alpha channel if specified.

  • Borders & Shadows: Extract border radius, color, width, and for shadows, the x/y offset, blur, spread, and color. These translate directly to BoxDecoration and BoxShadow properties.

  • Gradients: If a gradient is present, meticulously note its angle, the precise colors involved, and their respective stops. Flutter's LinearGradient or RadialGradient will be your tools here.

Implement a Consistent Spacing & Sizing System: The End of Magic Numbers

Randomly hardcoding 16.0, 8.0, or 24.0 throughout your codebase is a recipe for inconsistency and maintenance headaches. Establish a design system for spacing and sizing.

  • Identify the Base Unit: Figma designs often implicitly use a base spacing unit (for example, all paddings are multiples of 4 or 8 pixels). Identify this consistent increment.

  • Centralized Constants: Create a dedicated file, perhaps lib/utils/app_dimensions.dart, to store your spacing and sizing variables.

      // lib/utils/app_dimensions.dart
      class AppDimensions {
        static const double spacingSmall = 8.0;
        static const double spacingMedium = 16.0;
        static const double spacingLarge = 24.0;
        static const double iconSizeMedium = 24.0;
        // ... and so on for all consistent measurements
      }
    
  • Consistent Usage: Always refer to these constants in your widgets:

      Padding(
        padding: const EdgeInsets.all(AppDimensions.spacingMedium),
        child: // ...
      ),
      SizedBox(width: AppDimensions.spacingSmall),
    
  • Benefit: This approach not only ensures consistent visual rhythm but also simplifies global design adjustments.

Replicate Typography with Absolute Fidelity: Beyond Basic Fonts

Text is a cornerstone of UI design. Achieving pixel-perfect typography means going beyond just selecting the right font family.

  • Custom Font Integration: If your Figma design uses custom fonts, you must correctly add them to your pubspec.yaml and ensure they load properly in your Flutter app.

  • Precise Font Weights: Distinguish meticulously between FontWeight.w400 (Regular), w500 (Medium), w600 (SemiBold), w700 (Bold), and so on. The Figma inspect panel will provide the exact weight.

  • fontSize Accuracy: Use the exact pixel size from Figma for your fontSize property in TextStyle.

  • Line Height (height): This is paramount for vertical text spacing. Figma's "Line Height" property, often expressed as a percentage or pixel value, needs conversion. If Figma states 24px line height for a 16px font size, your TextStyle height property should be 24 / 16 = 1.5.

  • letterSpacing: Directly apply the letter spacing value from Figma (which is often in pixels and translates directly to Flutter's letterSpacing property).

  • textBaseline (Advanced): For very specific multi-font or icon-with-text alignments, you might occasionally need to fine-tune textBaseline to match Figma's visual precision.

Deconstruct Layouts with Flutter's Primitives: Column, Row, Stack, and Spacer

Flutter's declarative layout system offers powerful primitives. Learning to map Figma's visual arrangements to these widgets is key.

  • Primary Flow: Determine if the main flow of elements is horizontal (Row) or vertical (Column).

  • Overlapping Elements (Stack): If elements are layered or positioned on top of each other in Figma, a Stack widget combined with Positioned children is the correct approach. Do not force overlapping elements into Column/Row with complex negative margins or paddings.

  • Content Distribution:

    • mainAxisAlignment: Use this to distribute children along the main axis of a Row or Column (for example, start, center, end, spaceBetween, spaceAround, spaceEvenly).

    • crossAxisAlignment: Use this to align children along the cross axis (for example, start, center, end, stretch, baseline).

  • Flexible Spacing (Spacer): Replicate Figma's "stretch" or "fill available space" auto-layout behaviors using Spacer() widgets within Row or Column.

  • Adaptive Sizing (Expanded, Flexible): When elements need to take up remaining space or be constrained within a certain proportion, Expanded and Flexible are essential. Mimic Figma's "Fill Container" or "Fixed Width" behaviors precisely.

Master BoxDecoration: The Aesthetic Workhorse

BoxDecoration is your primary tool for replicating the visual aesthetics of containers in Figma, including backgrounds, borders, shadows, and gradients.

  • color: The background color of the container, directly from Figma's hex code.

  • borderRadius: Match Figma's exact corner radii. Use BorderRadius.circular() for uniform corners, BorderRadius.only() for specific corners, or BorderRadius.all(Radius.elliptical(x, y)) for more complex shapes.

  • border: Replicate border styles using Border.all(color: ..., width: ...) or more specific options like Border.symmetric() or BorderDirectional() if individual sides have different styles.

  • boxShadow: This is where minute details truly matter. Extract every value:

      boxShadow: [
        BoxShadow(
          color: Color(0x33000000), // Exact color, including opacity (alpha channel)
          offset: Offset(0, 4),      // Exact X and Y offset
          blurRadius: 8,             // Exact blur radius
          spreadRadius: 0,           // Exact spread radius (often 0, but always verify)
        ),
      ],
    
  • gradient: Precisely translate linear or radial gradients:

      gradient: LinearGradient(
        begin: Alignment.topLeft, // Or specific angles derived from Figma
        end: Alignment.bottomRight,
        colors: [Color(0xFF00FF00), Color(0xFF0000FF)], // Exact colors
        stops: [0.0, 1.0], // Exact color stop positions
      ),
    

Utilize ClipRRect and Overflow Management: Handling the Intangibles

Sometimes, elements in Figma might appear to "spill out" or be precisely cropped. Understanding Flutter's clipping and overflow behavior is critical.

  • ClipRRect for Rounded Corners: If a child widget's content needs to be clipped to a parent's rounded corners (for example, an image within a card), wrap the child in ClipRRect. Don't solely rely on the parent's BoxDecoration, especially in complex hierarchies.

  • Overflow Behavior (OverflowBox): Figma designs might show elements extending beyond a frame's boundaries. By default, Column/Row clip content (overflow: Clip.hardEdge). If you need content to be visible outside its immediate parent, you might need a Stack or explicitly manage overflow, potentially using an OverflowBox for specific scenarios.

  • Extended Shadows: If a shadow in Figma extends significantly beyond its element, ensure your BoxShadow spreadRadius and offset values are accurate. Also, confirm that the parent container allows for this visual extension (for example, it doesn't have clipBehavior: Clip.hardEdge if clipping is not desired).

Leverage FittedBox and AspectRatio: Maintaining Proportions

Images and content blocks often need to scale proportionally or fit within specific areas. These widgets are indispensable for responsive design.

  • FittedBox: Excellent for ensuring a child widget (like an icon or text block) scales to fit its parent, while maintaining its original aspect ratio. Carefully consider the fit properties like contain, cover, fill, and scaleDown to match Figma's behavior.

  • AspectRatio: Crucial for images, videos, or any container where the ratio of width to height must be maintained regardless of the available screen space.

      AspectRatio(
        aspectRatio: 16 / 9, // Derived directly from Figma's image dimensions
        child: Image.network('...'),
      ),
    
  • Smart Image Sizing: Avoid setting fixed width and height on Image.network or Image.asset unless the design explicitly dictates a static size. Instead, think about how the image scales and fills its container in Figma.

Replicate Opacity and Blending Modes: The Subtle Layers

Subtle effects often define the "feel" of a design. Don't overlook transparency and blending.

  • Opacity Widget: Use this widget for general element transparency.

  • Alpha Channel in Colors: For background colors, borders, or text colors with transparency, always include the alpha channel in your hex code (for example, 0x80RRGGBB for 50% opacity).

  • ColorFiltered or ShaderMask (Advanced Blending): While less common for everyday designs, if Figma utilizes complex blending modes (for example, "Multiply," "Screen," "Overlay"), you'll need to explore ColorFiltered with its blendMode property or, for more advanced custom effects, ShaderMask. Look for subtle color interactions where one visual layer directly affects another.

Implement Vectors and Icons with Scalability: Sharpness at Any Scale

Rasterizing icons or complex vector shapes is a common mistake that leads to blurriness on different screen densities. Embrace vector graphics.

  • SVG Icons: Always export icons from Figma as SVGs. Leverage a library like flutter_svg to render them in your Flutter app, ensuring crispness and scalability across all device resolutions.

  • CustomPaint for Unique Shapes: For highly unique, non-standard shapes, illustrations, or complex dividers, CustomPainter is your ultimate tool. This requires translating Figma's vector paths (Bezier curves, lines) into Flutter's Path object. This is the epitome of "deep attention to detail" for custom graphics.

  • Icon Fonts: For standard icon sets (for example, Material Icons, Font Awesome), use Flutter's built-in Icon widget or import the specific icon font family into your pubspec.yaml and reference it in your Icon widget.

Master Componentization and Reusability: Building Scalable UIs

Figma's components are not just for design, they're a direct hint at how to structure your Flutter code.

  • Identify Figma Components: Every button, card, input field, or navigation bar that's a component in Figma should ideally be a reusable StatelessWidget or StatefulWidget in Flutter.

  • Prop-Based Customization: Design your Flutter components to accept parameters (props) for text, colors, icons, and interactive behaviors, just like Figma components have variants or properties.

  • Theme Integration: Leverage Flutter's ThemeData to define global styles for colors, typography, and widget behaviors. This mirrors Figma's design tokens and ensures consistency across your app.

  • Shared Styles: Create classes or constants for frequently used TextStyle or BoxDecoration to centralize your design language.

Scrutinize Interactive States: Buttons, Inputs, and Others

Design isn't static. Replicating interactive states is a critical, often overlooked, detail.

  • Hover, Press, Focus: Figma designs often include states for buttons (hover, pressed), input fields (focused, error), and other interactive elements. You must implement these in Flutter using GestureDetector, InkWell, MaterialButton, TextFormField, and so on, and manage their state visually.

  • Animations: If Figma showcases micro-interactions or transitions, plan how to replicate them using AnimatedContainer, Hero animations, PageTransitionsBuilder, or custom AnimationController.

  • Disabled States: Ensure that disabled buttons or input fields are visually distinct and match their Figma counterparts in color, opacity, and cursor changes.

Cross-Reference and Iterate Continuously: The Verification Loop

Replication is not a one-time task, it's an iterative process of comparison and refinement.

  • Side-by-Side Comparison: Always have your Flutter app running on a device or emulator right next to your Figma design. Ideally, take screenshots of your app and overlay them on the Figma design to spot discrepancies.

  • Pixel-by-Pixel Scan: Literally zoom into both the Figma design and your running Flutter app. Look for:

    • Off-by-One Errors: A single pixel difference in padding, border, or spacing.

    • Subtle Color Shifts: Are the colors exactly the same? Account for monitor calibration, but strive for hex code matching.

    • Font Rendering Nuances: Sometimes font rendering can subtly vary across platforms or Flutter's text engine. Adjust letterSpacing or height slightly if needed to achieve visual parity.

    • Shadow Fidelity: Are the shadows exactly as soft/hard, diffuse, and offset as in Figma?

    • Alignment Precision: Even a tiny misalignment of text baselines or icon centers must be corrected.

  • Automated Tools (If Applicable): While manual inspection is paramount, some plugins or third-party tools can assist in comparing Flutter UI with Figma, offering a quick initial check.

  • Peer Review: A fresh pair of eyes from another developer can often spot details you've become blind to.

Understand Design System Thinking: Beyond Individual Components

Why it Matters: Figma files often represent a living design system. Understanding this philosophy helps you build a more robust and maintainable Flutter app.

Actionable Advice:

  • Design Tokens: Recognize how Figma uses "design tokens" (variables for colors, typography, spacing, shadows). Translate these directly into Flutter's ThemeData, custom Color and TextStyle constants, and your AppDimensions class.

  • Component Libraries: Think of your Flutter widgets as a direct extension of the Figma component library. Each component in Figma should ideally correspond to a well-defined, reusable Flutter widget.

  • Naming Conventions: Adopt consistent naming conventions in your code that mirror Figma's (for example, primaryButton, headline1TextStyle). This creates a shared language between designers and developers.

Embrace Constraints and Responsiveness: Adapting to All Screens

Why it Matters: Figma designs are often fixed at a certain width (for example, 375px for mobile). Your Flutter app must be responsive and adapt gracefully to various screen sizes, orientations, and device types.

Actionable Advice:

  • Figma Constraints: Pay close attention to how elements are constrained in Figma (left/right, top/bottom, center, scale). These directly inform your use of Flexible, Expanded, Align, Positioned, and FractionallySizedBox in Flutter.

  • MediaQuery: Use MediaQuery.of(context).size to get the current screen dimensions and adapt layouts accordingly. Avoid fixed pixel widths/heights for entire screens.

  • Layout Builders (LayoutBuilder, OrientationBuilder): For more complex responsive layouts, use LayoutBuilder to get the available constraints of a parent widget and adjust children based on that. OrientationBuilder helps adapt to portrait vs. landscape modes.

  • Relative Units: Where possible, think in terms of percentages or fractions (FractionallySizedBox) rather than absolute pixel values for spacing and sizing that needs to scale.

Handling Assets Efficiently: Images and SVGs

Why it Matters: Proper asset management is crucial for performance and scalability.

Actionable Advice:

  • Export Formats: Discuss with designers the best export formats. For icons and simple illustrations, SVGs are king (flutter_svg library). For complex photos, PNG or WebP (with proper compression) are often preferred.

  • Resolution: For raster images (PNG, JPG), ensure designers export assets at 2x and 3x resolutions, and place them in assets/images/2.0x/ and assets/images/3.0x/ directories respectively, so Flutter automatically picks the correct one for the device's pixel density.

  • Asset Bundling: Declare all your assets in pubspec.yaml under the assets: section.

  • Image Caching: For network images, consider using cached_network_image to improve performance and user experience.

Accessibility Considerations: Designing for Everyone

Why it Matters: A pixel-perfect replica isn't truly complete if it's not accessible. Figma designs should ideally include accessibility annotations, but as a developer, you're the last line of defense.

Actionable Advice:

  • Semantic Widgets: Use Flutter's semantic widgets whenever possible (for example, ElevatedButton instead of a custom Container with a GestureDetector). These widgets often have built-in accessibility features.

  • Meaningful Labels: Provide semanticsLabel for icons and images that convey information to screen readers.

  • Color Contrast: While primarily a design responsibility, double-check color contrast ratios, especially for text, against WCAG guidelines. If the design is failing, flag it.

  • Tap Targets: Ensure interactive elements have sufficiently large tap targets (minimum 48x48 logical pixels) even if the visual element is smaller, using minWidth on buttons or Padding around Icons.

Performance Optimization during Replication

Why it Matters: A beautiful UI is useless if it's janky. Code-level decisions impact performance.

Actionable Advice:

  • const Widgets: Use const constructor for widgets whenever possible. This tells Flutter that the widget can be reused without rebuilding, significantly improving performance. This is a common missed opportunity.

  • RepaintBoundary: For complex, static parts of your UI that don't change often but have many children or custom painting, consider wrapping them in a RepaintBoundary to prevent unnecessary repaints of their children.

  • Avoid Deep Nesting: While Flutter's widget tree is deep, excessively deep nesting can sometimes lead to performance issues. Try to flatten your widget tree where logical (for example, using Wrap instead of many nested Rows for flow layouts).

  • Profile Your App: Use Flutter DevTools's Performance tab to identify UI flaws and memory leaks early in the development process.

Version Control and Collaboration: Working with Teams

Why it Matters: UI development is rarely a solo endeavor. Effective team collaboration is essential.

Actionable Advice:

  • Git Best Practices: Use Git for version control. Create feature branches for specific UI screens or components. Commit frequently with descriptive messages.

  • Code Reviews: Get your UI code reviewed by peers. They can spot missed details, potential performance issues, or suggest better widget usage.

  • Communication with Designers: Maintain an open channel of communication. If a Figma detail is unclear, ask. If a replication is proving difficult, discuss alternatives. Use tools like Slack, Discord, or project management platforms to share progress and clarify requirements.

  • Figma Plugins/Integrations: Explore Figma plugins that might aid developers (for example, extracting CSS/Flutter code snippets, though often these are just starting points).

Handling Edge Cases and Data Dynamics

Why it Matters: Designs often show ideal states. Real-world apps have varying data, empty states, and loading states.

Actionable Advice:

  • Empty States: Replicate any "empty state" designs from Figma (for example, empty shopping cart, no search results).

  • Loading States: How does the UI look when data is being fetched (for example, skeletons, loading spinners)?

  • Error States: What happens if an API call fails or input validation errors occur? Ensure these are designed and replicated.

  • Dynamic Content: Consider how varying text lengths (short vs. long names), image aspect ratios from real data, or lists with many/few items will affect your layout. Test with diverse data.

Implement Vectors and Icons with Scalability: Achieving Visual Consistency Across All Resolutions

Rasterizing icons or complex vector shapes is a common mistake that leads to blurriness on different screen densities. Embrace vector graphics and ensure you're using the exact icons specified in the design.

  • Exact Icon Source Verification:

    • Figma Inspect Panel: For each icon, meticulously check the "Inspect" panel in Figma. Does it indicate a specific icon font (for example, Material Icons, Font Awesome), a custom SVG, or a raster image?

    • Design System Documentation: Consult the design system documentation (if available) for the prescribed icon set and how they should be implemented.

  • SVG Icons (Preferred for Custom Icons):

    • Export from Figma: Always export custom or unique icons from Figma as SVGs. This format ensures they scale without pixelation.

    • Flutter Integration: Leverage the flutter_svg package (add flutter_svg: ^x.x.x to your pubspec.yaml).

        import 'package:flutter_svg/flutter_svg.dart';
        // ...
        SvgPicture.asset(
          'assets/icons/my_custom_icon.svg',
          width: 24.0, // Match Figma's exact size for initial layout
          height: 24.0,
          colorFilter: ColorFilter.mode(Colors.black, BlendMode.srcIn), // Match icon color if needed
        );
      
  • Icon Fonts (Preferred for Standard Sets):

    • Identify the Font: If Figma uses a standard icon font like Material Icons, Cupertino Icons, or Font Awesome, ensure you're using the correct one.

    • Material/Cupertino Icons: For built-in Flutter icons, simply use the Icon widget with the appropriate constant:

        Icon(
          Icons.arrow_back,
          size: 24.0, // Match Figma's exact size
          color: Colors.blue, // Match Figma's exact color
        );
      
    • Custom Icon Fonts (for example, Font Awesome, custom brand icons):

      1. Obtain Font Files: Get the .ttf font file(s) from your designer or the icon font provider.

      2. Add to pubspec.yaml:

         flutter:
           fonts:
             - family: MyCustomIcons
               fonts:
                 - asset: assets/fonts/MyCustomIcons.ttf
        
      3. Reference in Code: Create a static const IconData class or use the direct Icon constructor:

         import 'package:flutter/material.dart';
        
         class MyCustomIcons {
           MyCustomIcons._(); // Private constructor
        
           static const IconData home = IconData(0xe900, fontFamily: 'MyCustomIcons');
           static const IconData settings = IconData(0xe901, fontFamily: 'MyCustomIcons');
           // ... map other icons using their Unicode code points from the font
         }
        
         // Usage:
         Icon(MyCustomIcons.home, size: 24.0, color: Colors.red);
        
  • CustomPaint (For Complex, Unique Shapes):

    • Vector Path Translation: If the icon is a highly custom, unique illustration that can't be easily exported as a simple SVG or is part of a larger complex graphic, you might need to translate its vector paths from Figma into a Path object using CustomPainter. This is the most granular level of icon replication.
  • Avoid Rasterized Icons: Unless an icon is inherently a photograph or complex raster image, never export icons as PNG or JPG as they will pixelate when scaled or viewed on high-density screens.

Self-Correction and Learning from Mistakes

Why it Matters: The best way to improve is to reflect on what went wrong and why.

Actionable Advice:

  • Document Challenges: When you encounter a particularly tricky replication, document the problem, the Figma details, and how you eventually solved it. This builds your knowledge base.

  • Refactor Regularly: As you learn new Flutter techniques or discover more efficient ways to structure your UI, don't be afraid to refactor existing code to apply these improvements.

  • Stay Updated: Flutter and Figma are constantly evolving. Keep an eye on new features, widgets, and best practices that can make your replication process smoother.

To bridge the gap between theory and practice, we’ll build a complete Flutter application that replicates the three distinct UI designs shown below. I got this image from Envato. This project isn't just about copying, it's a practical demonstration of every principle we've discussed, from dissecting Figma's "Inspect" panel values to implementing a robust, scalable, and pixel-perfect component structure.

6ef84737-9847-428a-bd7a-bc9f877c774e

What we’ll build:

  1. A Smart Home Dashboard: Focusing on layout, BoxDecoration, and clean information hierarchy.

  2. A Music Player UI: Highlighting the use of Stack for complex overlapping layouts and custom list items.

  3. An Apartment Booking App: Demonstrating PageView for creating interactive carousels and a custom bottom navigation bar with a FloatingActionButton.

This hands-on example will solidify your understanding and serve as a reference for your own projects. Let's dive into the code.

Project Overview

This project is built following the core principles of a scalable and maintainable Flutter application. We are not just replicating the UI, we are architecting it correctly.

Guide:

  1. Componentization: Every logical piece of the UI (a header, a card, a button) is isolated into its own widget file. This makes the code readable, reusable, and easy to test.

  2. Separation of Concerns: "Screen" files are responsible for the overall layout and state management. "Widget" files are responsible only for their own appearance and internal logic.

  3. Centralized Design System: All colors, dimensions, and text styles are defined in central utility files (utils/), mirroring the concept of "Design Tokens" in Figma.

Final Project Directory Structure

This is the clean, organized file structure we will build. It is the professional standard for Flutter projects.

lib/
├── main.dart
|
├── models/
│   └── track_model.dart
|
├── screens/
│   ├── home_dashboard_screen.dart
│   ├── smart_home_screen.dart
│   ├── music_player_screen.dart
│   └── apartment_booking_screen.dart
|
├── utils/
│   ├── app_colors.dart
│   ├── app_dimensions.dart
│   └── app_styles.dart
|
└── widgets/
    ├── app_mockup_frame.dart
    ├── smart_home/
    │   ├── power_usage_card.dart
    │   ├── remote_access_card.dart
    │   ├── room_card.dart
    │   └── smart_home_header.dart
    ├── music_player/
    │   ├── artist_card.dart
    │   ├── music_player_header.dart
    │   ├── track_list.dart
    │   └── track_list_item.dart
    └── apartment_booking/
        ├── apartment_card.dart
        ├── apartment_carousel.dart
        ├── booking_bottom_nav.dart
        ├── booking_header.dart
        └── booking_search.dart

Step-by-Step Code Implementation

Here is the complete code for each file, with explanations.

1. pubspec.yaml

First, ensure your pubspec.yaml includes the google_fonts package to match the typography.

name: figma_replication_project
description: A new Flutter project.
publish_to: 'none'

version: 1.0.0+1

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  google_fonts: ^6.1.0 # For high-quality, custom fonts

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0

flutter:
  uses-material-design: true

2. Utilities (lib/utils/)

This directory centralizes our design system, perfectly demonstrating the "Design Tokens" and "Consistent Spacing" principles from your article.

lib/utils/app_colors.dart

import 'package:flutter/material.dart';

// Centralizes all application colors for consistency and easy theming.
class AppColors {
  static const Color background = Color(0xFFFFD1B5);
  static const Color primaryBlue = Color(0xFF3D82F8);
  static const Color lightBlue = Color(0xFFD2E2FF);
  static const Color textDark = Color(0xFF2E3A59);
  static const Color textLight = Color(0xFF8F9BB3);
  static const Color cardBackground = Colors.white;
}

lib/utils/app_dimensions.dart

// Centralizes all spacing and sizing values to maintain a consistent visual rhythm.
class AppDimensions {
  static const double spacingXXSmall = 4.0;
  static const double spacingXSmall = 8.0;
  static const double spacingSmall = 12.0;
  static const double spacingMedium = 16.0;
  static const double spacingLarge = 24.0;
  static const double spacingXLarge = 32.0;

  static const double borderRadiusSmall = 8.0;
  static const double borderRadiusMedium = 16.0;
  static const double borderRadiusLarge = 24.0;

  static const double mockupWidth = 320.0;
  static const double mockupHeight = 680.0;
}

lib/utils/app_styles.dart

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'app_colors.dart';
import 'app_dimensions.dart';

// Centralizes text styles and common decoration elements like shadows.
// This ensures absolute fidelity to the Figma typography specs.
class AppStyles {
  // Base text style using a specific Google Font for a modern look.
  static TextStyle get _baseTextStyle => GoogleFonts.poppins(
        color: AppColors.textDark,
      );

  // Specific, named text styles that correspond to the Figma design.
  static TextStyle h1 = _baseTextStyle.copyWith(fontSize: 22, fontWeight: FontWeight.w600);
  static TextStyle h2 = _baseTextStyle.copyWith(fontSize: 18, fontWeight: FontWeight.w600);
  static TextStyle bodyText = _baseTextStyle.copyWith(fontSize: 14, fontWeight: FontWeight.w500);
  static TextStyle subtitle = _baseTextStyle.copyWith(fontSize: 12, color: AppColors.textLight, fontWeight: FontWeight.normal);
  static TextStyle buttonText = _baseTextStyle.copyWith(fontSize: 14, color: Colors.white, fontWeight: FontWeight.w600);

  // Reusable box shadow, matching the Figma properties exactly.
  static BoxShadow cardShadow = BoxShadow(
    color: AppColors.primaryBlue.withOpacity(0.1),
    blurRadius: 20,
    offset: const Offset(0, 10),
  );
}

3. Model (lib/models/)

This holds the data structure for our application's content, separating data from UI.

lib/models/track_model.dart

// Represents the data structure for a single music track.
class Track {
  final String title;
  final String duration;
  final bool isPlaying;

  Track({required this.title, required this.duration, this.isPlaying = false});
}

// Mock data for the music player screen.
final List<Track> topTracks = [
  Track(title: 'Old Town Road', duration: '3:41'),
  Track(title: 'I Don\'t Care', duration: '4:35', isPlaying: true),
  Track(title: 'Dancing With A Stranger', duration: '3:12'),
  Track(title: 'Sweet But Psycho', duration: '4:07'),
  Track(title: 'If I Can\'t Have You', duration: '4:07'),
];

4. Reusable Widgets (lib/widgets/)

This is the core of our component-based architecture.

Generic Widget

lib/widgets/app_mockup_frame.dart

import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:flutter/material.dart';

// A wrapper widget to create the "phone" frame around each UI design.
class AppMockupFrame extends StatelessWidget {
  final Widget child;

  const AppMockupFrame({Key? key, required this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: AppDimensions.mockupWidth,
      height: AppDimensions.mockupHeight,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(AppDimensions.borderRadiusLarge),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withOpacity(0.15),
            blurRadius: 30,
            offset: const Offset(0, 10),
          ),
        ],
        border: Border.all(color: Colors.white.withOpacity(0.5), width: 2),
      ),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(AppDimensions.borderRadiusLarge - 2),
        child: child,
      ),
    );
  }
}

Smart Home Widgets (lib/widgets/smart_home/)

Each file here is a self-contained component for the Smart Home screen.

lib/widgets/smart_home/smart_home_header.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

class SmartHomeHeader extends StatelessWidget {
  const SmartHomeHeader({Key? key}) : super(key: key);
  // ... (code from previous answer)
}

lib/widgets/smart_home/power_usage_card.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

class PowerUsageCard extends StatelessWidget {
  const PowerUsageCard({Key? key}) : super(key: key);
  // ... (code from previous answer)
}

lib/widgets/smart_home/room_card.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

class RoomCard extends StatelessWidget {
  final String roomName;
  final String deviceCount;
  final Color color;
  final Color textColor;

  const RoomCard({
    Key? key,
    required this.roomName,
    required this.deviceCount,
    required this.color,
    required this.textColor,
  }) : super(key: key);
  // ... (code from previous answer)
}

lib/widgets/smart_home/remote_access_card.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

class RemoteAccessCard extends StatelessWidget {
  const RemoteAccessCard({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(
        horizontal: AppDimensions.spacingMedium,
        vertical: AppDimensions.spacingSmall,
      ),
      decoration: BoxDecoration(
        color: AppColors.primaryBlue,
        borderRadius: BorderRadius.circular(AppDimensions.borderRadiusMedium),
      ),
      child: Row(
        children: [
          const Icon(Icons.info_outline, color: Colors.white, size: 20),
          const SizedBox(width: AppDimensions.spacingSmall),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('Quick Remote Access',
                    style: AppStyles.bodyText.copyWith(color: Colors.white)),
                Text(
                  'Click here to connect with your phone.',
                  style: AppStyles.subtitle
                      .copyWith(color: Colors.white.withOpacity(0.8), fontSize: 10),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

Music Player Widgets (lib/widgets/music_player/)

These widgets are the building blocks for the Music Player UI.

lib/widgets/music_player/music_player_header.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';

// This widget creates the distinctive blue, curved header.
// It uses SafeArea to ensure content isn't obscured by system UI (like notches).
class MusicPlayerHeader extends StatelessWidget {
  const MusicPlayerHeader({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 260,
      decoration: const BoxDecoration(
        color: AppColors.primaryBlue,
        borderRadius: BorderRadius.only(
          bottomLeft: Radius.circular(50),
          bottomRight: Radius.circular(50),
        ),
      ),
      child: SafeArea(
        bottom: false,
        child: Padding(
          padding: const EdgeInsets.all(AppDimensions.spacingLarge),
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Icon(Icons.arrow_back, color: Colors.white),
              Container(
                width: 40,
                height: 40,
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: AppColors.lightBlue.withOpacity(0.5),
                  border: Border.all(color: Colors.white, width: 1.5),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

lib/widgets/music_player/artist_card.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

// The floating card that displays artist information.
// It uses the centralized AppStyles.cardShadow for a consistent shadow effect.
class ArtistCard extends StatelessWidget {
  const ArtistCard({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(AppDimensions.spacingMedium),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(AppDimensions.borderRadiusMedium),
        boxShadow: [AppStyles.cardShadow],
      ),
      child: Row(
        children: [
          Container(
            width: 80,
            height: 80,
            decoration: BoxDecoration(
              color: AppColors.lightBlue,
              borderRadius: BorderRadius.circular(AppDimensions.borderRadiusSmall),
            ),
          ),
          const SizedBox(width: AppDimensions.spacingMedium),
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('Antonia Berger', style: AppStyles.h2),
              Text('Hip Hop Artist', style: AppStyles.subtitle),
              Text('antonia.com', style: AppStyles.subtitle.copyWith(color: AppColors.primaryBlue)),
            ],
          )
        ],
      ),
    );
  }
}

lib/widgets/music_player/track_list_item.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/models/track_model.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

// Represents a single row in the music track list.
// It conditionally renders its UI based on the `track.isPlaying` property.
class TrackListItem extends StatelessWidget {
  final Track track;
  const TrackListItem({Key? key, required this.track}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: AppDimensions.spacingSmall),
      child: Row(
        children: [
          Container(
            width: 40,
            height: 40,
            decoration: BoxDecoration(
              color: track.isPlaying ? AppColors.primaryBlue : Colors.transparent,
              shape: BoxShape.circle,
              border: Border.all(color: track.isPlaying ? AppColors.primaryBlue : AppColors.textLight.withOpacity(0.5), width: 1.5),
            ),
            child: Icon(
              track.isPlaying ? Icons.pause : Icons.play_arrow,
              color: track.isPlaying ? Colors.white : AppColors.textDark,
              size: 20,
            ),
          ),
          const SizedBox(width: AppDimensions.spacingMedium),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(track.title, style: AppStyles.bodyText),
                if (track.isPlaying)
                  Padding(
                    padding: const EdgeInsets.only(top: 4.0),
                    child: SizedBox(
                      height: 2,
                      child: LinearProgressIndicator(
                        value: 0.4,
                        backgroundColor: AppColors.lightBlue,
                        valueColor: const AlwaysStoppedAnimation<Color>(AppColors.primaryBlue),
                      ),
                    ),
                  ),
              ],
            ),
          ),
          Text(track.duration, style: AppStyles.subtitle),
        ],
      ),
    );
  }
}

lib/widgets/music_player/track_list.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/models/track_model.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';
import 'package:figma_replication_project/widgets/music_player/track_list_item.dart';

// This widget builds the scrollable list of tracks.
// It maps the mock data from `topTracks` to `TrackListItem` widgets.
class TrackList extends StatelessWidget {
  const TrackList({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: const EdgeInsets.fromLTRB(
        AppDimensions.spacingLarge,
        AppDimensions.spacingLarge,
        AppDimensions.spacingLarge,
        0,
      ),
      children: [
        Text('Top Tracks', style: AppStyles.h2),
        const SizedBox(height: AppDimensions.spacingMedium),
        // Using the spread operator (...) to add all items from the list.
        ...topTracks.map((track) => TrackListItem(track: track)).toList(),
      ],
    );
  }
}

Apartment Booking Widgets (lib/widgets/apartment_booking/)

These widgets are the building blocks for the Apartment Booking UI.

lib/widgets/apartment_booking/booking_header.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

// The header section for the apartment booking screen.
class BookingHeader extends StatelessWidget {
  const BookingHeader({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(
        AppDimensions.spacingLarge,
        AppDimensions.spacingMedium,
        AppDimensions.spacingLarge,
        0,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Icon(Icons.arrow_back, color: AppColors.textDark),
              Container(
                width: 40,
                height: 40,
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: AppColors.lightBlue.withOpacity(0.5),
                  border: Border.all(color: AppColors.primaryBlue, width: 1.5),
                ),
              ),
            ],
          ),
          const SizedBox(height: AppDimensions.spacingMedium),
          Text('Discover & book', style: AppStyles.h1),
          Text('unique apartments', style: AppStyles.h1),
        ],
      ),
    );
  }
}

lib/widgets/apartment_booking/booking_search.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

// The search bar component with a suggestion chip and a search button.
class BookingSearch extends StatelessWidget {
  const BookingSearch({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: AppDimensions.spacingLarge),
      child: Row(
        children: [
          Expanded(
            child: Container(
              padding: const EdgeInsets.symmetric(
                horizontal: AppDimensions.spacingMedium,
                vertical: AppDimensions.spacingSmall,
              ),
              decoration: BoxDecoration(
                color: AppColors.primaryBlue,
                borderRadius: BorderRadius.circular(30),
              ),
              child: Center(
                child: Text(
                  'TRY "COPENHAGEN"',
                  style: AppStyles.buttonText.copyWith(fontSize: 12),
                ),
              ),
            ),
          ),
          const SizedBox(width: AppDimensions.spacingSmall),
          Container(
            padding: const EdgeInsets.all(AppDimensions.spacingSmall),
            decoration: const BoxDecoration(
              color: AppColors.primaryBlue,
              shape: BoxShape.circle,
            ),
            child: const Icon(Icons.search, color: Colors.white, size: 24),
          ),
        ],
      ),
    );
  }
}

lib/widgets/apartment_booking/apartment_card.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/utils/app_styles.dart';

// A single card representing an apartment in the carousel.
// It uses a Stack to position the text and the send button.
class ApartmentCard extends StatelessWidget {
  const ApartmentCard({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: AppColors.lightBlue,
        borderRadius: BorderRadius.circular(AppDimensions.borderRadiusLarge),
        boxShadow: [AppStyles.cardShadow],
      ),
      child: Stack(
        children: [
          Positioned(
            left: AppDimensions.spacingMedium,
            bottom: AppDimensions.spacingMedium,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('Tidy Minimal', style: AppStyles.h2),
                Text('Berlin, Germany', style: AppStyles.subtitle),
              ],
            ),
          ),
          Positioned(
            right: AppDimensions.spacingMedium,
            bottom: AppDimensions.spacingMedium,
            child: Container(
              padding: const EdgeInsets.all(AppDimensions.spacingSmall),
              decoration: const BoxDecoration(
                color: AppColors.primaryBlue,
                shape: BoxShape.circle,
              ),
              child: const Icon(Icons.send, color: Colors.white, size: 20, semanticLabel: 'Send'),
            ),
          ),
        ],
      ),
    );
  }
}

lib/widgets/apartment_booking/apartment_carousel.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/widgets/apartment_booking/apartment_card.dart';

// This widget manages the PageView for the apartment cards.
// It's a StatelessWidget because it receives its state (controller, currentPage)
// from the parent StatefulWidget.
class ApartmentCarousel extends StatelessWidget {
  final PageController pageController;
  final int currentPage;

  const ApartmentCarousel({
    Key? key,
    required this.pageController,
    required this.currentPage,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 320,
      child: PageView.builder(
        controller: pageController,
        itemCount: 3,
        itemBuilder: (context, index) {
          // AnimatedContainer creates the subtle scaling effect when a card is active.
          return AnimatedContainer(
            duration: const Duration(milliseconds: 300),
            curve: Curves.easeInOut,
            margin: EdgeInsets.only(
              right: AppDimensions.spacingSmall,
              top: currentPage == index ? 0 : 20,
              bottom: currentPage == index ? 20 : 0,
            ),
            child: const ApartmentCard(),
          );
        },
      ),
    );
  }
}

lib/widgets/apartment_booking/booking_bottom_nav.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';

// The custom bottom navigation bar with a notch for the FloatingActionButton.
class BookingBottomNav extends StatelessWidget {
  const BookingBottomNav({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BottomAppBar(
      shape: const CircularNotchedRectangle(),
      notchMargin: 8.0,
      color: AppColors.cardBackground,
      surfaceTintColor: AppColors.cardBackground,
      elevation: 20,
      shadowColor: Colors.black.withOpacity(0.05),
      child: const Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          Icon(Icons.home_outlined, color: AppColors.textLight, size: 28),
          Icon(Icons.search, color: AppColors.textLight, size: 28),
          SizedBox(width: 48), // The placeholder space for the FAB
          Icon(Icons.favorite_border, color: AppColors.textLight, size: 28),
          Icon(Icons.person_outline, color: AppColors.textLight, size: 28),
        ],
      ),
    );
  }
}

5. Screens (lib/screens/)

These files now act as clean, readable blueprints. They compose the smaller widgets to build the final UI.

lib/screens/smart_home_screen.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/widgets/smart_home/power_usage_card.dart';
import 'package:figma_replication_project/widgets/smart_home/remote_access_card.dart';
import 'package:figma_replication_project/widgets/smart_home/room_card.dart';
import 'package:figma_replication_project/widgets/smart_home/smart_home_header.dart';

// This screen composes various "smart_home" widgets to build the UI.
// Notice how readable this is compared to having all the code in one file.
class SmartHomeScreen extends StatelessWidget {
  const SmartHomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: AppColors.cardBackground,
      body: Padding(
        padding: const EdgeInsets.all(AppDimensions.spacingLarge),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const SmartHomeHeader(),
            const SizedBox(height: AppDimensions.spacingXLarge),
            const PowerUsageCard(),
            const SizedBox(height: AppDimensions.spacingLarge),
            const Row(
              children: [
                Expanded(
                  child: RoomCard(
                    roomName: 'Living Room',
                    deviceCount: '9 Active Devices',
                    color: AppColors.lightBlue,
                    textColor: AppColors.textDark,
                  ),
                ),
                SizedBox(width: AppDimensions.spacingMedium),
                Expanded(
                  child: RoomCard(
                    roomName: 'Bathroom',
                    deviceCount: '1 Active Device',
                    color: AppColors.primaryBlue,
                    textColor: Colors.white,
                  ),
                ),
              ],
            ),
            const Spacer(),
            const RemoteAccessCard(),
          ],
        ),
      ),
    );
  }
}

lib/screens/music_player_screen.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/widgets/music_player/artist_card.dart';
import 'package:figma_replication_project/widgets/music_player/music_player_header.dart';
import 'package:figma_replication_project/widgets/music_player/track_list.dart';

// This screen uses a Stack to create the overlapping UI effect,
// a perfect demonstration of the "Deconstruct Layouts with Stack" principle.
class MusicPlayerScreen extends StatelessWidget {
  const MusicPlayerScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: AppColors.cardBackground,
      body: Stack(
        children: [
          const Positioned.fill(top: 220, child: TrackList()),
          const MusicPlayerHeader(),
          const Positioned(
            top: 120,
            left: AppDimensions.spacingLarge,
            right: AppDimensions.spacingLarge,
            child: ArtistCard(),
          ),
        ],
      ),
    );
  }
}

lib/screens/apartment_booking_screen.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/utils/app_colors.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/widgets/apartment_booking/apartment_carousel.dart';
import 'package:figma_replication_project/widgets/apartment_booking/booking_bottom_nav.dart';
import 'package:figma_replication_project/widgets/apartment_booking/booking_header.dart';
import 'package:figma_replication_project/widgets/apartment_booking/booking_search.dart';

// This is a StatefulWidget because it needs to manage the state of the
// PageController and the current active page index for the carousel animation.
class ApartmentBookingScreen extends StatefulWidget {
  const ApartmentBookingScreen({Key? key}) : super(key: key);

  @override
  State<ApartmentBookingScreen> createState() => _ApartmentBookingScreenState();
}

class _ApartmentBookingScreenState extends State<ApartmentBookingScreen> {
  final PageController _pageController = PageController(viewportFraction: 0.85);
  int _currentPage = 0;

  @override
  void initState() {
    super.initState();
    // Listen to page changes to update the UI for the scaling effect.
    _pageController.addListener(() {
      if (_pageController.page?.round() != _currentPage) {
        setState(() {
          _currentPage = _pageController.page!.round();
        });
      }
    });
  }

  @override
  void dispose() {
    _pageController.dispose(); // Always dispose controllers to prevent memory leaks.
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: AppColors.cardBackground,
      body: SafeArea(
        bottom: false,
        child: Column(
          children: [
            const BookingHeader(),
            const SizedBox(height: AppDimensions.spacingMedium),
            const BookingSearch(),
            const SizedBox(height: AppDimensions.spacingLarge),
            // The carousel is passed the controller and current page state.
            ApartmentCarousel(
              pageController: _pageController,
              currentPage: _currentPage,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        backgroundColor: AppColors.primaryBlue,
        shape: const CircleBorder(),
        elevation: 4.0,
        child: const Icon(Icons.add, color: Colors.white, size: 32),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      bottomNavigationBar: const BookingBottomNav(),
    );
  }
}

6. Application Entry Point

Finally, the main.dart and home_dashboard_screen.dart tie everything together.

lib/screens/home_dashboard_screen.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/screens/apartment_booking_screen.dart';
import 'package:figma_replication_project/screens/music_player_screen.dart';
import 'package:figma_replication_project/screens/smart_home_screen.dart';
import 'package:figma_replication_project/utils/app_dimensions.dart';
import 'package:figma_replication_project/widgets/app_mockup_frame.dart';

// This is the main screen that displays the three mockups.
// It uses a LayoutBuilder to create a responsive layout, demonstrating
// the "Embrace Constraints and Responsiveness" principle.
class HomeDashboardScreen extends StatelessWidget {
  const HomeDashboardScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.symmetric(vertical: AppDimensions.spacingXLarge),
            child: LayoutBuilder(
              builder: (context, constraints) {
                bool isWide = constraints.maxWidth > (AppDimensions.mockupWidth * 3 + 100);

                // Show in a Row on wide screens, and a Column on narrow screens.
                return isWide
                    ? const Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          AppMockupFrame(child: SmartHomeScreen()),
                          SizedBox(width: AppDimensions.spacingXLarge),
                          AppMockupFrame(child: MusicPlayerScreen()),
                          SizedBox(width: AppDimensions.spacingXLarge),
                          AppMockupFrame(child: ApartmentBookingScreen()),
                        ],
                      )
                    : Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          const AppMockupFrame(child: SmartHomeScreen()),
                          const SizedBox(height: AppDimensions.spacingXLarge),
                          const AppMockupFrame(child: MusicPlayerScreen()),
                          const SizedBox(height: AppDimensions.spacingXLarge),
                          const AppMockupFrame(child: ApartmentBookingScreen()),
                        ],
                      );
              },
            ),
          ),
        ),
      ),
    );
  }
}

lib/main.dart

import 'package:flutter/material.dart';
import 'package:figma_replication_project/screens/home_dashboard_screen.dart';
import 'package:figma_replication_project/utils/app_colors.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Figma to Flutter Replication',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: AppColors.primaryBlue,
        scaffoldBackgroundColor: AppColors.background,
        useMaterial3: true,
      ),
      home: const HomeDashboardScreen(),
    );
  }
}

Conclusion

Replicating Figma designs in Flutter with pixel-perfect accuracy is a skill developed through deliberate practice and an unwavering commitment to detail. It requires more than just understanding Flutter widgets. It demands a deep appreciation for the nuances of design, a systematic approach to breaking down complex layouts, and a relentless pursuit of visual fidelity. By internalizing these practices, you won't just be writing code, you'll be sculpting user interfaces that truly honor the designer's vision.