Skip to main content

Overview

The AutoLight V3 WebClient is a modern Next.js 15 web application that provides a comprehensive interface for controlling AutoLight V3 LED systems. The application connects to AutoLight hardware devices via REST API and provides real-time control and monitoring capabilities with an advanced Pattern Builder for LED sequence development. Key Technologies: Next.js 15, React 19, TypeScript, shadcn/ui, Tailwind CSS 4

Development Commands

Primary Workflow

# Start development server (port 3001)
npm run dev

# Build for production with static export
npm run build

# Start production server (port 3001)
npm run start

# Lint code
npm run lint

# Kill server on port 3001 (Linux/macOS)
npm run kill

Mobile Development (Capacitor)

# Add Android platform
npm run cap:add:android

# Build and sync for Android development
npm run cap:build:android

# Sync project with native platforms
npm run cap:sync

Architecture

Client-Side Rendering Strategy

This application uses full client-side rendering with all major components using the "use client" directive:
  • Real-time Updates: Immediate response to device state changes
  • Complex Interactions: Pattern Builder requires client-side state management
  • Performance: Avoids server-side rendering overhead for real-time UI

Dual Context State Management

Separate contexts for different concerns:
Device and API State ManagementLocation: /lib/contexts/ALSContext.tsx
interface ALSContextType {
  // Device State
  deviceName: string
  deviceSerial: string
  deviceCh: number
  mode: number
  delay: number
  
  // API Configuration
  host: string
  port: string
  protocol: 'http' | 'https'
  connectionType: 'ip' | 'dns'
  
  // Settings Management
  settingsData: {
    themes: 'modern' | 'classic'
    colors: 'dark' | 'light'
    loader: boolean
  }
  
  // Update Methods
  updateDeviceName: (name: string) => void
  updateMode: (mode: number) => void
  updateDelay: (delay: number) => void
  updateConnectionConfig: (config: ConnectionConfig) => void
}
Features:
  • localStorage persistence for API configuration
  • Memoized callbacks with deep equality checks
  • Optimized updates to prevent unnecessary re-renders

Real-Time Polling System

useALSPolling Hook - Location: /lib/hooks/useALSPolling.ts
export function useALSPolling() {
  const { updateDeviceState, connectionConfig } = useALS()
  
  useEffect(() => {
    const pollDevice = async () => {
      try {
        // Concurrent API calls using Promise.allSettled
        const [name, serial, ch, mode, delay] = await Promise.allSettled([
          getDeviceName(),
          getDeviceSerial(),
          getDeviceChannels(),
          getDeviceMode(),
          getDeviceDelay()
        ])
        
        // Update state with results
        updateDeviceState({ name, serial, ch, mode, delay })
      } catch (error) {
        console.error('Polling error:', error)
      }
    }
    
    // Poll every 2 seconds
    const interval = setInterval(pollDevice, 2000)
    pollDevice() // Initial poll
    
    return () => clearInterval(interval)
  }, [connectionConfig])
}
Features:
  • Concurrent API Calls: Promise.allSettled() for 5 endpoints simultaneously
  • Grace Period Logic: 1-second grace period after local changes
  • Dynamic Configuration: Updates API config without interrupting polling
  • Error Resilience: Comprehensive error handling with fallbacks

API Integration

The application communicates with AutoLight V3 hardware via REST endpoints.

Base URL Construction

const baseURL = `${protocol}://${host}:${port}/api/v1`

// Example: http://192.168.4.1:8000/api/v1

API Functions

Location: /lib/api/device.ts
export async function getDeviceName(): Promise<string> {
  const response = await fetch(`${baseURL}/data/get/device/name`)
  return response.text()
}

export async function getDeviceSerial(): Promise<string> {
  const response = await fetch(`${baseURL}/data/get/device/serial`)
  return response.text()
}

export async function getDeviceChannels(): Promise<number> {
  const response = await fetch(`${baseURL}/data/get/device/ch`)
  return parseInt(await response.text())
}

Connection Configuration

Stored in localStorage with migration support:
interface ConnectionConfig {
  host: string          // '192.168.4.1' or 'als.local'
  port: string          // '8000'
  protocol: 'http' | 'https'
  connectionType: 'ip' | 'dns'
}

// Default configuration
const defaultConfig: ConnectionConfig = {
  host: '192.168.4.1',
  port: '8000',
  protocol: 'http',
  connectionType: 'ip'
}

Component Architecture

Dual Theme System

Card-based interface with drawer componentsLocation: components/ModernTheme.tsxFeatures:
  • Card-based layout with shadcn/ui components
  • Drawer navigation for settings and info
  • Responsive grid system
  • Modern UI/UX patterns
<div className="container mx-auto p-4 space-y-6">
  <MainHeader />
  
  <div className="grid gap-6 md:grid-cols-2">
    <Card>
      <CardHeader>
        <CardTitle>LED Control</CardTitle>
      </CardHeader>
      <CardContent>
        {/* Control interface */}
      </CardContent>
    </Card>
  </div>
</div>

Core Components

components/
├── MainPage.tsx              # Root component with theme routing
├── ModernTheme.tsx           # Card-based interface
├── ClassicTheme.tsx          # Section-based layout
├── content/                  # Shared UI components
│   ├── MainHeader.tsx        # Navigation header
│   ├── Sidebar.tsx           # Mobile sidebar navigation
│   ├── ConnectionStatus.tsx  # Device connection indicators
│   └── ThemeToggle.tsx       # Dark/light mode toggle
├── simulation/               # Pattern Builder components
│   ├── modes/                # 4 simulation modes
│   ├── grid/                 # Grid system components
│   ├── config/               # Configuration components
│   └── expression/           # Expression parsing UI
└── ui/                       # shadcn/ui components (21 components)

shadcn/ui Integration

The application uses 21 Radix UI components:

Button

Card

Drawer

Dialog

Slider

Switch

Tabs

Select

Accordion

Alert

Badge

Input

Label

Textarea

Tooltip

Separator

Checkbox

RadioGroup

DropdownMenu

Progress

Spinner

Configuration: components.json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": false,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "app/globals.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}

Main Interface Features

Device Control

16 LED sequence modes (0-15)
<Select value={mode} onValueChange={updateMode}>
  <SelectTrigger>
    <SelectValue />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="0">Mode 0 - OFF</SelectItem>
    <SelectItem value="1">Mode 1 - Static ON</SelectItem>
    <SelectItem value="2">Mode 2 - Blink All</SelectItem>
    {/* ... modes 3-15 */}
  </SelectContent>
</Select>

Settings Management

Location: /app/settings/page.tsx
Configure API connection:
  • Host: IP address or DNS name
  • Port: API port (default 8000)
  • Protocol: HTTP or HTTPS
  • Connection Type: IP or DNS
  • Test Connection: Built-in connectivity test
<ConnectionConfigForm
  config={connectionConfig}
  onUpdate={updateConnectionConfig}
  onTest={testConnection}
/>
Customize appearance:
  • Theme: Modern or Classic
  • Color Mode: Dark or Light
  • Accent Color: Customizable
<ThemeSelector
  theme={theme}
  colorMode={colorMode}
  onThemeChange={updateTheme}
  onColorModeChange={updateColorMode}
/>
Device configuration:
  • Device Name: Update device name
  • Channel Count: Display channel configuration
  • Serial Number: Read-only device serial
<DeviceInfoForm
  deviceName={deviceName}
  deviceSerial={deviceSerial}
  deviceCh={deviceCh}
  onNameUpdate={updateDeviceName}
/>

Pattern Builder Integration

The Pattern Builder is available at /app/simulation/page.tsx and provides desktop-only LED sequence development.
Desktop Only: The Pattern Builder requires a screen width ≥1024px (lg breakpoint). Mobile devices will see an informative message explaining the desktop requirement.

4 Simulation Modes

Interactive grid-based LED pattern creationComponent: components/simulation/modes/VisualPatternMode.tsxFeatures:
  • Dynamic LED grid (supports up to 64 channels)
  • Frame-by-frame editing
  • Timeline visualization
  • Real-time playback with precise timing
  • Export to C++ code
<DynamicPatternGrid
  channels={deviceCh}
  frame={currentFrame}
  onLEDClick={toggleLED}
/>

High-Precision Timing System

PrecisionTimer Class - Location: /lib/utils/precisionTimer.ts
class PrecisionTimer {
  private targetDelay: number
  private callback: () => void
  
  constructor(delay: number, callback: () => void) {
    this.targetDelay = delay
    this.callback = callback
  }
  
  start() {
    // Hybrid algorithm: setTimeout + requestAnimationFrame
    const startTime = performance.now()
    
    const tick = () => {
      const elapsed = performance.now() - startTime
      
      if (elapsed >= this.targetDelay) {
        this.callback()
        return
      }
      
      requestAnimationFrame(tick)
    }
    
    // Initial setTimeout for bulk delay
    setTimeout(() => {
      requestAnimationFrame(tick)
    }, this.targetDelay - 20)
  }
}
Features:
  • ±1-4% Timing Accuracy: Revolutionary improvement over standard setTimeout
  • Hybrid Algorithm: Combines setTimeout and requestAnimationFrame
  • Hardware Compatibility: JavaScript patterns match ESP32 timing exactly
  • Zero Double-Timing: Eliminates setTimeout + playback conflicts

Configuration Files

Next.js Configuration

next.config.ts
const nextConfig: NextConfig = {
  output: 'export',        // Static export mode
  trailingSlash: true,     // Required for static hosting
  basePath: '',            // No base path
  images: { 
    unoptimized: true      // Static image optimization
  }
}

Tailwind Configuration

tailwind.config.ts
export default {
  darkMode: ['class'],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
  ],
  theme: {
    extend: {
      colors: {
        border: 'hsl(var(--border))',
        background: 'hsl(var(--background))',
        foreground: 'hsl(var(--foreground))',
        // ... CSS variable-based colors
      }
    }
  },
  plugins: [require('tailwindcss-animate')]
}

Deployment

Static Export Build

# Build for production
npm run build

# Output directory: /out
# Files are static HTML/CSS/JS
# Can be served from any web server

Serving Static Files

npm run start
# Serves on http://localhost:3001

Next Steps

Pattern Builder

Learn about LED pattern creation tools

REST API

Complete API reference for integration

AutoLight V3

Explore firmware architecture

Back to Overview

Return to AutoLight overview

Build docs developers (and LLMs) love