Skip to main content

Frontend Development Overview

Frontend development creates the user-facing parts of applications - the interfaces users see and interact with. This encompasses web applications (React, Angular) and mobile applications (React Native, native iOS, native Android).

What is Frontend Development?

Frontend development bridges user needs and backend systems. It involves:

  • UI implementation: Building interfaces from designs
  • State management: Managing application data and user interactions
  • API integration: Fetching and displaying backend data
  • User experience: Performance, accessibility, responsiveness
  • Platform-specific concerns: Browser compatibility, mobile gestures, native platform features

Web vs. Mobile Frontend

While principles are shared, platforms have distinct characteristics:

AspectWebMobile
InputMouse, keyboard, touch (tablets)Touch, gestures, sensors
Screen sizeVariable (desktop, tablet, mobile)Smaller, fixed per device
PerformancePowerful CPUs, ample memoryLimited resources, battery concerns
OfflineMostly online, PWAs for offlineOften offline, sync when online
DistributionInstant (URL), no approvalApp stores, review process
UpdatesInstant deploymentUser must update app
Platform APIsWeb APIs (Camera, GPS, etc.)Native APIs (deeper integration)

Core Frontend Principles

Component-Based Architecture

Break UIs into reusable, composable components. Modern frameworks (React, Angular, Vue, SwiftUI, Jetpack Compose) all embrace this pattern.

Conceptual Example:

UserProfile Component
├── Avatar Component (displays user image)
├── UserInfo Component (displays name, email)
└── ActionButtons Component (handles user actions)

Each component is self-contained with its own logic and presentation. The parent component composes smaller components to create complex UIs.

Benefits:

  • Reusability: Components used across multiple features
  • Testability: Test components in isolation
  • Maintainability: Changes isolated to specific components
  • Collaboration: Teams work on different components independently

Framework Implementations:

Unidirectional Data Flow

Data flows one direction: parent to child via properties/inputs. Changes bubble up via callbacks/events.

Conceptual Pattern:

Parent Component (manages state: count = 0)
↓ passes count as property
Display Component (shows: "Count: 0")

↓ passes increment callback
Button Component (user clicks)
↑ calls callback
Parent Component (updates state: count = 1)
↓ passes updated count
Display Component (shows: "Count: 1")

Why Unidirectional Flow Matters:

  • Predictable: Easy to trace data from source to UI
  • Debuggable: Clear cause and effect for state changes
  • Maintainable: Changes flow in one consistent direction

Data flows down (properties/props/inputs), events flow up (callbacks/events/outputs).

Framework Implementations:

Separation of Concerns

Separate presentation, logic, and data fetching into distinct layers.

Three-Layer Pattern:

┌─────────────────────────────────────┐
│ Presentation Layer │
│ (Pure UI components) │
│ - UserCard component │
│ - Receives data via props │
│ - No business logic │
└─────────────────────────────────────┘
↑ data
┌─────────────────────────────────────┐
│ Container Layer │
│ (Data orchestration) │
│ - UserListContainer │
│ - Fetches data │
│ - Manages loading/error states │
│ - Passes data to presentation │
└─────────────────────────────────────┘
↑ data
┌─────────────────────────────────────┐
│ Data Access Layer │
│ (API calls, caching) │
│ - fetchUsers() │
│ - updateUser() │
│ - Handles HTTP, caching, errors │
└─────────────────────────────────────┘

Anti-Pattern (Mixed Concerns): A single component that:

  • Fetches data from an API
  • Manages loading/error states
  • Contains business logic
  • Renders the UI with inline styles

This makes the component hard to test (must mock API), hard to reuse (tightly coupled to data source), and hard to maintain (too many responsibilities).

Good Pattern (Separated Concerns):

  • Container Component: Fetches data, manages states, delegates rendering
  • Presentation Component: Pure UI that receives data and displays it
  • Data Layer: Isolated API calls and caching logic

Benefits:

  • Testability: Test presentation without mocking APIs
  • Reusability: Presentation components work with any data source
  • Maintainability: Change one layer without affecting others
  • Clarity: Each piece has one clear responsibility

See Web Component Architecture for detailed container vs presentational patterns.

Declarative UI

Describe what the UI should look like based on state, not how to build it step-by-step.

Imperative Approach (How - Step-by-Step DOM Manipulation):

// Tell the computer HOW to build the UI
const div = document.createElement('div');
div.className = 'user-card';
const h3 = document.createElement('h3');
h3.textContent = user.name;
div.appendChild(h3);
document.body.appendChild(div);

// Update when data changes - must manually track and update DOM
if (user.name !== previousName) {
h3.textContent = user.name;
}

Declarative Approach (What - State-Driven):

// Tell the computer WHAT the UI should look like
UserCard(user) {
UI:
- Card container with class "user-card"
- Heading displaying user.name
}

// Framework automatically updates UI when user.name changes

Benefits of Declarative:

  • Easier to understand: Read what the UI looks like, not how it's constructed
  • Less error-prone: No manual DOM synchronization
  • Easier to test: Test what UI looks like for given state
  • Maintainable: Changes to state automatically update UI

Modern frameworks are all declarative: React (JSX), Angular (templates), Vue (templates), SwiftUI (declarative views), Jetpack Compose (composable functions).

Framework Examples:

Frontend Architecture Layers

UI Layer

Components that render the interface. Should be mostly presentational.

Responsibilities:

  • Render UI based on props/state
  • Handle user interactions (clicks, input)
  • Minimal logic (UI-specific only)

State Management Layer

Manages application state. See Web State Management.

Tools:

  • React: Zustand (recommended), Redux, Context API
  • Angular: Signals (recommended), NgRx, Services
  • React Native: Same as React (Zustand, Redux)
  • iOS: Combine, SwiftUI State
  • Android: ViewModel, StateFlow, Compose State

Data Access Layer

Fetches data from APIs. Handles caching, loading states, error handling, and data synchronization.

Responsibilities:

  • Make HTTP requests to backend APIs
  • Cache responses to avoid redundant requests
  • Manage loading and error states
  • Handle background refetching to keep data fresh
  • Coordinate request deduplication
  • Retry failed requests with backoff strategies

Conceptual Pattern:

Component → Data Access Layer → HTTP Request → Backend API

Cache Check

Return Cached (if fresh) OR Fetch New Data

Update Cache → Notify Components

Tools by Framework:

  • React: React Query/TanStack Query, SWR, Apollo Client (GraphQL), RTK Query
  • Angular: HttpClient with RxJS, Apollo Angular (GraphQL), custom services with caching
  • React Native: Same as React (React Query, Apollo)
  • Native iOS: URLSession, Alamofire, Combine publishers
  • Native Android: Retrofit, OkHttp, Coroutines with Flow

Key Concepts:

  • Caching: Store fetched data to reduce API calls
  • Stale-while-revalidate: Show cached data immediately, fetch fresh data in background
  • Request deduplication: Multiple components requesting same data = single API call
  • Optimistic updates: Update UI immediately, rollback if API call fails

See React State Management for React Query patterns, Angular State Management for HttpClient patterns.

Routing Layer

Maps URLs to components (web) or screens (mobile).

See Mobile Navigation for mobile-specific patterns.

Web Frontend

See Web Development for web-specific patterns.

Strengths:

  • Large ecosystem, excellent tooling
  • Functional components with hooks
  • Great developer experience
  • Strong TypeScript support

When to use: Most new web projects, especially with complex state management needs.

See React Guidelines.

Angular

Strengths:

  • Complete framework (routing, forms, HTTP, etc.)
  • Strong TypeScript integration
  • Dependency injection
  • Excellent for enterprise applications

When to use: Large teams, complex enterprise applications, existing Angular codebase.

See Angular Guidelines.

Mobile Frontend

See Mobile Development for mobile-specific patterns.

React Native (Cross-Platform)

Write once, run on iOS and Android.

Strengths:

  • Shared codebase reduces development time
  • JavaScript ecosystem
  • Hot reloading for fast development
  • Native performance for most use cases

Weaknesses:

  • Limited to features supported by React Native
  • Some platform-specific code still needed
  • Slightly less performant than fully native

When to use: Apps without heavy platform-specific features, rapid development, smaller teams.

See React Native Guidelines.

Native iOS (Swift)

Strengths:

  • Full access to iOS APIs
  • Best performance
  • Latest iOS features immediately available
  • SwiftUI for modern declarative UI

When to use: iOS-specific features needed, maximum performance required, rich iOS ecosystem integration.

See iOS Guidelines.

Native Android (Kotlin)

Strengths:

  • Full access to Android APIs
  • Best performance
  • Jetpack Compose for modern declarative UI
  • Material Design components

When to use: Android-specific features needed, maximum performance required, deep Android integration.

See Android Guidelines.

Cross-Cutting Frontend Concerns

Accessibility

Build applications usable by everyone, including people with disabilities.

Key principles (WCAG 2.1):

  • Perceivable: Content must be presentable to all users
  • Operable: UI components must be operable
  • Understandable: Information must be understandable
  • Robust: Content must work with assistive technologies

See Accessibility for universal principles, Web Accessibility for web-specific implementation.

Performance

Frontend performance directly impacts user experience.

Web vitals:

  • LCP (Largest Contentful Paint): < 2.5s
  • FID (First Input Delay): < 100ms
  • CLS (Cumulative Layout Shift): < 0.1

See React Performance, Angular Performance, Mobile Performance.

Responsive Design (Web)

Adapt to different screen sizes.

/* Mobile-first approach */
.container {
padding: 1rem;
width: 100%;
}

/* Tablet */
@media (min-width: 768px) {
.container {
padding: 2rem;
max-width: 720px;
margin: 0 auto;
}
}

/* Desktop */
@media (min-width: 1200px) {
.container {
max-width: 1140px;
}
}

See Web Styling for detailed responsive patterns.

Testing

Frontend testing pyramid:

  1. Unit tests: Test individual components and functions
  2. Integration tests: Test component interactions
  3. E2E tests: Test full user workflows

See React Testing, Angular Testing, Mobile Testing.

Internationalization (i18n)

Support multiple languages and locales.

Core Concepts:

  • Translation keys: Reference text by key rather than hardcoding strings
  • Parameter interpolation: Insert dynamic values into translated strings
  • Pluralization: Handle singular/plural forms correctly for each language
  • Locale-specific formatting: Dates, numbers, currencies formatted per locale

Conceptual Pattern:

Translation File (en.json):
{
"greeting.welcome": "Welcome, {{name}}!",
"greeting.message": "Thank you for visiting."
}

Translation File (es.json):
{
"greeting.welcome": "¡Bienvenido, {{name}}!",
"greeting.message": "Gracias por visitarnos."
}

Component:
Display: translate("greeting.welcome", { name: "John" })
Result (en): "Welcome, John!"
Result (es): "¡Bienvenido, John!"

Tools by Framework:

  • React: i18next, react-intl (Format.js), LinguiJS
  • Angular: @angular/localize, ngx-translate
  • React Native: Same as React (i18next, react-intl)
  • Native iOS: NSLocalizedString, Localizable.strings
  • Native Android: strings.xml resources, multiple locale folders

See framework-specific guides for implementation details.

Frontend Development Workflow

Component Development

  1. Design review: Understand requirements and designs
  2. Component breakdown: Identify reusable components
  3. Implementation: Build components bottom-up (small to large)
  4. Testing: Unit tests, integration tests
  5. Code review: Peer review for quality
  6. Integration: Combine with backend APIs

Styling Approaches

Web applications have multiple styling approaches. The choice depends on team size, project complexity, and framework preferences.

Approach Categories:

  1. Traditional CSS/Scoped CSS

    • Standard CSS files with scoping mechanisms
    • Examples: CSS Modules (React), Component styles (Angular), Scoped styles (Vue)
    • Pros: Familiar, good IDE support, separate styling from logic
    • Cons: Context switching between files, potential naming conflicts
  2. Utility-First CSS

    • Compose styles from pre-defined utility classes
    • Examples: Tailwind CSS, Tachyons
    • Pros: Fast development, consistent design system, small production bundles
    • Cons: Verbose HTML, learning curve for class names
  3. CSS-in-JS

    • Write styles in JavaScript/TypeScript
    • Examples: styled-components, Emotion, styled-jsx
    • Pros: Dynamic styles based on props, automatic critical CSS, type safety
    • Cons: Runtime overhead, harder to debug, larger bundles
  4. Native Platform Styles

    • Platform-specific styling systems
    • Examples: StyleSheet (React Native), SwiftUI modifiers, Jetpack Compose modifiers
    • Pros: Platform-optimized, access to platform-specific features
    • Cons: Platform-specific, different APIs per platform

Conceptual Example (All Approaches):

Card Component with:
- 1rem padding
- 1px solid border (#ccc)
- Rounded corners

Title with:
- 1.2rem font size
- Bold weight

Each approach achieves the same visual result using different syntax and organization strategies.

See Web Styling for detailed web-specific comparison and implementation patterns.

Common Frontend Anti-Patterns

Prop Drilling

Passing properties/props through many intermediate components that don't use them, just to get data to deeply nested components.

Problem Pattern:

App (has user data)
↓ passes user to Dashboard
Dashboard (doesn't use user, just passes it down)
↓ passes user to Sidebar
Sidebar (doesn't use user, just passes it down)
↓ passes user to UserMenu
UserMenu (doesn't use user, just passes it down)
↓ passes user to Avatar
Avatar (finally uses user data)

Three layers of components serve only as conduits for data they don't use. This makes components harder to refactor and couples them unnecessarily.

Solution: Use shared state mechanisms (Context in React, Services in Angular) or state management libraries for data needed by distant components.

See Web State Management for shared state patterns.

Massive Components

Components with hundreds of lines and many responsibilities.

Solution: Break into smaller, focused components.

State Duplication

Same data in multiple places, getting out of sync.

Solution: Single source of truth. Derive state instead of duplicating.

Premature Optimization

Optimizing before identifying actual performance issues.

Solution: Build for clarity first, profile, then optimize bottlenecks.

Further Learning

Books:

  • Learning React by Alex Banks & Eve Porcello
  • Angular in Action by Jeremy Wilken
  • React Native in Action by Nader Dabit

Online Resources:

Practice:

  • Build small projects with different frameworks
  • Contribute to open-source frontend projects
  • Review code from established projects (Airbnb, GitHub)
  • Follow frontend thought leaders (Kent C. Dodds, Dan Abramov, Addy Osmani)