← Back to Blog

Building Spending Smarter: A .NET MAUI Journey to the App Store

Michael Mallit
December 3, 2025
10 min read
Building Spending Smarter: A .NET MAUI Journey to the App Store

The story of building and launching Spending Smarter, an iOS expense tracking app built with .NET MAUI. Learn about the development process, technical challenges, and lessons learned shipping a cross-platform mobile app to the Apple App Store.

From Idea to App Store: Building Spending Smarter

Today I'm excited to share the journey of building and launching Spending Smarter, an intelligent expense tracking application for iOS. This project represents a complete end-to-end development experience using .NET MAUI, from initial concept to a polished app available on the Apple App Store.

As developers, we often build products for clients or contribute to large codebases where we only see a slice of the full development lifecycle. Building Spending Smarter from scratch gave me the opportunity to experience every phase—architecture decisions, UI/UX design, data modeling, deployment, and App Store submission. Here's what I learned along the way.

Why .NET MAUI for a Mobile App?

The choice of .NET MAUI (Multi-platform App UI) for this project was deliberate. While I initially planned to launch on iOS only, I wanted the flexibility to expand to Android in the future without rewriting the entire application. .NET MAUI's single codebase approach made this possible.

Key Benefits I Experienced

  • Familiar C# ecosystem – Leveraging my existing .NET expertise meant faster development and fewer context switches
  • XAML for UI – Declarative UI markup that's both powerful and maintainable
  • Native performance – Compiled to native code, resulting in smooth animations and responsive interactions
  • Shared business logic – All expense calculations, data access, and business rules written once
  • Strong typing – Catching errors at compile-time rather than discovering them in production

While .NET MAUI is still maturing compared to native Swift/SwiftUI development, the productivity gains from code reuse and familiar tooling made it an excellent choice for this project.

The Application Architecture

Spending Smarter is built on a clean architecture pattern that separates concerns and makes the codebase maintainable as it grows.

Data Layer: SQL Azure for Cloud Storage

User financial data is sensitive and valuable. I chose SQL Azure as the backend database to provide a robust, scalable cloud solution with several key advantages:

  • Cloud Sync – Data automatically syncs across devices, allowing users to access their financial data from multiple devices
  • Secure Backup – Data is securely stored in Azure with enterprise-grade encryption and automatic backups
  • Scalability – SQL Azure easily handles growing datasets as users accumulate expense history
  • Cross-device Access – Users can seamlessly switch between devices without losing their data
  • Offline Support – Local caching ensures the app works even without connectivity, syncing when back online

I used Entity Framework Core with SQL Azure for database access, providing a powerful ORM with full LINQ support and Azure integration:

public class ExpenseRepository
{
    private readonly ApplicationDbContext _context;
    private readonly IConnectivity _connectivity;

    public async Task> GetExpensesByDateRangeAsync(
        DateTime startDate, DateTime endDate)
    {
        return await _context.Expenses
            .Where(e => e.Date >= startDate && e.Date <= endDate)
            .OrderByDescending(e => e.Date)
            .ToListAsync();
    }

    public async Task GetTotalSpendingAsync(
        string category, DateTime month)
    {
        var expenses = await _context.Expenses
            .Where(e => e.Category == category 
                && e.Date.Month == month.Month 
                && e.Date.Year == month.Year)
            .ToListAsync();
        
        return expenses.Sum(e => e.Amount);
    }
}

Business Logic: Services and ViewModels

The app follows an MVVM (Model-View-ViewModel) pattern, which MAUI supports naturally through data binding. Each screen has a corresponding ViewModel that handles user interactions and exposes data to the view:

public class ExpenseListViewModel : BaseViewModel
{
    private readonly IExpenseRepository _repository;
    private readonly ICategoryService _categoryService;
    
    public ObservableCollection GroupedExpenses { get; }
    
    public ICommand AddExpenseCommand { get; }
    public ICommand FilterCommand { get; }
    public ICommand DeleteExpenseCommand { get; }

    public async Task LoadExpensesAsync()
    {
        IsBusy = true;
        try
        {
            var expenses = await _repository.GetExpensesByDateRangeAsync(
                SelectedStartDate, SelectedEndDate);
            
            GroupedExpenses.Clear();
            var grouped = expenses
                .GroupBy(e => e.Date.Date)
                .OrderByDescending(g => g.Key);
            
            foreach (var group in grouped)
            {
                GroupedExpenses.Add(new ExpenseGroup(group.Key, group));
            }
        }
        finally
        {
            IsBusy = false;
        }
    }
}

UI Layer: XAML and Custom Controls

The user interface is built with XAML, leveraging MAUI's rich set of controls and layouts. I created several custom controls to achieve the polished look and feel I wanted:

  • CategoryPicker – A custom control for selecting expense categories with icons and colors
  • DateRangeSelector – Quick date range selection (this week, this month, custom range)
  • SpendingChart – Visual representation of spending by category using SkiaSharp for custom drawing
  • BudgetProgressBar – Animated progress indicator showing budget utilization

Key Features That Make Spending Smarter Useful

Smart Categorization

Expenses are automatically suggested categories based on merchant names and previous patterns. Users can also create custom categories with personalized icons and colors to match their spending habits.

Budget Tracking

Set monthly budgets for each category and get real-time visibility into spending. The app provides clear visual feedback when approaching or exceeding budget limits, helping users stay on track.

Insightful Analytics

The analytics screen provides valuable insights:

  • Spending trends over time
  • Category breakdown with percentages
  • Month-over-month comparisons
  • Top spending categories
  • Average daily spending

All analytics are calculated using efficient LINQ queries against SQL Azure, with intelligent caching to ensure fast performance even with large datasets.

Export and Backup

Users can export their expense data to CSV format for use in spreadsheets or accounting software. The export functionality uses MAUI's file system access APIs:

public async Task ExportToCsvAsync(List expenses)
{
    var csv = new StringBuilder();
    csv.AppendLine("Date,Category,Amount,Description,Payment Method");
    
    foreach (var expense in expenses)
    {
        csv.AppendLine($"{expense.Date:yyyy-MM-dd}," +
            $"{expense.Category},{expense.Amount:F2}," +
            $"\"{expense.Description}\",{expense.PaymentMethod}");
    }
    
    var filename = $"SpendingSmarter_Export_{DateTime.Now:yyyyMMdd}.csv";
    var path = Path.Combine(FileSystem.CacheDirectory, filename);
    
    await File.WriteAllTextAsync(path, csv.ToString());
    await Share.RequestAsync(new ShareFileRequest
    {
        Title = "Export Expenses",
        File = new ShareFile(path)
    });
}

Technical Challenges and Solutions

Challenge 1: iOS-Specific UI Patterns

While MAUI provides cross-platform UI components, iOS has specific design patterns and user expectations. I needed to ensure the app felt native to iOS users:

Solution: Used platform-specific styling and behaviors through MAUI's conditional compilation and platform-specific code:

#if IOS
    // Use iOS-specific navigation patterns
    await Navigation.PushModalAsync(detailPage);
#else
    await Navigation.PushAsync(detailPage);
#endif

Challenge 2: Performance with Large Datasets

As users accumulate hundreds or thousands of expense records, list performance became critical.

Solution: Implemented virtualization using CollectionView, database indexing, and pagination:

CREATE INDEX idx_expense_date ON Expenses(Date DESC);
CREATE INDEX idx_expense_category ON Expenses(Category);

Challenge 3: Date and Currency Handling

Different regions have different date formats and currency conventions.

Solution: Used .NET's built-in CultureInfo and IFormatProvider to respect user locale settings:

public string FormatCurrency(decimal amount)
{
    var culture = CultureInfo.CurrentCulture;
    return amount.ToString("C", culture);
}

Challenge 4: App Store Submission

Navigating Apple's App Store review process required attention to privacy policies, data handling disclosures, and UI guidelines.

Solution: Created comprehensive privacy policy, ensured all required app metadata was accurate, and thoroughly tested on physical iOS devices before submission. The app was approved on the first submission.

The App Store Launch Process

Shipping to the App Store involves several steps beyond just building the app:

  1. Apple Developer Account – Enrolled in the Apple Developer Program ($99/year)
  2. App Store Connect setup – Created app listing, uploaded screenshots, wrote description
  3. Privacy policy – Documented cloud data handling practices, encryption, and Azure security measures
  4. Archive and upload – Built release archive in Visual Studio for Mac, uploaded via Transporter
  5. TestFlight beta – Ran a brief beta test with friends to catch any last issues
  6. App Review submission – Submitted for review with detailed testing instructions
  7. Approval and release – Approved within 24 hours, released to the App Store

Lessons Learned

1. Start Simple, Iterate Based on Usage

My initial feature list was ambitious. I scaled back to core functionality for v1.0 and planned additional features based on actual user feedback. This got the app to market faster and ensured I was building features people actually wanted.

2. Physical Device Testing is Essential

The iOS simulator is useful, but nothing replaces testing on actual devices. Touch interactions, performance, and visual polish all need real device validation.

3. .NET MAUI is Production-Ready

Despite some rough edges in tooling and occasional platform-specific quirks, .NET MAUI delivered a high-quality native iOS app. The framework is mature enough for serious production use.

4. Cloud-First Architecture Enables Premium Features

Choosing SQL Azure as the backend enabled powerful features like cross-device sync and automatic backups. While it added complexity around authentication and data synchronization, the Azure ecosystem provided robust, scalable solutions that enhanced the user experience significantly.

5. The App Store Review is Fair

Apple's review process gets a bad reputation, but I found it straightforward. Clear guidelines, reasonable requirements, and helpful feedback when needed.

What's Next for Spending Smarter?

Now that v1.0 is live with SQL Azure cloud sync, I'm gathering user feedback and planning the roadmap:

  • Recurring expense support – Automatically track subscriptions and regular bills
  • Receipt scanning – Use OCR to extract amount and merchant from receipt photos
  • Widget support – Quick expense entry from the home screen
  • Enhanced analytics – More detailed spending insights and predictions using Azure AI services
  • Android version – Leverage the MAUI codebase to launch on Google Play with same cloud sync
  • Family sharing – Share expense tracking across family members with role-based permissions

Try Spending Smarter

If you're an iOS user looking for a straightforward, privacy-focused expense tracker, I'd love for you to try Spending Smarter. The app is free to download and use—no subscriptions, no ads, just a useful tool for managing your spending.

For Developers: The .NET MAUI Opportunity

Building Spending Smarter reinforced my belief that .NET MAUI is an excellent choice for cross-platform mobile development, especially for developers already in the .NET ecosystem. The ability to leverage existing C# skills, share code across platforms, and still deliver native-quality apps is genuinely powerful.

If you're considering .NET MAUI for your next mobile project, or if you need help building a cross-platform app, the team at MallitLabs has deep expertise in .NET MAUI development. We can help you navigate the technical decisions, avoid common pitfalls, and ship high-quality mobile applications that your users will love.

Building and launching your own app is an incredibly rewarding experience. I hope sharing this journey inspires you to build and ship your own ideas.

Ready to start your project?

Let's discuss how MallitLabs can help bring your vision to life.