Check a page for accessibility
Review supplied markup or descriptions for practical accessibility issues and fixes.
5,455,881 AI resources indexedWorking toward the world’s largest AI resource index.
Use when applying a brand theme configuration to the app. Reads theme_config.json and updates Dart theme files with new colors, gradients, logos, and animation effects.
---
name: apply-theme-3d7fe97afac1
description: Use when applying a brand theme configuration to the app. Reads theme_config.json and updates Dart theme files with new colors, gradients, logos, and animation effects.
---
# Apply Theme Skill
Reads `assets/config/theme_config.json` generated by `/brand-theme` and applies it to the Flutter app's theme system.
## When to Use
- After running `/brand-theme` to generate a config
- User asks to "apply the theme", "update theme from config", or "implement the brand colors"
- User invokes `/apply-theme` directly
## Prerequisites
- `assets/config/theme_config.json` must exist (generated by `/brand-theme`)
- If it doesn't exist, instruct user to run `/brand-theme` first
## Process Overview
1. Read and validate `theme_config.json`
2. Update color definitions in `lib/core/theme/app_colors.dart`
3. Update gradients in `lib/core/theme/gradients.dart`
4. Update logo paths
5. Update app name, caption, and welcome message in `lib/core/constants/app_constants.dart`
6. Implement animation effects based on style preset
7. Verify the app builds successfully
## Step 1: Read Configuration
Read `assets/config/theme_config.json` and validate structure:
```json
{
"brand": {
"name": "...",
"appName": { "light": "...", "dark": "..." },
"caption": { "light": "...", "dark": "..." },
"welcomeMessage": "...",
"logo": { "light": "...", "dark": "..." }
},
"colors": { "primary": "#...", "secondary": "#...", "accent": "#..." },
"animation": { "style": "neon|cosmic|minimal|professional|playful" },
"modes": { "default": "dark|light|system" }
}
```
**Validation checks:**
- Primary color is valid hex
- Logo paths are provided
- Animation style is one of the valid presets
- App name and caption are provided (or default to brand.name)
## Step 2: Update app_colors.dart
File: `lib/core/theme/app_colors.dart`
### Color Mapping
Map config colors to the app's color system. Generate both light and dark variants.
**From config primary color, derive:**
For **dark mode** (if primary is the accent color):
- `_darkPrimary` = config primary
- `_darkPrimaryForeground` = contrasting color (white or dark based on luminance)
- `_darkSecondary` = config secondary (or derive complementary)
- `_darkAccent` = config accent (or derive triadic)
- `_darkBackground` = deep dark version of primary (10% lightness)
- `_darkCard` = slightly lighter than background (15% lightness)
- `_darkMuted` = desaturated primary at 20% lightness
- `_darkMessageBubbleOwn` = primary at 30% lightness
For **light mode**:
- `_lightPrimary` = config primary
- `_lightPrimaryForeground` = white (or dark if primary is light)
- `_lightBackground` = white or very light tint of primary
- `_lightCard` = off-white or very light gray
- `_lightMessageBubbleOwn` = config primary
### Logo Paths
Update lines 97-98 in app_colors.dart:
```dart
static const String lightLogo = '[CONFIG_LIGHT_LOGO]';
static const String darkLogo = '[CONFIG_DARK_LOGO]';
```
**Logo Sizing Note:**
- The welcome screen (`lib/features/chat/presentation/widgets/welcome_hero_screen.dart`) displays the logo at `height: 120`
- **Prefer emblem/icon-only logos** - full logos with text appear oversized at this height
- If logo appears too large, verify an emblem-only asset is being used
### Color Generation Algorithm
```
Given primary hex color:
1. Convert to HSL
2. For dark mode derived colors:
- Background: H same, S * 0.3, L = 5%
- Card: H same, S * 0.3, L = 8%
- Muted: H same, S * 0.2, L = 15%
- Border: H same, S * 0.2, L = 12%
3. For light mode derived colors:
- Background: white (#FFFFFF)
- Card: H same, S * 0.05, L = 98%
- Muted: H same, S * 0.1, L = 96%
4. For foreground/text colors:
- If primary luminance > 0.5: use dark text
- If primary luminance <= 0.5: use light text
```
## Step 3: Update gradients.dart
File: `lib/core/theme/gradients.dart`
Generate gradient variations from the config colors:
```dart
// Primary gradient - 3 stops from lighter to darker
static const darkPrimaryGradient = LinearGradient(
colors: [
Color(0xFF[LIGHTER_PRIMARY]), // +10% lightness
Color(0xFF[PRIMARY]), // config primary
Color(0xFF[DARKER_PRIMARY]), // -10% lightness
],
stops: [0.0, 0.5, 1.0],
);
```
Apply same pattern to:
- `darkPrimaryGradient` / `lightPrimaryGradient`
- `darkSecondaryGradient` / `lightSecondaryGradient`
- `darkAccentGradient`
- `primaryButtonGradient`
- `secondaryButtonGradient`
## Step 4: Update App Constants
File: `lib/core/constants/app_constants.dart`
Update the app name, caption, and related strings from the config:
```dart
// App Information
static const String appName = '[CONFIG_APPNAME_LIGHT]'; // Light theme name
static const String appNameDark = "[CONFIG_APPNAME_DARK]"; // Dark theme name
static const String appCaption = '[CONFIG_CAPTION_LIGHT]'; // Light theme caption
static const String appCaptionDark = '[CONFIG_CAPTION_DARK]'; // Dark theme caption
```
**Mapping from config:**
- `appName` = `brand.appName.light` (or `brand.name` if not specified)
- `appNameDark` = `brand.appName.dark` (or `brand.name` if not specified)
- `appCaption` = `brand.caption.light` (or "Powered by AI" if not specified)
- `appCaptionDark` = `brand.caption.dark` (or same as light if not specified)
**Note:** The welcome message (`brand.welcomeMessage`) is used in `chat_home_page.dart` via the app name constants. Updating `appName` and `appNameDark` will automatically update the welcome message format: "Welcome to {appName}!"
## Step 5: Implement Animation Effects
Based on `animation.style` from config, create or update animation widgets.
### CRITICAL: Follow Existing Codebase Patterns
All effects MUST follow these patterns from the existing codebase:
#### Pattern 1: Theme Brightness Detection
```dart
final isDark = Theme.of(context).brightness == Brightness.dark;
```
#### Pattern 2: AppColors Extension Access
```dart
final appColors = Theme.of(context).extension<AppColorsExtension>()!;
final colorScheme = Theme.of(context).colorScheme;
```
#### Pattern 3: Dynamic Color Selection (from speech_to_text_widget.dart)
```dart
List<Color> _buildGlowColors() {
final isDark = Theme.of(context).brightness == Brightness.dark;
final appColors = context.appColors;
if (isDark) {
return isActive
? [
colorScheme.primary.withOpacity(0.8),
colorScheme.secondary.withOpacity(0.6),
appColors.accent.withOpacity(0.4),
]
: [
appColors.mutedForeground.withOpacity(0.3),
appColors.mutedForeground.withOpacity(0.2),
];
}
// Light theme with reduced intensity...
}
```
#### Pattern 4: Use AppConstants for Animation Values
Reference: `lib/core/constants/app_constants.dart`
```dart
static const Duration glowAnimationDuration = Duration(milliseconds: 2000);
static const double glowBorderSize = 2.0;
static const double speechGlowSizeListening = 12.0;
static const double speechGlowSizeIdle = 6.0;
```
#### Pattern 5: Existing Packages to Use
- **glowy_borders** - `AnimatedGradientBorder` for neon glow effects
- **flutter_animate** - `.animate().fadeIn().scale().shimmer()` chains
- **CustomPainter** - For particle/starfield effects (see `particles_widget.dart`)
- **AnimationController + AnimatedBuilder** - For wave/pulse effects
#### Pattern 6: Particles Widget Reference
See `lib/shared/widgets/particles_widget.dart` for starfield implementation:
```dart
ParticlesWidget(
quantity: 50,
color: appColors.primary, // Theme-aware
staticity: 50,
size: 0.4,
)
```
### Effect Implementation Patterns
Reference: https://github.com/flutterfx/flutterfx_widgets
#### cosmic style
Create `lib/shared/widgets/effects/cosmic_background.dart`:
- Animated starfield using CustomPainter
- Subtle parallax on mouse/touch movement
- Use `flutter_animate` for particle fade effects
#### neon style
Create `lib/shared/widgets/effects/border_beams.dart`:
- Animated gradient border using `glowy_borders` package
- Pulsing glow effect synced with primary color
- Use config primary color for the beam color
#### minimal style
- No new widgets needed
- Ensure existing `BlurFade` transitions are subtle (duration: 200ms, blur: 2.0)
#### professional style
Create `lib/shared/widgets/effects/fancy_card.dart`:
- Elevated card with subtle shadow animation
- Hover state with slight scale and shadow increase
- Clean, understated motion
#### playful style
Create `lib/shared/widgets/effects/particle_burst.dart`:
- Confetti/particle effect on interactions
- Use chart colors from config for particle variety
- Bouncy spring animations
### Effect File Structure
```
lib/shared/widgets/effects/
├── cosmic_background.dart # For cosmic style
├── border_beams.dart # For neon style
├── fancy_card.dart # For professional style
├── particle_burst.dart # For playful style
└── effects_provider.dart # Exports based on active style
```
### effects_provider.dart Template
```dart
import 'package:flutter/material.dart';
enum AnimationStyle { cosmic, neon, minimal, professional, playful }
// Current active style from config
const AnimationStyle activeStyle = AnimationStyle.[CONFIG_STYLE];
class EffectsProvider {
static Widget wrapWithBackground(Widget child) {
switch (activeStyle) {
case AnimationStyle.cosmic:
return CosmicBackground(child: child);
case AnimationStyle.neon:
return BorderBeamsBackground(child: child);
case AnimationStyle.professional:
return FancyCardBackground(child: child);
case AnimationStyle.playful:
return FlickeringGridBackground(child: child);
case AnimationStyle.minimal:
default:
return child;
}
}
static Widget wrapWithLoadingEffect(Widget child) {
// Similar switch for loading indicators
}
}
```
## Step 6: Verify Build
After making all changes:
1. Run `flutter analyze` to check for errors
2. Run `flutter build web --wasm` to verify build succeeds
3. Report any issues found
**IMPORTANT:** If testing via the backend server (http://localhost:8000):
- The server serves static files from `build/web`
- After rebuilding, **restart the server** to serve the new build
- Kill existing server: `lsof -ti :8000 | xargs kill -9`
- Start fresh: `cd backend && uv run python app.py`
## Output Summary
After applying theme, display:
```
Theme applied successfully!
Updated files:
- lib/core/theme/app_colors.dart (colors + logos)
- lib/core/theme/gradients.dart (gradient variations)
- lib/core/constants/app_constants.dart (app name + caption)
- lib/shared/widgets/effects/ (animation widgets)
Brand applied:
- App Name: [NAME]
- Caption: [CAPTION]
- Welcome: [WELCOME_MESSAGE]
Colors applied:
- Primary: [HEX]
- Secondary: [HEX]
- Accent: [HEX]
Animation style: [STYLE]
Next steps:
- Run `flutter build web --wasm` to rebuild
- Restart the backend server to serve the new build
- Test the app at http://localhost:8000
```
## Rollback
If issues occur, the skill should:
1. Keep original files backed up (git handles this)
2. Provide instructions to revert: `git checkout -- lib/core/theme/`
## File Modification Checklist
Before completing, verify these files were updated:
- [ ] `lib/core/theme/app_colors.dart` - Color constants and logo paths
- [ ] `lib/core/theme/gradients.dart` - Gradient definitions
- [ ] `lib/core/constants/app_constants.dart` - App name, caption, welcome message
- [ ] `lib/shared/widgets/effects/` - Animation effect widgets (if style != minimal)
- [ ] Verify `flutter analyze` passes
- [ ] Commit changes with descriptive message
## Error Handling
**Config file not found:**
```
theme_config.json not found at assets/config/theme_config.json
Run /brand-theme first to generate the configuration.
```
**Invalid color format:**
```
Invalid color "[value]" in config. Expected hex format like #FF5F46.
Please fix the config file or run /brand-theme again.
```
**Build fails after changes:**
```
Build failed after applying theme. Errors:
[error details]
You can revert changes with: git checkout -- lib/core/theme/
Then review the config and try again.
```
---
name: apply-theme-3d7fe97afac1
description: Use when applying a brand theme configuration to the app. Reads theme_config.json and updates Dart theme files with new colors, gradients, logos, and animation effects.
---
# Apply Theme Skill
Reads `assets/config/theme_config.json` generated by `/brand-theme` and applies it to the Flutter app's theme system.
## When to Use
- After running `/brand-theme` to generate a config
- User asks to "apply the theme", "update theme from config", or "implement the brand colors"
- User invokes `/apply-theme` directly
## Prerequisites
- `assets/config/theme_config.json` must exist (generated by `/brand-theme`)
- If it doesn't exist, instruct user to run `/brand-theme` first
## Process Overview
1. Read and validate `theme_config.json`
2. Update color definitions in `lib/core/theme/app_colors.dart`
3. Update gradients in `lib/core/theme/gradients.dart`
4. Update logo paths
5. Update app name, caption, and welcome message in `lib/core/constants/app_constants.dart`
6. Implement animation effects based on style preset
7. Verify the app builds successfully
## Step 1: Read Configuration
Read `assets/config/theme_config.json` and validate structure:
```json
{
"brand": {
"name": "...",
"appName": { "light": "...", "dark": "..." },
"caption": { "light": "...", "dark": "..." },
"welcomeMessage": "...",
"logo": { "light": "...", "dark": "..." }
},
"colors": { "primary": "#...", "secondary": "#...", "accent": "#..." },
"animation": { "style": "neon|cosmic|minimal|professional|playful" },
"modes": { "default": "dark|light|system" }
}
```
**Validation checks:**
- Primary color is valid hex
- Logo paths are provided
- Animation style is one of the valid presets
- App name and caption are provided (or default to brand.name)
## Step 2: Update app_colors.dart
File: `lib/core/theme/app_colors.dart`
### Color Mapping
Map config colors to the app's color system. Generate both light and dark variants.
**From config primary color, derive:**
For **dark mode** (if primary is the accent color):
- `_darkPrimary` = config primary
- `_darkPrimaryForeground` = contrasting color (white or dark based on luminance)
- `_darkSecondary` = config secondary (or derive complementary)
- `_darkAccent` = config accent (or derive triadic)
- `_darkBackground` = deep dark version of primary (10% lightness)
- `_darkCard` = slightly lighter than background (15% lightness)
- `_darkMuted` = desaturated primary at 20% lightness
- `_darkMessageBubbleOwn` = primary at 30% lightness
For **light mode**:
- `_lightPrimary` = config primary
- `_lightPrimaryForeground` = white (or dark if primary is light)
- `_lightBackground` = white or very light tint of primary
- `_lightCard` = off-white or very light gray
- `_lightMessageBubbleOwn` = config primary
### Logo Paths
Update lines 97-98 in app_colors.dart:
```dart
static const String lightLogo = '[CONFIG_LIGHT_LOGO]';
static const String darkLogo = '[CONFIG_DARK_LOGO]';
```
**Logo Sizing Note:**
- The welcome screen (`lib/features/chat/presentation/widgets/welcome_hero_screen.dart`) displays the logo at `height: 120`
- **Prefer emblem/icon-only logos** - full logos with text appear oversized at this height
- If logo appears too large, verify an emblem-only asset is being used
### Color Generation Algorithm
```
Given primary hex color:
1. Convert to HSL
2. For dark mode derived colors:
- Background: H same, S * 0.3, L = 5%
- Card: H same, S * 0.3, L = 8%
- Muted: H same, S * 0.2, L = 15%
- Border: H same, S * 0.2, L = 12%
3. For light mode derived colors:
- Background: white (#FFFFFF)
- Card: H same, S * 0.05, L = 98%
- Muted: H same, S * 0.1, L = 96%
4. For foreground/text colors:
- If primary luminance > 0.5: use dark text
- If primary luminance <= 0.5: use light text
```
## Step 3: Update gradients.dart
File: `lib/core/theme/gradients.dart`
Generate gradient variations from the config colors:
```dart
// Primary gradient - 3 stops from lighter to darker
static const darkPrimaryGradient = LinearGradient(
colors: [
Color(0xFF[LIGHTER_PRIMARY]), // +10% lightness
Color(0xFF[PRIMARY]), // config primary
Color(0xFF[DARKER_PRIMARY]), // -10% lightness
],
stops: [0.0, 0.5, 1.0],
);
```
Apply same pattern to:
- `darkPrimaryGradient` / `lightPrimaryGradient`
- `darkSecondaryGradient` / `lightSecondaryGradient`
- `darkAccentGradient`
- `primaryButtonGradient`
- `secondaryButtonGradient`
## Step 4: Update App Constants
File: `lib/core/constants/app_constants.dart`
Update the app name, caption, and related strings from the config:
```dart
// App Information
static const String appName = '[CONFIG_APPNAME_LIGHT]'; // Light theme name
static const String appNameDark = "[CONFIG_APPNAME_DARK]"; // Dark theme name
static const String appCaption = '[CONFIG_CAPTION_LIGHT]'; // Light theme caption
static const String appCaptionDark = '[CONFIG_CAPTION_DARK]'; // Dark theme caption
```
**Mapping from config:**
- `appName` = `brand.appName.light` (or `brand.name` if not specified)
- `appNameDark` = `brand.appName.dark` (or `brand.name` if not specified)
- `appCaption` = `brand.caption.light` (or "Powered by AI" if not specified)
- `appCaptionDark` = `brand.caption.dark` (or same as light if not specified)
**Note:** The welcome message (`brand.welcomeMessage`) is used in `chat_home_page.dart` via the app name constants. Updating `appName` and `appNameDark` will automatically update the welcome message format: "Welcome to {appName}!"
## Step 5: Implement Animation Effects
Based on `animation.style` from config, create or update animation widgets.
### CRITICAL: Follow Existing Codebase Patterns
All effects MUST follow these patterns from the existing codebase:
#### Pattern 1: Theme Brightness Detection
```dart
final isDark = Theme.of(context).brightness == Brightness.dark;
```
#### Pattern 2: AppColors Extension Access
```dart
final appColors = Theme.of(context).extension<AppColorsExtension>()!;
final colorScheme = Theme.of(context).colorScheme;
```
#### Pattern 3: Dynamic Color Selection (from speech_to_text_widget.dart)
```dart
List<Color> _buildGlowColors() {
final isDark = Theme.of(context).brightness == Brightness.dark;
final appColors = context.appColors;
if (isDark) {
return isActive
? [
colorScheme.primary.withOpacity(0.8),
colorScheme.secondary.withOpacity(0.6),
appColors.accent.withOpacity(0.4),
]
: [
appColors.mutedForeground.withOpacity(0.3),
appColors.mutedForeground.withOpacity(0.2),
];
}
// Light theme with reduced intensity...
}
```
#### Pattern 4: Use AppConstants for Animation Values
Reference: `lib/core/constants/app_constants.dart`
```dart
static const Duration glowAnimationDuration = Duration(milliseconds: 2000);
static const double glowBorderSize = 2.0;
static const double speechGlowSizeListening = 12.0;
static const double speechGlowSizeIdle = 6.0;
```
#### Pattern 5: Existing Packages to Use
- **glowy_borders** - `AnimatedGradientBorder` for neon glow effects
- **flutter_animate** - `.animate().fadeIn().scale().shimmer()` chains
- **CustomPainter** - For particle/starfield effects (see `particles_widget.dart`)
- **AnimationController + AnimatedBuilder** - For wave/pulse effects
#### Pattern 6: Particles Widget Reference
See `lib/shared/widgets/particles_widget.dart` for starfield implementation:
```dart
ParticlesWidget(
quantity: 50,
color: appColors.primary, // Theme-aware
staticity: 50,
size: 0.4,
)
```
### Effect Implementation Patterns
Reference: https://github.com/flutterfx/flutterfx_widgets
#### cosmic style
Create `lib/shared/widgets/effects/cosmic_background.dart`:
- Animated starfield using CustomPainter
- Subtle parallax on mouse/touch movement
- Use `flutter_animate` for particle fade effects
#### neon style
Create `lib/shared/widgets/effects/border_beams.dart`:
- Animated gradient border using `glowy_borders` package
- Pulsing glow effect synced with primary color
- Use config primary color for the beam color
#### minimal style
- No new widgets needed
- Ensure existing `BlurFade` transitions are subtle (duration: 200ms, blur: 2.0)
#### professional style
Create `lib/shared/widgets/effects/fancy_card.dart`:
- Elevated card with subtle shadow animation
- Hover state with slight scale and shadow increase
- Clean, understated motion
#### playful style
Create `lib/shared/widgets/effects/particle_burst.dart`:
- Confetti/particle effect on interactions
- Use chart colors from config for particle variety
- Bouncy spring animations
### Effect File Structure
```
lib/shared/widgets/effects/
├── cosmic_background.dart # For cosmic style
├── border_beams.dart # For neon style
├── fancy_card.dart # For professional style
├── particle_burst.dart # For playful style
└── effects_provider.dart # Exports based on active style
```
### effects_provider.dart Template
```dart
import 'package:flutter/material.dart';
enum AnimationStyle { cosmic, neon, minimal, professional, playful }
// Current active style from config
const AnimationStyle activeStyle = AnimationStyle.[CONFIG_STYLE];
class EffectsProvider {
static Widget wrapWithBackground(Widget child) {
switch (activeStyle) {
case AnimationStyle.cosmic:
return CosmicBackground(child: child);
case AnimationStyle.neon:
return BorderBeamsBackground(child: child);
case AnimationStyle.professional:
return FancyCardBackground(child: child);
case AnimationStyle.playful:
return FlickeringGridBackground(child: child);
case AnimationStyle.minimal:
default:
return child;
}
}
static Widget wrapWithLoadingEffect(Widget child) {
// Similar switch for loading indicators
}
}
```
## Step 6: Verify Build
After making all changes:
1. Run `flutter analyze` to check for errors
2. Run `flutter build web --wasm` to verify build succeeds
3. Report any issues found
**IMPORTANT:** If testing via the backend server (http://localhost:8000):
- The server serves static files from `build/web`
- After rebuilding, **restart the server** to serve the new build
- Kill existing server: `lsof -ti :8000 | xargs kill -9`
- Start fresh: `cd backend && uv run python app.py`
## Output Summary
After applying theme, display:
```
Theme applied successfully!
Updated files:
- lib/core/theme/app_colors.dart (colors + logos)
- lib/core/theme/gradients.dart (gradient variations)
- lib/core/constants/app_constants.dart (app name + caption)
- lib/shared/widgets/effects/ (animation widgets)
Brand applied:
- App Name: [NAME]
- Caption: [CAPTION]
- Welcome: [WELCOME_MESSAGE]
Colors applied:
- Primary: [HEX]
- Secondary: [HEX]
- Accent: [HEX]
Animation style: [STYLE]
Next steps:
- Run `flutter build web --wasm` to rebuild
- Restart the backend server to serve the new build
- Test the app at http://localhost:8000
```
## Rollback
If issues occur, the skill should:
1. Keep original files backed up (git handles this)
2. Provide instructions to revert: `git checkout -- lib/core/theme/`
## File Modification Checklist
Before completing, verify these files were updated:
- [ ] `lib/core/theme/app_colors.dart` - Color constants and logo paths
- [ ] `lib/core/theme/gradients.dart` - Gradient definitions
- [ ] `lib/core/constants/app_constants.dart` - App name, caption, welcome message
- [ ] `lib/shared/widgets/effects/` - Animation effect widgets (if style != minimal)
- [ ] Verify `flutter analyze` passes
- [ ] Commit changes with descriptive message
## Error Handling
**Config file not found:**
```
theme_config.json not found at assets/config/theme_config.json
Run /brand-theme first to generate the configuration.
```
**Invalid color format:**
```
Invalid color "[value]" in config. Expected hex format like #FF5F46.
Please fix the config file or run /brand-theme again.
```
**Build fails after changes:**
```
Build failed after applying theme. Errors:
[error details]
You can revert changes with: git checkout -- lib/core/theme/
Then review the config and try again.
```
Imported from the listed AgentSkill.sh category. Complete supplied package files and notices are retained. Required external tools and credentials are not installed. No bundled code was executed during import. Individual agent task behavior has not been tested.