Skip to content

Create a generator theme for zero password manager #59

Description

@SoulNaturalist

Feature: Theme Generator with background picker + custom color palette sync (Flutter + FastAPI)

Summary

Add a custom theme generator for Zero Password Manager that allows the user to:

  • choose a background image from assets/images/backgrounds/
  • choose the main background color
  • choose colors for buttons
  • choose colors for inputs
  • preview the result live
  • save the generated theme locally
  • optionally sync the custom theme to the backend so the same theme is available across devices

This should extend the current theme system instead of replacing it.


Context

The project already has:

  • a Flutter theme layer with AppTheme, BaseTheme, and ThemeManager
  • built-in themes: dark, cyberpunk, glassmorphism
  • local persistence for theme selection through SharedPreferences
  • background assets declared in pubspec.yaml
  • a FastAPI backend in server/

That makes it reasonable to implement a user-defined theme as the next step.


Problem

Right now users can only switch between a fixed set of predefined themes.

We need a flexible theme generator where the user can configure:

  1. background image from bundled assets
  2. main background color
  3. button color palette
  4. input color palette

The current theme model is static and enum-based, so it does not support dynamic user-created themes or sync between devices.


Proposed solution

Introduce a Custom Theme mode with a generator UI in Flutter and optional persistence/sync through FastAPI.

User flow

In Settings → Appearance / Theme:

  • user selects Custom theme

  • user opens Theme Generator

  • user picks:

    • background image from assets/images/backgrounds/
    • primary background color
    • button color
    • button text color
    • input background color
    • input border / accent color
    • input text color
  • user sees live preview

  • user clicks:

    • Save locally
    • Reset to default
    • Sync to account (if backend is enabled)

Scope

Flutter frontend

1. Add dynamic theme model

Create a new serializable model, for example:

class CustomThemeConfig {
  final String? backgroundAsset;
  final String backgroundColor;
  final String buttonColor;
  final String buttonTextColor;
  final String inputColor;
  final String inputBorderColor;
  final String inputTextColor;
  final String accentColor;
  final String surfaceColor;
  final bool useBackgroundImage;
}

Hex format example: #1A142E

2. Extend theme system

Refactor current theme layer so UI can work with:

  • predefined themes
  • custom theme generated from CustomThemeConfig

Possible direction:

  • keep existing AppTheme enum for built-ins
  • add AppTheme.custom
  • create CustomTheme extends BaseTheme
  • build CustomTheme from CustomThemeConfig

3. Add Theme Generator screen

New screen/dialog in Flutter:

  • background picker from asset directory

  • color pickers for:

    • app background
    • buttons
    • inputs
    • accents
  • preview cards for:

    • button
    • input
    • password card
    • settings tile
  • validation for contrast/readability

4. Local persistence

Save generated config locally, for example in SharedPreferences:

  • app_theme = custom
  • custom_theme_config = {json}

5. Apply theme globally

On app startup:

  • load built-in theme as now
  • if selected theme is custom, load local config and instantiate dynamic theme

6. Background rendering

Background image should be optional.

Expected behavior:

  • if image is selected, render it under overlay/surface layer
  • if image is not selected, use solid color / gradient
  • UI must remain readable with dark overlay if needed

7. Preview-safe contrast rules

Add simple guards:

  • minimum contrast for text on buttons
  • minimum contrast for text on inputs
  • fallback to white/black text when selected colors are too close

FastAPI backend

Backend is optional for first milestone, but should be included in the design.

1. Add theme storage model

Create per-user custom theme storage.

Possible DB model:

class UserTheme(Base):
    __tablename__ = "user_themes"

    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey("users.id"), unique=True, nullable=False)
    background_asset = Column(String, nullable=True)
    background_color = Column(String, nullable=False)
    button_color = Column(String, nullable=False)
    button_text_color = Column(String, nullable=False)
    input_color = Column(String, nullable=False)
    input_border_color = Column(String, nullable=False)
    input_text_color = Column(String, nullable=False)
    accent_color = Column(String, nullable=False)
    surface_color = Column(String, nullable=False)
    use_background_image = Column(Boolean, default=False, nullable=False)
    updated_at = Column(DateTime, nullable=False)

2. Add API schema

Pydantic request/response schemas for custom theme config.

3. Add endpoints

Suggested endpoints:

  • GET /theme
  • PUT /theme
  • DELETE /theme

Behavior:

  • GET returns current user custom theme
  • PUT creates/updates current user custom theme
  • DELETE clears synced custom theme

4. Validation

Backend should validate:

  • hex color format
  • background_asset only from allowed bundled asset list
  • payload completeness
  • authenticated user ownership

5. Sync behavior

Flutter flow:

  • save locally first
  • if authenticated and sync is enabled, push config to backend
  • on login/app start, optionally pull backend theme and merge with local state

Conflict strategy for MVP:

  • server wins only if user explicitly chooses “restore from account”
  • otherwise local config remains active

API draft

GET /theme

Response:

{
  "background_asset": "assets/images/backgrounds/bg_01.png",
  "background_color": "#1A142E",
  "button_color": "#5D52D2",
  "button_text_color": "#FFFFFF",
  "input_color": "#221937",
  "input_border_color": "#8B7ED8",
  "input_text_color": "#FFFFFF",
  "accent_color": "#8B7ED8",
  "surface_color": "#2A1F3D",
  "use_background_image": true,
  "updated_at": "2026-04-20T12:00:00Z"
}

PUT /theme

Request:

{
  "background_asset": "assets/images/backgrounds/bg_01.png",
  "background_color": "#1A142E",
  "button_color": "#5D52D2",
  "button_text_color": "#FFFFFF",
  "input_color": "#221937",
  "input_border_color": "#8B7ED8",
  "input_text_color": "#FFFFFF",
  "accent_color": "#8B7ED8",
  "surface_color": "#2A1F3D",
  "use_background_image": true
}

DELETE /theme

Deletes synced custom theme for current user.


Implementation notes

Flutter

Suggested files:

  • lib/models/custom_theme_config.dart
  • lib/theme/custom_theme.dart
  • lib/services/theme_service.dart
  • lib/screens/theme_generator_screen.dart

Potential refactor targets:

  • lib/theme/colors.dart
  • lib/main.dart
  • lib/screens/settings_screen.dart

FastAPI

Suggested files:

  • server/themes/router.py
  • server/themes/schemas.py
  • server/themes/crud.py
  • migration for user_themes table

Acceptance criteria

  • User can select a background image from bundled assets
  • User can set background color
  • User can set button colors
  • User can set input colors
  • User can preview the generated theme before saving
  • Custom theme is applied across the app after save
  • Custom theme persists locally after app restart
  • Backend can save and return per-user custom theme
  • Only valid asset paths and hex colors are accepted by backend
  • Reset to predefined theme works correctly
  • UI remains readable for edge-case color combinations
  • Existing built-in themes continue to work unchanged

MVP split

Phase 1

Flutter-only local custom theme:

  • generator UI
  • asset picker
  • local persistence
  • runtime apply

Phase 2

FastAPI sync:

  • DB model
  • CRUD endpoints
  • Flutter sync integration

Risks / edge cases

  • Poor contrast can make UI unreadable
  • Full-screen image backgrounds may hurt text clarity
  • Enum-based theme logic may need partial refactor
  • Sync conflicts between local and remote theme must be defined explicitly

Nice-to-have later

  • export/import theme as JSON
  • share theme presets
  • generated gradients instead of flat colors
  • blur/overlay controls for background image
  • per-theme name and thumbnails
  • multiple saved custom themes per user

Definition of done

The app supports a new Custom Theme Generator that lets the user choose a bundled background image and configure color palette for buttons, inputs, and main background, with local persistence in Flutter and optional account sync through FastAPI.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions