Files
Clario/CLAUDE.md
Nouredeen06 d8dea1913a
All checks were successful
Build Linux / build (push) Successful in 1m8s
Added multi-currency support, account/budget management, and settings
- Primary account determines app-wide reference currency; all totals, charts, and summaries convert to it automatically using live rates

- Transactions show both converted and original amounts for cross-currency accounts; IsMultiCurrency recalculates on primary currency change

- Exchange rates fetched live on account save and broadcast via RatesRefreshed so all views update without a restart

- Account create/edit/delete with currency, icon, color, and primary toggle

- Budget create/edit/delete; savings goal dialog

- Settings view: display name, avatar upload, theme, language

- Removed currency selector from Settings (follows primary account)

- Fixed account list sort: primary first, then oldest CreatedAt, per group

- Fixed total balance overlap in dashboard accounts card
2026-04-03 02:39:51 +03:00

6.2 KiB

Clario — Claude Code Instructions

Clario is a cross-platform personal finance tracking app. See @NEW_CHAT_CONTEXT.md for full project context before starting any task.


Tech Stack

  • UI: Avalonia UI XPlat (.NET 9), CommunityToolkit.MVVM
  • Backend: Supabase (PostgreSQL, Auth, RLS, Realtime)
  • Charts: LiveCharts2 (SkiaSharp)
  • IDE: JetBrains Rider, Windows dev machine (Arabic region — always use en-US CultureInfo)

Project Structure

Clario/                  ← shared (ViewModels, Models, Services, Data, CustomControls, Behaviors, Converters)
Clario.Desktop/          ← Windows/macOS/Linux entry point
Clario.Android/          ← Android entry point
Views/                   ← desktop AXAML views only
MobileViews/             ← mobile AXAML views only

Build & Run

# Desktop
dotnet run --project Clario.Desktop

# Android (requires connected device or emulator)
dotnet build Clario.Android -c Release

# Verify build
dotnet build Clario.sln

Platform Detection

// Always check this before any platform-specific logic
App.IsMobile  // true on Android/iOS, false on desktop

CRITICAL RULES — Read before every task

AXAML Rules

  • ALWAYS use {DynamicResource} for theme colors, never hardcode hex
  • NEVER put DataTemplates in AXAML — ViewLocator handles all view resolution
  • NEVER add MinWidth/MinHeight to UserControl in mobile views
  • NEVER use BoxShadow in mobile views
  • Use x:CompileBindings="False" on shell views with dynamic DataContext
  • Desktop views go in Views/, mobile views go in MobileViews/ named {Name}ViewMobile.axaml
  • Icon background opacity always: <SolidColorBrush Color="..." Opacity="0.15"/>
  • Separator between list items: Spacing="1" on StackPanel + BorderSubtle background on container

ViewModel Rules

  • NEVER fetch data in child ViewModel constructors
  • NEVER trigger initialization from partial void On{Property}Changed when VM depends on multiple properties
  • Call Initialize() explicitly after object initializer sets all required fields
  • Child VMs have public required ViewModelBase parentViewModel
  • Replace lists entirely to trigger bindings — never mutate and expect updates

C# Rules

  • Always en-US CultureInfo for dates/numbers (Windows has Arabic region)
  • Use Task.WhenAll for parallel async fetches in InitializeApp
  • Use _ = SomeAsyncMethod() for fire-and-forget with try/catch inside the method
  • Wrap fire-and-forget in try/catch — exceptions are silently swallowed

Style Classes

accented   → primary action button (AccentBlue bg)
base       → secondary action button
nav        → transparent navigation/toggle button
danger     → destructive action (DangerButtonBackground + AccentRed text)
ghost      → transparent TextBox (no border, any state)
label      → uppercase muted TextBlock label
muted      → TextMuted foreground
mobile     → root class on mobile views (enables mobile overrides)

Design Tokens (quick reference)

BgBase/BgSurface/BgSidebar/BgHover
BorderSubtle/BorderAccent
TextPrimary/TextSecondary/TextMuted/TextDisabled
AccentBlue/AccentGreen/AccentYellow/AccentRed/AccentPurple/AccentOrange/AccentPink
IconBgBlue/IconBgGreen/IconBgRed/IconBgOrange/IconBgPurple/IconBgPink
BadgeBgRed/BadgeBgYellow/BadgeBgGreen/BadgeBgBlue
DangerButtonBackground/DangerButtonBorder
SvgPrimary/SvgSecondary/SvgMuted/SvgDisabled/SvgBlue/SvgGreen/SvgYellow/SvgRed

SVG Pattern

<Svg Path="../Assets/Icons/icon-name.svg" Width="16" Height="16" Css="{DynamicResource SvgBlue}"/>

Converters (quick reference)

Key Usage
HexToColorConverter ConverterParameter=color/css/brush
AmountColorConverter type string → AccentRed/Green brush
AmountSignConverter MultiBinding(amount, type) → +$x.xx
BoolToColorConverter ConverterParameter='#hex1|#hex2'
BoolToCssConverter ConverterParameter='#hex1|#hex2' → SVG CSS
SvgPathFromName "icon-name""../Assets/Icons/icon-name.svg"
DateFormatConverter DateTime → string (always en-US)
EqualValueConverter MultiBinding equality → bool
NetworthSumConverter MultiBinding(income, expenses) → net
PercentageConverter MultiBinding(value, total) → %

Flyout Pattern

<Button.Flyout>
    <Flyout Placement="BottomEdgeAlignedRight"
            FlyoutPresenterTheme="{StaticResource TransparentFlyoutPresenter}">
        <views:SomeView/>
    </Flyout>
</Button.Flyout>

Modal Overlay Pattern

<!-- In MainView content area, on top of ContentControl -->
<views:SomeFormView
    DataContext="{Binding SomeFormVM}"
    IsVisible="{Binding IsFormVisible}"/>

The view's root Grid must have <Border Background="#70000000"/> as the dim layer.

Bottom Sheet Pattern (mobile)

  • Controlled via ShowSheet() / HideSheet() public methods in code-behind
  • TranslateTransform animation: CubicEaseOut 320ms up, CubicEaseIn 260ms down
  • OverlayGrid.IsVisible = false by default in AXAML
  • Set BottomSheet.MaxHeight = Bounds.Height * 0.82 in OnAttachedToVisualTree

Supabase

// All queries via DataRepo
DataRepo.General.FetchTransactions()
DataRepo.General.FetchCategories()
DataRepo.General.FetchAccounts()
DataRepo.General.FetchBudgets()
DataRepo.General.FetchProfileInfo()
// etc.

// Auth
SupabaseService.Client.Auth.CurrentUser
SupabaseService.Client.Auth.SignIn(email, password)
SupabaseService.Client.Auth.SignOut()
SupabaseService.Client.Auth.Update(new UserAttributes { ... })

RLS: all tables enabled. INSERT uses WITH CHECK (auth.uid() = user_id).


Verification

After any code change, verify by:

  1. dotnet build Clario.sln — must have zero errors
  2. Check AXAML for {DynamicResource} on all color bindings
  3. Check that no ViewModel constructor fetches data
  4. On mobile views: no BoxShadow, no MinWidth/MinHeight, has Classes="mobile" on root

What's Not Yet Built

  • AuthViewMobile — needs creating
  • Settings view mobile version — needs creating
  • Analytics view — not designed yet
  • Light theme — token file incomplete, do not assume it's complete
  • Real-time Supabase subscriptions — not wired to UI