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);
#endifChallenge 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:
- Apple Developer Account – Enrolled in the Apple Developer Program ($99/year)
- App Store Connect setup – Created app listing, uploaded screenshots, wrote description
- Privacy policy – Documented cloud data handling practices, encryption, and Azure security measures
- Archive and upload – Built release archive in Visual Studio for Mac, uploaded via Transporter
- TestFlight beta – Ran a brief beta test with friends to catch any last issues
- App Review submission – Submitted for review with detailed testing instructions
- 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.

