DevBites is a .NET MAUI app that delivers short, engaging programming concept cards in an infinite-scrolling feed.
It uses Microsoft.Extensions.AI (IChatClient) so the AI provider is swappable between Gemini and Ollama via .env config.
- Infinite scrolling AI-generated feed
- Topic filter (
.NET,Python,OOP,SOLID,Design Patterns,Data Structures) - Expertise filter (
Beginner,Medium,Advanced,Pro) - Collapsible custom header
- Reusable card and header UI components (
ContentViewcontrols) - Favorite reels (heart toggle per card)
- Persistent favorites stored locally in
SQLite - Feed/Favorites bottom tab bar UI
- AI provider switching through
.env(gemini/ollama) - Structured output enforcement using JSON schema via
IChatClientresponse format
DevBites uses an MVVM-first design that keeps UI, state, and data responsibilities separated.
FeedPagehosts the complete screen layout, including:- collapsible top header
- main content region
- loading and error status area
- bottom tab-style switch between Feed and Favorites
FeedHeaderViewis a reusable header component with topic and expertise pickers.ReelCardViewis a reusable card component used in both feed and favorites lists.
FeedViewModelmanages:- active reels and favorite reels
- selected topic and expertise
- pagination and cancellation logic
- toggling favorites
- switching between feed and favorites sections
AIContentServicerequests and parses AI-generated reels.FavoritesServicepersists saved reels in localSQLite(devbites.db3).DotEnvLoader+Constantsprovide runtime config for provider/model settings.
IChatClientabstraction keeps provider logic decoupled.- Provider is selected at startup (
geminiorollama) from.env. - JSON schema response format is applied to encourage strongly structured output.
- Represents one concept card returned by AI
- Uses
JsonPropertyNamemappings - Includes UI-only
IsFavoritestate (not serialized)
- Builds prompt using selected topic + expertise level
- Uses
IChatClient.GetResponseAsync - Enforces structured response format with JSON schema
- Parses response into
List<ProgrammingReel>
IAIContentService signature:
Task<IReadOnlyList<ProgrammingReel>> GetReelsAsync(
string topic,
string expertiseLevel,
CancellationToken cancellationToken = default);- Uses
sqlite-net-pcl - Stores favorites in local db file (
devbites.db3) - Supports toggle favorite, list favorites, and favorite-id lookup
Main state + commands:
Reels,FavoriteReelsSelectedTopic,SelectedExpertiseLevelShowFeedCommand,ShowFavoritesCommandToggleFavoriteCommandLoadInitialCommand,LoadMoreCommand- Cancellation-aware refresh when topic/expertise changes
The app loads .env from an embedded resource at startup.
Example:
AI_PROVIDER=gemini
GEMINI_API_KEY=your_key
GEMINI_MODEL=gemini-2.5-flash-lite
OLLAMA_ENDPOINT=http://localhost:11434
OLLAMA_MODEL=llama3.2- Create API key: https://aistudio.google.com/app/apikey
- Set in
.env:
AI_PROVIDER=gemini
GEMINI_API_KEY=your_key
GEMINI_MODEL=gemini-2.5-flash-lite- Install Ollama: https://ollama.com
- Pull model:
ollama pull llama3.2- Set in
.env:
AI_PROVIDER=ollama
OLLAMA_ENDPOINT=http://localhost:11434
OLLAMA_MODEL=llama3.2# 1) restore
dotnet restore
# 2) build
dotnet build
# 3) run Android
dotnet build -t:Run -f net10.0-android
# 4) run Windows
dotnet build -t:Run -f net10.0-windows10.0.19041.0| Registered as | Concrete type | Lifetime |
|---|---|---|
IChatClient |
GeminiChatClient or OllamaApiClient |
Singleton |
IAIContentService |
AIContentService |
Singleton |
IFavoritesService |
FavoritesService |
Singleton |
FeedViewModel |
FeedViewModel |
Transient |
FeedPage |
FeedPage |
Transient |
.NET 10.NET MAUICommunityToolkit.MvvmMicrosoft.Extensions.AIGeminiDotnet.Extensions.AIOllamaSharpsqlite-net-pcl