Feature Flag Service Tutorial · Module 08 of 10

Admin Dashboard & UI

Build a React-based admin dashboard to create, edit, and toggle flags. Create a rule builder UI for non-technical users. Show real-time flag evaluation statistics and audit history. By the end, anyone can manage flags without touching code.

~5–6 hrsAdvancedUI focus
← Back to Module 08 overview
What You'll Have at the End

Definition of Done

  • React frontend scaffolded with Create React App or Vite.
  • Flag list page: create, edit, toggle, delete flags.
  • Rule builder: drag-and-drop or form-based rule creation.
  • Flag details page: view rules, audit history, evaluation stats.
  • Real-time stats: evaluation throughput, cache hit rate.
  • Audit log viewer: who changed what and when.
  • Authentication: API key or OAuth.
  • Responsive design: works on desktop and tablet.
The Steps

Build It

STEP 1

Scaffold React dashboard

npm create vite@latest dashboard -- --template react-ts
cd dashboard
npm install
✓ Verify: npm run dev starts dev server at http://localhost:5173.
STEP 2

Create React components for flag management

Create dashboard/src/components/FlagList.tsx:

import React, { useEffect, useState } from 'react';
import axios from 'axios';

interface Flag {
  id: string;
  name: string;
  description: string;
  status: 'off' | 'on' | 'percentage' | 'rules';
  percentage_enabled: number;
  updated_at: string;
}

export function FlagList() {
  const [flags, setFlags] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchFlags = async () => {
      try {
        const response = await axios.get('/api/flags');
        setFlags(response.data.flags);
      } catch (err) {
        console.error('Failed to fetch flags:', err);
      } finally {
        setLoading(false);
      }
    };
    fetchFlags();
  }, []);

  if (loading) return 
Loading...
; return (

Feature Flags

{flags.map(flag => ( ))}
Name Status Updated Actions
{flag.name} {flag.status} {new Date(flag.updated_at).toLocaleDateString()}
); }