Build a Business Card App with Flutter
Build a styled personal business card app that runs in your browser.
Introduction
30 Second Summary
Think about the last time you handed someone a business card or shared your contact details. Now imagine doing that with a custom app you built yourself, running right in your browser.
In this project, you will build a personal digital business card app using Flutter. You will compose styled layouts, display your name and contact info, and see changes appear instantly as you code.
What You'll Build
A personal business card app that displays your name, job title, and contact information in a polished Material Design layout, running in Google Chrome.
By the end of this project, you'll have:
- A Flutter project scaffolded and running in your Chrome browser.
- Hands-on experience with Flutter's widget composition model, building layouts with Rows, Columns, and Containers.
- Experience using hot reload to see your UI update instantly as you change code.
- Secret Mission: Add a dark mode toggle that switches the card's color scheme using a StatefulWidget.
Are there any prerequisites?
None. This project includes full setup instructions for every tool you need, including Flutter, VS Code, and Git. No prior programming experience with Dart or Flutter is required.
Install Flutter and Set Up VS Code
Before you can build anything with Flutter, you need a few tools installed on your machine.
Since this project targets the web, the setup is lightweight. You only need Git, Visual Studio Code, and Google Chrome. No Android Studio or mobile emulators required.
In this step, get ready to:
- Install Git for Windows, Visual Studio Code, and the Flutter extension for VS Code.
- Download and install the Flutter SDK using the VS Code Command Palette.
- Run flutter doctor -v in the terminal to verify everything is working.
Install Git for Windows, Visual Studio Code, and the Flutter extension
Flutter's SDK download process uses Git behind the scenes. You also need VS Code as your code editor and Google Chrome as your app's target browser.
Check if Git is installed
- Press the Windows key (Windows) or Cmd+Space (macOS) to open your search bar.
- Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
- Check if Git is already installed by running this command:
git --version
✔️ I see a version number
Git is ready to go. You can close this terminal window for now.
ⓧ Command not found
- Download the Git installer from git-scm.com/download/win.
- Run the downloaded installer.
- Accept the default options on each screen and click Next until the installation completes.
- Close and reopen your terminal, then run git --version again to confirm it works.
macOS users
On macOS, Git comes pre-installed with the Xcode command-line tools. If git --version prompts you to install them, click Install and wait for the download to finish.
Check if Google Chrome is installed
Your Flutter app will run inside Google Chrome. Most computers already have it installed.
✔️ I have Chrome installed
You are all set. Move on to the next section below.
ⓧ I don't have Chrome
- Download Google Chrome from google.com/chrome.
- Run the installer and follow the prompts to complete the installation.
Install Visual Studio Code
✔️ I already have VS Code
Great. Open VS Code and skip ahead to the Flutter extension install below.
ⓧ I need to install VS Code
- Download Visual Studio Code from code.visualstudio.com.
- Run the installer and accept the defaults.
- Once installed, open VS Code by pressing the Windows key (Windows) or Cmd+Space (macOS), typing Visual Studio Code, and pressing Enter.
Install the Flutter extension
- In VS Code, open the Extensions panel by pressing Cmd+Shift+X (macOS) or Ctrl+Shift+X (Windows).
- Type Flutter in the search bar at the top of the panel.
- Click Install on the extension published by Dart Code (it has millions of installs).
What about the Dart extension?
Installing the Flutter extension automatically installs the Dart extension too. You do not need to install it separately.
Use the VS Code Command Palette to download and install the Flutter SDK
The Flutter extension provides a built-in way to download the Flutter SDK without leaving VS Code. You will trigger the download by starting to create a new project.
- Open the Command Palette by pressing Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows).
- Type flutter in the search field.
- Select Flutter: New Project from the dropdown.
- VS Code will detect that the Flutter SDK is not installed yet. Click Download SDK.
- Choose a folder on your computer where you want to store the Flutter SDK (your home folder or Documents works well).
- Click Clone Flutter.
The download takes a few minutes. You will see a notification in VS Code that says the Flutter SDK is being downloaded.
- When the download finishes, click Add SDK to PATH.
- If VS Code shows a Google Analytics notice, click OK.
- Close all open terminal windows inside VS Code.
- Restart VS Code completely (close it and reopen it).
Why restart VS Code?
Adding the SDK to your PATH means your system now knows where to find the flutter command. Restarting VS Code ensures any new terminal you open picks up this change.
Download seems stuck?
If the download notification has not progressed for several minutes, click Cancel on the notification and start the process again from the Command Palette.
Make sure you have a stable internet connection and that Git is installed (the SDK download uses Git to clone the repository).
help me troubleshoot my Flutter SDK download in VS Code
Run flutter doctor -v to verify your installation
Flutter includes a built-in command that checks whether all required tools are properly installed. This confirms your setup is complete.
- Open a new terminal inside VS Code by pressing Ctrl+` (backtick key, located above Tab on most keyboards).
- Verify your Flutter installation by running this command:
flutter doctor -v
What does this command do?
The flutter doctor command validates that all components of a complete Flutter development environment are installed. The -v flag gives you verbose output so you can see exactly what passed and what needs attention.
You should see output listing several categories with checkmarks. Look for green checkmarks next to Flutter and Chrome.
✔️ I see green checkmarks for Flutter and Chrome
Your environment is fully set up and ready to build Flutter apps.
ⓧ I see errors or the command is not found
- If you see "command not found", make sure you restarted VS Code after adding the SDK to PATH.
- If Chrome shows an issue, confirm you have Google Chrome installed (not Chromium or another browser).
- Warnings about Android toolchain or Xcode are expected and safe to ignore. This project only targets the web.
help me fix my flutter doctor errors
Ignore Android and iOS warnings
You will likely see warnings about Android Studio and Xcode not being installed. That is perfectly fine. This project runs entirely in Chrome, so you only need the Flutter SDK and Chrome to show green checkmarks.
Your development environment is fully set up. Next up, you will create your first Flutter project and see it running live in Chrome.
Create Your Flutter Project
With Flutter installed and ready, it's time to create the project you'll be building for the rest of this guide.
Flutter includes a scaffolding command that generates an entire starter project for you. In this step, you'll use it to create a new project, explore the files it generates, and run the default app in your browser to prove everything works.
In this step, get ready to:
- Create a new Flutter project on your Desktop.
- Explore the generated file structure in VS Code.
- Run the default app in Chrome and confirm it loads.
Create a new Flutter project
Flutter's flutter create command generates a complete starter project with all the files and folders you need. You'll run it from your Desktop so the project is easy to find later.
- Open the integrated terminal in VS Code by pressing Ctrl+` (Windows) or Cmd+` (macOS).
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your Flutter project by running this command:
flutter create business_card
What does this command do?
flutter create business_card generates a complete Flutter project inside a new folder called business_card. The folder includes a lib/ directory with your app code, a pubspec.yaml for dependencies, and platform-specific folders for web, iOS, and Android.
Flutter project names must use lowercase letters and underscores only. That's why the project is called business_card instead of "BusinessCard" or "business-card".
- You'll see a list of files being created, followed by an "All done!" message.
- Confirm the project folder exists by running:
ls
You should see business_card listed in the output.
- Move into your new project folder by running:
cd business_card
Seeing 'command not found'?
If flutter create fails, the Flutter SDK may not be on your system PATH. Close and reopen VS Code, then try again. Restarting VS Code reloads the PATH variables that were set during installation.
help me fix a flutter command not found error
Open the project in VS Code and explore the file structure
Now that the project exists, you'll open it in VS Code and get familiar with the key files Flutter generated.
- In VS Code, click File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop and select the business_card folder, then click Select Folder.
The Explorer sidebar on the left now shows the project's file tree. Take a look at these three key files and folders:
- lib/main.dart is your app's entry point. All the Dart code that defines your UI lives in the lib/ folder.
- pubspec.yaml is the project's configuration file. It lists your app's name, version, and any packages (dependencies) you add later.
- web/ contains the HTML shell that hosts your Flutter app when it runs in a browser.
- Click on lib/main.dart in the Explorer sidebar to open it in the editor.
You should see a file filled with Dart code. This is Flutter's default counter app. It demonstrates a working widget tree with buttons and text that you'll replace in the next step.
What is a widget?
In Flutter, everything you see on screen is a widget. Text, buttons, layouts, padding, even the app itself are all widgets nested inside each other.
This "everything is a widget" model is how Flutter builds complex UIs from small, reusable pieces. You'll compose widgets together like building blocks throughout this project.
Run the default app in Chrome
The generated project already has a working app inside it. You'll run it in Google Chrome to confirm your full setup is working end to end.
- Open the integrated terminal again by pressing Ctrl+` (Windows) or Cmd+` (macOS).
- Launch the app in Chrome by running this command:
flutter run -d chrome
What does this command do?
flutter run -d chrome compiles your Dart code and launches the app in a Chrome browser window. The -d chrome flag tells Flutter which device to target.
The first run takes longer because Flutter has to compile everything from scratch. Subsequent runs will be much faster.
After a short wait, a Chrome window opens with the Flutter demo app. You should see a purple app bar at the top with the text "Flutter Demo Home Page" and a floating "+" button in the bottom right corner.
- Click the "+" button a few times. The counter on screen increments with each click.
Why are we running in Chrome instead of a phone?
Running in Chrome avoids the need for Android Studio, Android SDKs, emulators, and the significantly more complex mobile toolchain setup. The Flutter code is identical regardless of target platform.
For web development, only Git and Google Chrome are required. You can always add mobile targets later without changing a single line of your app code.
Chrome didn't open?
Make sure Google Chrome is installed and is the browser recognized by Flutter. Run flutter doctor -v and look for "Chrome" under the "Connected devices" section.
If you see a compilation error in the terminal, make sure your terminal is inside the business_card folder. Run cd ~/Desktop/business_card and try again.
help me fix flutter run -d chrome not working
Your Flutter project is up and running. Next up, you'll replace this default counter app with the start of your personal business card layout.
Build the Card Header Section
Your default Flutter app is running in Chrome. That counter app served its purpose, but now it is time to replace it with your own creation.
In this step, you will build the header section of your business card. This means setting up a clean app structure and creating the visual elements (avatar, name, job title) that make up the top of the card.
In this step, get ready to:
- Replace the default app code with a clean MaterialApp and Scaffold.
- Create a header section with a CircleAvatar, your name, and your job title.
- Use a Column widget to stack elements vertically with proper spacing.
Replace the default code with a clean MaterialApp
The default counter app has a lot of code you do not need. You will replace the entire file with a much simpler app structure built around MaterialApp, which is Flutter's starting point for any app using Material Design.
- In VS Code, open lib/main.dart from the Explorer sidebar on the left.
- Select all the existing code by pressing Cmd+A (macOS) or Ctrl+A (Windows) and delete it.
- Paste the following code into the now-empty file:
import 'package:flutter/material.dart';
void main() {
runApp(const BusinessCardApp());
}
class BusinessCardApp extends StatelessWidget {
const BusinessCardApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Business Card',
theme: ThemeData(
// Use teal as the primary color seed
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: const BusinessCardPage(),
);
}
}
What does this code do?
This creates the shell of your app. Every Flutter app needs a root widget that kicks things off.
- runApp() tells Flutter which widget to display first.
- BusinessCardApp is a StatelessWidget that returns a MaterialApp with a teal color theme.
- home: const BusinessCardPage() points to the page widget you will build next.
What is a StatelessWidget?
A StatelessWidget is a widget that never changes after it is built. It has no internal state to update. Since the app shell just defines a theme and a home page, it does not need to change, making StatelessWidget the right choice.
You will see a red underline on BusinessCardPage in your editor. That is expected. You have not created that class yet.
Build the header with a Column layout
Now you will create the BusinessCardPage widget that displays the card header. A Column widget stacks its children vertically, which is perfect for placing an avatar above a name above a job title.
- In lib/main.dart, place your cursor at the very end of the file (after the closing } of the BusinessCardApp class).
- Add the following code below it:
class BusinessCardPage extends StatelessWidget {
const BusinessCardPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal[100],
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Profile avatar circle
const CircleAvatar(
radius: 50,
backgroundColor: Colors.white,
child: Icon(Icons.person, size: 50, color: Colors.teal),
),
const SizedBox(height: 16),
// Name text
const Text(
'Your Name',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: 'Pacifico',
),
),
const SizedBox(height: 8),
// Job title text
Text(
'FLUTTER DEVELOPER',
style: TextStyle(
fontSize: 16,
color: Colors.teal[900],
letterSpacing: 2.5,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
);
}
}
What does this code do?
This builds the visual layout of your card header from the outside in.
- Scaffold provides the basic page structure with a light teal background color.
- SafeArea keeps content from overlapping device notches or status bars.
- Center positions everything in the middle of the screen horizontally.
- Column stacks its children vertically. mainAxisAlignment: MainAxisAlignment.center centers them vertically too.
- CircleAvatar creates a round profile icon as a placeholder for a photo.
- SizedBox adds vertical space between the widgets so they do not touch.
Why is everything a widget?
In Flutter, every visual element is a widget. Text is a widget. A circle is a widget. Even the spacing between elements is a widget (SizedBox). You build complex UIs by composing small, simple widgets together like building blocks.
- Save lib/main.dart.
- Look at your Chrome window. Hot reload automatically updates the app when you save. You should see a teal background with a white circle avatar, your name in large white text, and "FLUTTER DEVELOPER" below it.
Hot reload not working?
If the app did not update automatically, switch to the terminal where flutter run is running and press r to trigger a manual hot reload. If you see errors, make sure you saved the file first.
Seeing a blank screen or error?
- Check that the BusinessCardPage class is placed AFTER the closing } of the BusinessCardApp class, not inside it.
- Make sure you deleted ALL the old code before pasting. Leftover code from the counter app causes conflicts.
- Confirm the class name matches exactly: BusinessCardPage in both the home: line and the class declaration.
Still stuck? Help me debug my Flutter business card app. I replaced main.dart but I'm seeing a blank screen or error in Chrome.
✔️ Awesome, I've got everything!
Great. Double check you have saved your file, then move on to the next step.
ⓧ I'd like to double check the full code
Here is the complete lib/main.dart file at this point. Make sure yours matches exactly.
import 'package:flutter/material.dart';
void main() {
runApp(const BusinessCardApp());
}
class BusinessCardApp extends StatelessWidget {
const BusinessCardApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Business Card',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: const BusinessCardPage(),
);
}
}
class BusinessCardPage extends StatelessWidget {
const BusinessCardPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal[100],
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircleAvatar(
radius: 50,
backgroundColor: Colors.white,
child: Icon(Icons.person, size: 50, color: Colors.teal),
),
const SizedBox(height: 16),
const Text(
'Your Name',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: 'Pacifico',
),
),
const SizedBox(height: 8),
Text(
'FLUTTER DEVELOPER',
style: TextStyle(
fontSize: 16,
color: Colors.teal[900],
letterSpacing: 2.5,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
);
}
}
Your card header looks great. Next up, you will add contact information cards below the header to make the business card actually useful.
Add Contact Information Cards
Your business card header is looking great. You have a profile avatar, your name, and your job title stacked neatly in a Column.
A real business card also needs contact details. In this step, you will build a reusable ContactCard widget that pairs an icon with a line of text, then use it three times to display your phone number, email, and website.
In this step, get ready to:
- Create a reusable ContactCard widget with an icon and text inside a styled Container.
- Add three contact cards to your business card page with proper spacing.
Create the ContactCard widget
Instead of copying and pasting the same Row-with-icon layout three times, you will create one custom widget that accepts an icon and text as parameters. This is widget composition in action.
- In lib/main.dart, scroll to the very bottom of the file (below the closing } of BusinessCardPage).
- Add the following ContactCard class at the bottom of the file:
class ContactCard extends StatelessWidget {
final IconData icon;
final String text;
const ContactCard({super.key, required this.icon, required this.text});
@override
Widget build(BuildContext context) {
return Container(
width: 320,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(icon, color: Colors.teal, size: 24),
const SizedBox(width: 16),
Text(
text,
style: TextStyle(
fontSize: 16,
color: Colors.teal[900],
),
),
],
),
);
}
}
What does this code do?
This creates a custom widget called ContactCard that takes two inputs: an icon and a text string.
- Container gives the card a fixed width of 320, white background, and rounded corners.
- Row lays out the icon and text side by side horizontally.
- SizedBox(width: 16) adds a gap between the icon and the text so they don't touch.
- Save main.dart.
You won't see a change yet. The next chunk uses this widget in your page.
Add contact cards to your page
Now that you have a reusable ContactCard widget, you can use it multiple times with different icons and text. Each usage is just a constructor call with your parameters.
- In the BusinessCardPage class, find the Column's children list.
- Find the closing ), of the 'FLUTTER DEVELOPER' Text widget.
- Add the following code directly below it (still inside the children list):
const SizedBox(height: 32),
// Phone contact card
const ContactCard(
icon: Icons.phone,
text: '+1 (555) 123-4567',
),
const SizedBox(height: 12),
// Email contact card
const ContactCard(
icon: Icons.email,
text: 'yourname@email.com',
),
const SizedBox(height: 12),
// Website contact card
const ContactCard(
icon: Icons.language,
text: 'www.yourwebsite.com',
),
What does this code do?
- SizedBox(height: 32) creates a larger gap between the header section and the contact cards.
- Each ContactCard reuses the widget you just created, passing in a different icon and text string.
- SizedBox(height: 12) adds consistent spacing between each card.
Why reuse a widget instead of copying code?
If you wanted to change the styling of all contact cards (say, add a shadow), you would only need to edit the ContactCard class once. Without a reusable widget, you would need to find and update three separate copies of the same code.
- Save main.dart. Hot reload triggers automatically.
- Check your Chrome browser. You should see three white rounded cards below your name and title, each showing a teal icon on the left and contact text on the right.
Don't see the contact cards?
- Make sure the ContactCard class is outside the closing } of BusinessCardPage, not inside it.
- Check for a red error banner in Chrome. This usually means a missing comma between items in the children list.
- Verify that your new code sits inside the children: [...] array, after the 'FLUTTER DEVELOPER' Text widget.
Help me debug my ContactCard widget not appearing in Chrome
✔️ Awesome, I've got everything!
Great. Double check you have saved your file before moving on.
ⓧ I'd like to double check the full code
Here is the complete lib/main.dart file at this point. Compare yours against it:
import 'package:flutter/material.dart';
void main() {
runApp(const BusinessCardApp());
}
class BusinessCardApp extends StatelessWidget {
const BusinessCardApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Business Card',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: const BusinessCardPage(),
);
}
}
class BusinessCardPage extends StatelessWidget {
const BusinessCardPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal[100],
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircleAvatar(
radius: 50,
backgroundColor: Colors.white,
child: Icon(Icons.person, size: 50, color: Colors.teal),
),
const SizedBox(height: 16),
const Text(
'Your Name',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: 'Pacifico',
),
),
const SizedBox(height: 8),
Text(
'FLUTTER DEVELOPER',
style: TextStyle(
fontSize: 16,
color: Colors.teal[900],
letterSpacing: 2.5,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 32),
const ContactCard(
icon: Icons.phone,
text: '+1 (555) 123-4567',
),
const SizedBox(height: 12),
const ContactCard(
icon: Icons.email,
text: 'yourname@email.com',
),
const SizedBox(height: 12),
const ContactCard(
icon: Icons.language,
text: 'www.yourwebsite.com',
),
],
),
),
),
);
}
}
class ContactCard extends StatelessWidget {
final IconData icon;
final String text;
const ContactCard({super.key, required this.icon, required this.text});
@override
Widget build(BuildContext context) {
return Container(
width: 320,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(icon, color: Colors.teal, size: 24),
const SizedBox(width: 16),
Text(
text,
style: TextStyle(
fontSize: 16,
color: Colors.teal[900],
),
),
],
),
);
}
}
Your business card now has real contact information. Next up, you will style and polish the overall layout with a custom theme and see hot reload in action as you tweak colors and spacing in real time.
Style and Polish the Layout
Your business card has all the structural pieces in place. Now it's time to understand how Flutter's theming and layout systems make everything look polished and professional.
In this step, you'll explore how ThemeData controls your app's color palette. You'll also experience hot reload firsthand by making a live change and watching it appear instantly in Chrome.
In this step, get ready to:
- Understand how ThemeData and ColorScheme control your app's colors.
- Review how layout widgets create proper spacing and alignment.
- Use hot reload to see changes appear instantly in Chrome.
Explore your custom color theme
Flutter uses a ThemeData object to define your app's visual identity in one central place. Every widget in your app can read from this theme to stay consistent.
- In VS Code, open lib/main.dart.
- Find the BusinessCardApp class and look at the theme property inside MaterialApp:
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
What does this code do?
ColorScheme.fromSeed takes a single seed color and generates a full palette of harmonious colors for your app. Flutter uses this palette across all Material widgets automatically.
useMaterial3: true enables Material Design 3, Google's latest design system. This gives your widgets modern shapes, spacing, and color mappings out of the box.
Review the padding, margins, and alignment
Your layout uses several widgets working together to center everything on screen. Each one handles a specific part of the positioning puzzle.
- Scroll down to the BusinessCardPage class and look at the widget tree inside the Scaffold:
return Scaffold(
backgroundColor: Colors.teal[100],
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
How do these layout widgets work together?
- SafeArea keeps content away from device notches and system bars.
- Center positions its child in the middle of the available space horizontally.
- Column with mainAxisAlignment: MainAxisAlignment.center vertically centers all the children.
- SizedBox widgets between children create consistent spacing without needing margins.
- Now look at the ContactCard class at the bottom of the file to see how each card is styled:
return Container(
width: 320,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
What makes ContactCard look polished?
- width: 320 gives every card the same width so they align neatly.
- EdgeInsets.symmetric adds inner padding so the text doesn't touch the card edges.
- BorderRadius.circular(8) rounds the corners for a modern card look.
Experience hot reload in action
Hot reload is one of Flutter's most powerful features. It injects updated code into your running app without restarting it, so you see changes in under a second.
- In lib/main.dart, find this line inside the BusinessCardApp class:
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
- Change Colors.teal to Colors.deepPurple, so the line looks like this:
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
- Save the file by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- If the app doesn't update automatically, switch to the terminal where flutter run is running and press r to trigger hot reload manually.
Look at your Chrome browser. The theme accent colors throughout the app update instantly to purple tones. No restart needed.
Why is hot reload so fast?
Hot reload injects your updated source code into the running Dart VM. Flutter then rebuilds the widget tree with the new values, preserving the app's current state. This means you can tweak colors, fonts, and layouts without waiting for a full app restart.
- Now change Colors.deepPurple back to Colors.teal so the line reads:
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
- Save the file again.
- Confirm in Chrome that your app is back to the teal color scheme.
Use hot reload as your design tool
Whenever you want to experiment with colors, font sizes, or spacing, just change the value, save, and check Chrome. You get near-instant visual feedback without losing your place in the app.
Not seeing changes in Chrome?
- Make sure the terminal where you ran flutter run -d chrome is still active. If you closed it, rerun the command.
- Check that you saved the file. Unsaved changes won't trigger hot reload.
- Try pressing r in the terminal to manually trigger hot reload.
Why isn't hot reload updating my Flutter app in Chrome?
✔️ Awesome, I've got everything!
Great. Double check you've saved lib/main.dart with the original teal color scheme restored.
ⓧ I'd like to double check the full code
Here's the complete lib/main.dart file. Make sure yours matches exactly:
import 'package:flutter/material.dart';
void main() {
runApp(const BusinessCardApp());
}
class BusinessCardApp extends StatelessWidget {
const BusinessCardApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Business Card',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
useMaterial3: true,
),
home: const BusinessCardPage(),
);
}
}
class BusinessCardPage extends StatelessWidget {
const BusinessCardPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal[100],
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircleAvatar(
radius: 50,
backgroundColor: Colors.white,
child: Icon(Icons.person, size: 50, color: Colors.teal),
),
const SizedBox(height: 16),
const Text(
'Your Name',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: 'Pacifico',
),
),
const SizedBox(height: 8),
Text(
'FLUTTER DEVELOPER',
style: TextStyle(
fontSize: 16,
color: Colors.teal[900],
letterSpacing: 2.5,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 32),
const ContactCard(
icon: Icons.phone,
text: '+1 (555) 123-4567',
),
const SizedBox(height: 12),
const ContactCard(
icon: Icons.email,
text: 'yourname@email.com',
),
const SizedBox(height: 12),
const ContactCard(
icon: Icons.language,
text: 'www.yourwebsite.com',
),
],
),
),
),
);
}
}
class ContactCard extends StatelessWidget {
final IconData icon;
final String text;
const ContactCard({super.key, required this.icon, required this.text});
@override
Widget build(BuildContext context) {
return Container(
width: 320,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(icon, color: Colors.teal, size: 24),
const SizedBox(width: 16),
Text(
text,
style: TextStyle(
fontSize: 16,
color: Colors.teal[900],
),
),
],
),
);
}
}
Your polished business card app is complete. You now know how Flutter's theming system, layout widgets, and hot reload work together to create a fast development experience. Next up, there's a Secret Mission waiting for you.
Secret mission
Add a Dark Mode Toggle
Your business card looks great, but what if users could switch between a light and dark color scheme? Build a toggle button that dynamically swaps the entire card's theme using StatefulWidget and setState.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely on your local machine, so there are no ongoing costs or cloud services to worry about. Decide whether to keep your tools installed, pause by stopping any running processes, or delete everything entirely.
Resources you used:
- The business_card project folder on your Desktop.
- Flutter SDK (installed via VS Code).
- Flutter and Dart extensions for VS Code.
- Git for Windows.
- Visual Studio Code.
Keep everything running
No action needed. Choose this if you plan to keep building Flutter apps or want to revisit this project later. Everything stays installed and ready for your next session.
- Your Flutter SDK, VS Code, Git, and extensions remain installed.
- Your business_card project folder stays on your Desktop.
- You can reopen the project anytime by launching VS Code and opening that folder.
Pause - I'll come back to this later
Stop any running Flutter dev server to free up system resources. Your files and tools stay installed for when you return.
- If flutter run is still active in your terminal, press q to quit the dev server.
- Close the Chrome tab that was running your app.
- Everything else stays in place for your next session.
Delete - I don't want to use this again
Remove all project files and tools from your machine. Follow each step below to clean up completely.
Delete the project folder
- Delete the business_card folder from your Desktop by running this command in PowerShell:
Remove-Item -Recurse -Force -Path (Join-Path $env:USERPROFILE "Desktop\business_card")
Uninstall the Flutter SDK
- Delete the Flutter SDK directory. This is the folder you chose when you installed the SDK via VS Code. For example, if you installed it in a develop\flutter folder inside your user directory, run:
Remove-Item -Recurse -Force -Path (Join-Path $env:USERPROFILE "develop\flutter")
- Optionally, remove Flutter and Dart configuration files:
Remove-Item -Recurse -Force -Path (Join-Path $env:APPDATA ".flutter-devtools")
Remove-Item -Recurse -Force -Path (Join-Path $env:LOCALAPPDATA "Pub\Cache")
Uninstall the Flutter and Dart VS Code extensions
- Open VS Code.
- Click the **Extensions** icon in the left sidebar (or press Ctrl+Shift+X).
- Find the Flutter extension in your installed list.
- Click the gear icon next to it and select Uninstall.
- Repeat for the Dart extension.
Uninstall Git for Windows
- Open Windows Settings.
- Select Apps, then Installed apps.
- Search for Git, click the three-dot menu next to it, and select Uninstall.
Uninstall Visual Studio Code
- In the same Installed apps list, search for Visual Studio Code.
- Click the three-dot menu next to it and select Uninstall.
That's a Wrap!
That's a Wrap!
Nice work! You just built a fully styled personal business card app with Flutter, running right in your browser. You went from zero Flutter experience to composing real widget layouts with custom colors, icons, and spacing.
You've learned how to:
- Build a complete Flutter app from scratch and run it in Chrome using flutter run -d chrome.
- Compose layouts with Column, Row, Container, CircleAvatar, and Icon widgets to create professional-looking UI.
- Use hot reload to see changes appear instantly in the browser without restarting your app.
- Added a dark mode toggle using StatefulWidget and setState to dynamically switch your app's color scheme.
Ready to quiz yourself?