Skip to main content
Back to all tutorials
Tested: Flutter 3.24.3 • Dart 3.5.3
WE-TUT-001 Verified September 2026
Schema Container Card Icons Flexbox

Build a Flutter Profile Card from a JSON Schema

Deconstruct how to compose Container, Row, Column, Text, and Icon widgets into an adaptive profile card with full standalone Dart code generation.

1. The Core Challenge & Problem

Mobile applications frequently need user profile teasers or social cards across feeds and drawer menus. Hardcoding separate layout variations for mobile and web leads to fragmented UI code. Furthermore, defining layouts dynamically via declarative backend schemas requires a disciplined, validated hierarchy to prevent layout crashes.

2. Architectural Principles & Resolution

This tutorial demonstrates how to construct a complete profile card using WidgetExamples' validated JSON schema (Version 1). The design employs a root `Container` acting as an elevated surface, an avatar badge composed of an `Icon` with circular `borderRadius`, a nested `Column` for typography, and an `ElevatedButton` for following/connecting. Because WidgetExamples enforces strict schema validation, every numeric dimension, hex colour (#2563EB), and alignment enum is pre-checked before passing into the Flutter rendering pipeline. When exported, the schema maps directly to clean, standalone Flutter Material 3 widgets without any runtime dependencies on the schema engine.

3. Complete Tested Flutter Code

main.dart (Flutter 3.x+ ready)
lib/main.dart Copy & Paste into a new Flutter project
import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
      backgroundColor: Color(0xFFF1F5F9),
      body: Center(
        child: ProfileCardExample(),
      ),
    ),
  ));
}

class ProfileCardExample extends StatelessWidget {
  const ProfileCardExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 320,
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: const [
          BoxShadow(
            color: Color(0x1A000000),
            blurRadius: 12,
            offset: Offset(0, 4),
          ),
        ],
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          // Avatar circle
          Container(
            width: 72,
            height: 72,
            decoration: BoxDecoration(
              color: const Color(0xFFEFF6FF),
              borderRadius: BorderRadius.circular(36),
            ),
            child: const Center(
              child: Icon(Icons.person, size: 40, color: Color(0xFF2563EB)),
            ),
          ),
          const SizedBox(height: 12),
          // User Name
          const Text(
            'Alex Mercer',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
              color: Color(0xFF0F172A),
            ),
          ),
          const SizedBox(height: 4),
          // Role subtitle
          const Text(
            'Principal Mobile Engineer',
            style: TextStyle(
              fontSize: 13,
              color: Color(0xFF64748B),
            ),
          ),
          const SizedBox(height: 16),
          // Action button
          SizedBox(
            width: double.infinity,
            child: ElevatedButton(
              onPressed: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('Connected with Alex Mercer!')),
                );
              },
              style: ElevatedButton.styleFrom(
                backgroundColor: const Color(0xFF2563EB),
                foregroundColor: Colors.white,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
              ),
              child: const Text('Connect'),
            ),
          ),
        ],
      ),
    );
  }
}

4. Expected Visual & Behavioral Result

A clean 320px wide profile card centered on the screen. It features a soft drop shadow, rounded corners (16px), a light blue circular avatar with a person glyph, bold headline typography, muted subtitle text, and a full-width blue action button that shows a snackbar message when tapped.

5. Common Pitfalls & Traps

Pitfall #1: Using unbounded height inside Column without mainAxisSize: MainAxisSize.min

Remedy: Columns expand vertically to fill parent constraints by default. In card widgets, always set mainAxisSize to MainAxisSize.min unless wrapped in a fixed-height container.

Pitfall #2: Applying double hex opacity strings without ARGB ordering (e.g. #2563EB80 vs Color(0x802563EB))

Remedy: Flutter Color expects 32-bit integer formatted as 0xAARRGGBB. Always place the alpha channel in the first byte position.

Pitfall #3: Deeply nesting multiple Center or Padding widgets when Container can specify both

Remedy: Utilize Container(padding: ..., alignment: ...) to consolidate layout hierarchy and reduce widget tree depth.

Official Flutter References & Standards