A production-ready Profile Management dashboard with full CRUD operations, multi-step creation flows, smart listing with search, filtering, and pagination, plus theme support — built with advanced React + TypeScript patterns.
This profile manager represents my deep dive into advanced React patterns, scalable architecture, and performance optimization.
While building it, I focused on creating reusable components, organizing logic through custom hooks, and applying React advanced patterns commonly used in production environments.
Special attention was given to performance, ensuring smooth rendering, efficient state updates, and fast navigation across the entire app.
In a nutshell, it's a complete profile management dashboard that:
- Handles full CRUD operations for user profiles
- Guides users through multi-step profile creation
- Offers smart listing with search, filtering, and pagination
- Supports theme switching between dark/light modes
- Works seamlessly across all device sizes
- Advanced React Patterns – Built production systems using 4 core patterns: Compound Components, Render Props, State Reducer, and Controlled/Uncontrolled components.
- Scalable Architecture – Feature-based modular structure with +25 reusable UI components (Button, Card, Modal, Tabs, SmartList, FormWizard, Toggle, Input, Select, Grid and more).
- Custom Hooks Architecture – Built 4+ reusable hooks for debouncing, filtering, pagination, search, theme management, and state management.
- Performance Optimization – 200.6 KB gzip bundle via strategic code splitting (11 chunks) and lazy loading 375+ modules, ensuring optimal loading performance.
- Type-Safe Development – Full TypeScript integration across 45+ components with generic components (like
SmartList<T>and others) and strict typing, catching errors at compile time.
- Core Development: React 19+, TypeScript, Vite
- Styling & UI: Tailwind CSS, Hero Icons
- Routing & State: React Router v7+, Context API + useReducer
- Advanced Patterns: Compound Components, Render Props, State Reducer, Controlled/Uncontrolled components
- Performance: Code Splitting, Lazy Loading, Memoization
While building the Profile Manager, I focused on maintainability, reusability, and performance.
I aimed to build a system that's:
- Reusable through a comprehensive component library
- Maintainable with clear separation between UI, state, and business logic
- Predictable global state with reducers
- Performant with optimized navigation and rendering
- Practical applying advanced React patterns to real-world scenarios
To achieve my goals, I adopted:
I applied 4 core React patterns where each made sense:
- Compound Components (Tabs, FormWizard) for intuitive APIs
- Render Props (Toggle) for flexible state sharing
- State Reducer for customizable component behavior
- Controlled/Uncontrolled components (Modal) for flexibility
TypeScript was used from day one. Every component, hook, and utility is fully typed, catching errors at compile time rather than runtime.
Complex operations like searching, filtering, and pagination live inside small, testable custom hooks so UI components stay clean, thin and focused.
Every architectural decision considers runtime cost:
- memoized context values and selectors to avoid tree-wide re-renders
React.memo,useMemo,useCallbackwhere appropriate- route- and component-level code splitting + prefetching for fast navigation
A feature-based folder layout that ensures:
- Clear separation of concerns between UI, business logic, and side effects
- A shared UI library that enforces consistency and reusability
- Scalable structure that grows gracefully with new features
A complete user management system that covers every essential CRUD operation in real-world applications:
Profile Creation:
- Quick Add: Single-step form for fast creation
- Form Wizard: Guided multi-step process with simple validation
Profile Operations:
- Browse: Grid/List of profile cards with expandable sections
- View: Dedicated profile page with full details and tabs
- Edit: In-place editing (Tab-based editing) with real-time validation
- Delete: Safe deletion with confirmation modal
State Management:
- Global state via Context API +
useReducer - Predictable state updates
- Clean separation of concerns
Usage:
Some Snippets code:
// Quick Add Form
<ProfileForm onSuccess={handleSuccess} />
// Browse & View Profiles as cards
<ProfileCard key={profile.id} profile={profile} />
//Profiles' state management
const { state, dispatch } = useProfileContext();
// Add profile
dispatch({
type: "ADD_PROFILE",
payload: { profile: newProfile } // newProfile: Profile
});
// Update profile
dispatch({
type: "UPDATE_PROFILE",
payload: { id: profileId, profile: updatedData }
});A flexible, reusable wizard system built with compound components:
Architecture:
- Compound Components Pattern for intuitive API
- Context API + Reducer for state management
- TypeScript Generics for type safety
Features:
- Reusable across different item types (Profiles, Products, …)
- Dynamic step navigation (next/prev/callback-based transitions)
- Step-level validation callbacks
- Final submission with error handling
Usage:
Used to create a profile across multiple steps: Personal Info → Contact Info → Interests → Review → Submit
//Flow: Personal Info → Contact Info → Interests → Review → Submit
<FormWizard<ProfileWizardState, ProfileWizardAction>
context={ProfileWizardContext}
reducer={profileWizardReducer}
initialState={initialState}
totalSteps={4}
>
<FormWizard.Step>
<StepPersonalInfo stepIndex={0} />
</FormWizard.Step>
<FormWizard.Step>
<StepContactInfo stepIndex={1} />
</FormWizard.Step>
<FormWizard.Step>
<StepInterests stepIndex={2} />
</FormWizard.Step>
<FormWizard.Step>
<StepReview stepIndex={3} />
</FormWizard.Step>
</FormWizard>A generic, type-safe list component for handling complex data collections.
Core Features:
- Generic Type Support:
SmartList<T>works with any data type - Multiple Layouts: Grid and list view modes via
GenericListbase - Advanced Search: Debounced search across multiple fields
- Dynamic Filtering: Select and checkbox filters
- Client-side Pagination: Configurable page sizes
Technical Implementation:
useSearch<T>hookuseDebouncedValue<T>for debouncing search queryuseFilter<T>hook for multi-criteria filteringusePagination<T>hook for navigation- Internal components:
<SmartListSearch />,<SmartListFilters />, and<SmartListPagination />compose the finalSmartList<T> - Config-driven search and filter definitions
- State reducer pattern for custom behavior
- Custom state management:
useSmartListReducerhook with default state reducer &StateReducerOverridefor advanced behavior customization
Usage Example:
Used in Profiles List page to view all profiles with search, filter, pagination with results count.
<SmartList<Profile>
items={profiles}
itemKey={(profile: Profile) => profile.id}
renderItem={(profile: Profile) => (
<ProfileCard key={profile.id} profile={profile} />
)}
pagination={{ pageSize: 9 }}
search={searchConfig}
filter={filterConfig}
/>A flexible tab system using the Compound Components pattern:
Architecture & Key Features:
- Compound Components Pattern for intuitive API
- Context-driven with
useStatefor internal state management - TypeScript for type safety
- URL synchronization for deep linking (Optional tab syncing with URL)
- Default tab support
Usage Example:
Applied in Profile View Page to organize operations: View - Edit - Delete in one place
//The main usage of the tabs system
<Tabs defaultTab="details">
<Tabs.List>
<Tabs.Tab tabName="details">Details</Tabs.Tab>
<Tabs.Tab tabName="edit">Edit</Tabs.Tab>
</Tabs.List>
<Tabs.Container>
<Tabs.Panel tabName="details">
<ProfileDetails profile={profile} />
</Tabs.Panel>
{/* ... */}
</Tabs.Container>
</Tabs>A flexible state management component using Render Props + State Reducer patterns.
Key Features:
- useReducer hook for local state management
- Default reducer + custom override support
- TypeScript for type safety
- Toggle, reset, and set state actions
Usage Examples:
- Toggling the Add Profile Section (ProfileListPage)
<Toggle>
{({ on, toggle }) => (
<section>
<Button onClick={toggle} variant={on ? "outline" : "primary"}>
{on ? "Cancel" : "Quick Add Profile"}
</Button>
{on && <ProfileForm onSuccess={toggle} />}
</section>
)}
</Toggle>- Toggle Additional Content (ProfileCard)
<Toggle>
{({ on, toggle }) => (
<div>
{on && <div>Additional details...</div>}
<Button onClick={toggle} title={on ? "Show less" : "Show more"}>
{on ? <ChevronUpIcon /> : <ChevronDownIcon />}
</Button>
</div>
)}
</Toggle>const customReducer: ToggleStateReducer = (state, action) => {
//custom reducer logic
};
<Toggle reducer={customReducer}>
{({ on, toggle }) => (
// Custom toggle behavior
)}
</Toggle>A comprehensive design system of reusable components used throughout the application:
GenericList- Flexible list/grid layouts with empty state handlingGrid- Responsive grid system (1-4 columns) with gap and max-width controlModal- Controlled & uncontrolled modal dialogsLoadingIndicator- Loading states with multiple sizes and layoutsInput&Select- Fully accessible form controls with labels, helper text, and error statesButton- Multiple variants (primary, outline, ghost, success, danger) with multiple sizes & iconsCard- Consistent container styling across the appStat- Icon-value-label component for metrics display
A complete theme management system with dark/light mode support, built with Context API and seamless TailwindCSS integration.
Dark/Light mode Implementation Highlights:
- Theme Context with
useStatefor simple and effective state management - Custom
useThemehook for easy access throughout the application - Automatically adds/removes
darkclass from HTML element - Triggers TailwindCSS dark mode variants automatically
- Automatic persistence in localStorage
- Provides visual feedback with smooth icon transitions
- Provides ThemeToggle component for using across app
- TypeScript support - fully typed for safe usage
Usage Examples:
- Theme Provider Setup:
// Wrap the entire application
createRoot(document.getElementById("root")!).render(
<StrictMode>
<ThemeContextProvider>
<App />
</ThemeContextProvider>
</StrictMode>
);- Using ThemeToggle in Navigation:
function Header() {
return (
<header>
<nav>
<NavLink to="/">Home</NavLink>
<NavLink to="/profiles">Profiles</NavLink>
<ThemeToggle /> {/* One-click theme switching */}
</nav>
</header>
);
}- Accessing Theme in Components:
function ThemedComponent() {
const { theme } = useTheme();
return (
<div className={theme === "dark" ? "dark-styles" : "light-styles"}>
Content that adapts to theme
</div>
);
}A feature-oriented React architecture designed for scalability, clear separation of concerns, and reusable UI foundations.
- Root Layout: Application shell with global header, footer, and loading indicator.
- Header: Responsive navigation, theme toggle, and mobile drawer.
- Error Page: Friendly messaging, retry/navigation actions, and development-mode diagnostics.
A clean structure that scales easily and keeps features, shared logic, and UI patterns well-organized.
src/
├── features/ → Core application features
│ ├── profile/ → CRUD, reducers, context, and multi-step wizard
│ └── theme/ → Theme system (light/dark) with context & hooks
│
├── shared/ → Reusable UI and logic
│ ├── components/ → Button, Card, Modal, Tabs, SmartList…
│ ├── hooks/ → search, filter, pagination…
│ ├── layouts/ → RootLayout, Header, Footer
│ └── types/ → Shared TypeScript types
│
├── pages/ → Home, Profile List, Profile View, Add Profile
├── data/ → Mock data
├── assets/ → Logos & static assets
└── router.tsx → App routing configuration
This project was designed with performance in mind from the start. Throughout development, I focused on reducing bundle size, avoiding unnecessary re-renders, and ensuring that every screen feels fast and responsive.
Below is a breakdown of the key techniques used in the application and why they matter.
- Code Splitting: Each page and heavy component is loaded on demand.
- Lazy Loading + Suspense: Routes and tabs load only when needed.
- Prefetching: Future steps and components are preloaded for instant navigation.
- Memoization: useMemo, useCallback, and React.memo reduce unnecessary re-renders.
- Optimized Context: Context values are memoized to avoid tree-wide updates.
- Bundle Compression: Gzip and Brotli versions are generated automatically.
- Manual Chunk Splitting: Dependencies are grouped into logical vendor chunks.
- Bundle Analysis: stats.html confirms improved structure and reduced duplication.
- Faster initial load - Smaller initial bundle size
- Instant navigation - Prefetching and lazy loading
- Optimized runtime - Reduced unnecessary re-renders
- Better caching - Logical vendor chunk splitting
- Total bundle size (uncompressed): 934.37 KB
- Gzip size: 200.60 KB
- Brotli size: 166.43 KB
- Total chunks: 11
- Total modules processed: 464
- Lazy-loaded files: 375 files
View detailed performance analysis →
Clone the repository, install project dependencies, and start the server
git clone git@github.com:smadi2512/profile-manager.git
cd profile-manager
npm install
npm run devNote: The project will run on http://localhost:5173
|
|
|
|
|
|
|
|
|
- Add advanced filtering: date-based, range, and multi-select filters for profiles.
- Integrate virtualized lists (react-window) for large datasets
- Implement optimistic UI updates for instant feedback during profile operations.
- Add drag-and-drop for reordering profiles and interests
- Introduce undo/redo functionality using command pattern
- Build plugin system for extensibility and custom logic
- Enhance accessibility and keyboard navigation for a fully inclusive experience
- Add unit/integration tests (React Testing Library + Vitest)
- Implement error logging & monitoring (Sentry)
Created by Walaa Smadi✨
Passionate React developer building modern, maintainable, scalable, performant, and user-friendly web apps.
- Email: walasmadi93@gmail.com
- LinkedIn: Walaa Smadi
- GitHub: @smadi2512
Feel free to fork, star ⭐, and contribute!









