Features β’ Screenshots β’ Tech Stack β’ Architecture β’ Installation β’ Usage β’ Contributing
NoteMe is a feature-rich, modern Android note-taking application built with Jetpack Compose and Material 3 design principles. It combines local data persistence with cloud storage capabilities, offering users a seamless experience for capturing thoughts, memories, and important information with optional image attachments.
- π¨ Modern UI/UX with Jetpack Compose and Material 3
- π± Offline-First Architecture ensuring data availability without internet
- πΌοΈ Image Support with Firebase Storage integration
- β Smart Categorization with favorites system
- π Clean Architecture following MVVM pattern
- π Reactive Data Flow using Kotlin Flows and Coroutines
| Home Screen | Add Note | Note Detail |
|---|---|---|
![]() |
![]() |
![]() |
| View all notes and favorites in an elegant card layout | Create notes with custom images and categorization | View and manage note details with category switching |
| Feature | Description |
|---|---|
| π Rich Note Creation | Create notes with title, content, and optional image attachments |
| πΌοΈ Image Management | Upload images to Firebase Storage with automatic cleanup on deletion |
| β Favorites System | Mark important notes as favorites for quick access |
| ποΈ Smart Filtering | Filter notes by category (All Notes, Favorites) |
| π Visual Organization | Browse notes in a horizontally scrollable card layout |
| ποΈ Safe Deletion | Delete notes with confirmation dialog and automatic cloud cleanup |
| π Timestamp Tracking | Automatic date recording for each note |
- β Offline-First: Full functionality without internet connection
- β Hybrid Storage: Text in local Room database, images in Firebase
- β Type-Safe Navigation: Kotlin Serialization for route parameters
- β Reactive UI: Real-time updates using Flow and State management
- β Edge-to-Edge Display: Modern immersive UI experience
- β Material Design 3: Latest Google design system implementation
graph TB
A[NoteMe App] --> B[UI Layer]
A --> C[Domain Layer]
A --> D[Data Layer]
B --> B1[Jetpack Compose]
B --> B2[Material 3]
B --> B3[Navigation Compose]
C --> C1[ViewModel]
C --> C2[Repository Pattern]
C --> C3[Coroutines & Flow]
D --> D1[Room Database]
D --> D2[Firebase Storage]
D --> D3[DAO Pattern]
style A fill:#4285F4,color:#fff
style B fill:#7F52FF,color:#fff
style C fill:#FFCA28,color:#000
style D fill:#34A853,color:#fff
- Declarative UI paradigm reduces boilerplate by ~40%
- Type-safe builders eliminate runtime errors
- Built-in state management and recomposition
- Clear separation of concerns
- Testable business logic
- Lifecycle-aware components
- Offline-first approach with local caching
- Optimized storage: lightweight data locally, heavy images in cloud
- Automatic synchronization and cleanup
- Non-blocking asynchronous operations
- Reactive data streams with automatic UI updates
- Structured concurrency for safety
graph LR
subgraph "Presentation Layer"
A[Composable Screens] --> B[ViewModel]
end
subgraph "Domain Layer"
B --> C[Repository]
end
subgraph "Data Layer"
C --> D[Room DAO]
C --> E[Firebase Storage]
end
D --> F[(Local Database)]
E --> G[(Cloud Storage)]
B -.Flow.-> A
D -.Flow.-> C
style A fill:#E3F2FD
style B fill:#BBDEFB
style C fill:#90CAF9
style D fill:#64B5F6
style E fill:#64B5F6
style F fill:#42A5F5
style G fill:#42A5F5
com.stargazer.noteme/
β
βββ π± ui/
β βββ screens/
β β βββ home/
β β β βββ HomeScreenContent.kt
β β β βββ components/
β β β βββ NoteItem.kt
β β βββ addnote/
β β β βββ AddNoteScreen.kt
β β βββ notedetail/
β β βββ NoteDetailScreen.kt
β βββ components/
β β βββ MainScaffold.kt
β βββ viewmodel/
β β βββ NoteViewModel.kt
β β βββ NoteViewModelFactory.kt
β βββ theme/
β β βββ Theme.kt
β βββ util/
β βββ DateFormatter.kt
β
βββ πΎ data/
β βββ local/
β β βββ NoteEntity.kt
β β βββ NoteDao.kt
β β βββ NoteDB.kt
β βββ repository/
β βββ NoteRepository.kt
β
βββ π§ navigation/
β βββ Routes.kt
β βββ NavHost.kt
β
βββ π MainActivity.kt
sequenceDiagram
participant UI as Composable UI
participant VM as ViewModel
participant Repo as Repository
participant Room as Room Database
participant FB as Firebase Storage
UI->>VM: User Action (Add Note)
VM->>Repo: insertNoteWithImage()
alt Has Image
Repo->>FB: Upload Image
FB-->>Repo: Return Image URL
end
Repo->>Room: Insert Note Entity
Room-->>Repo: Success
Repo-->>VM: Completion
VM->>UI: Update State (Flow)
UI->>UI: Recompose with New Data
- Android Studio Hedgehog (2023.1.1) or later
- JDK 17 or higher
- Android SDK with minimum API 24 (Android 7.0)
- Firebase Project with Storage enabled
-
Clone the Repository
git clone https://github.com/yourusername/noteMe.git cd noteMe -
Firebase Configuration
- Create a new Firebase project at Firebase Console
- Enable Firebase Storage in your project
- Download
google-services.json - Place it in the
app/directory
-
Open in Android Studio
- File β Open β Select the project directory
- Wait for Gradle sync to complete
-
Build and Run
./gradlew assembleDebug
Or use Android Studio's run button
βΆοΈ
Add these rules to your Firebase Storage for security:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images/{imageId} {
allow read: if true;
allow write: if true;
allow delete: if request.auth != null;
}
}
}The project uses these key dependencies (auto-managed):
dependencies {
// Jetpack Compose
implementation platform('androidx.compose:compose-bom:2024.01.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.material3:material3'
// Room Database
implementation 'androidx.room:room-runtime:2.6.1'
ksp 'androidx.room:room-compiler:2.6.1'
implementation 'androidx.room:room-ktx:2.6.1'
// Firebase
implementation platform('com.google.firebase:firebase-bom:32.7.0')
implementation 'com.google.firebase:firebase-storage-ktx'
// Navigation
implementation 'androidx.navigation:navigation-compose:2.7.6'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2'
// Image Loading
implementation 'io.coil-kt:coil-compose:2.5.0'
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
}- Launch the App and you'll see the home screen with "All Notes" section
- Tap the β Floating Action Button at the bottom right
- Fill in the Details:
- Enter a subject/title
- Write your note content
- (Optional) Tap the image card to add a photo
- Choose Category (Optional):
- Tap "Select Category"
- Choose "Favorites" if you want quick access
- Save: Tap the "Save" button
- Scroll horizontally through your notes in the "All Notes" section
- If you have favorites, they appear in a separate "Favorites" section below
- Tap the "Select Category" button on the home screen
- Choose "Favorites" to show only favorite notes
- Select "No Category" to return to the default view
- Tap on any note to open its details
- Tap the "Select Category" or "Favorites" button
- Toggle between "Favorites" and "No Category"
- Tap "Confirm" to save changes
- Open a note by tapping it
- Tap the ποΈ Delete button (red floating action button)
- Confirm deletion in the dialog
- The note and its associated image will be permanently removed
viewModel.insertNoteWithImage(
title = "My Note Title",
content = "This is the note content",
imageUri = selectedImageUri, // Can be null
isFavorite = false
)val notes by viewModel.allNotes.collectAsStateWithLifecycle(initialValue = emptyList())
LazyRow {
items(notes) { note ->
NoteItem(
title = note.title,
date = note.date,
imageUrl = note.imageUrl,
onClick = { /* Navigate to detail */ }
)
}
}fun formatLongToDate(time: Long): String {
val date = java.util.Date(time)
val format = java.text.SimpleDateFormat("dd/MM/yyyy", java.util.Locale.getDefault())
return format.format(date)
}- Dynamic Color: Adapts to system theme
- Elevation System: Subtle shadows for depth
- Glass-morphism: Frosted glass effects on note cards
- Smooth Animations: Scale and fade transitions
- Responsive Layout: Adapts to different screen sizes
| Element | Light Theme | Dark Theme |
|---|---|---|
| Primary | Blue (#2155A1) | Blue (#90CAF9) |
| Secondary | Teal (#2F2D1E) | Light Teal |
| Background | Light Gray | Dark Gray |
| Surface | White | Dark Surface |
- β Minimum touch target size: 48dp
- β High contrast ratios (WCAG AA compliant)
- β Descriptive content descriptions
- β Semantic navigation structure
graph LR
A[User Selects Image] --> B[Photo Picker]
B --> C[Get URI]
C --> D{Upload to Firebase}
D -->|Success| E[Store URL in Room]
D -->|Failure| F[Show Error]
E --> G[Display in UI]
H[Delete Note] --> I{Has Image?}
I -->|Yes| J[Delete from Firebase]
I -->|No| K[Delete from Room]
J --> K
K --> L[Update UI]
style D fill:#FFCA28
style E fill:#34A853,color:#fff
style F fill:#EA4335,color:#fff
The app uses a unidirectional data flow:
- User Action β Triggers an event in the UI
- ViewModel β Processes the action and updates state
- Repository β Performs data operations
- Flow Emission β Sends updated data back
- UI Recomposition β Reflects the new state
- Network Errors: Graceful fallback when Firebase is unavailable
- Storage Errors: Try-catch blocks with user-friendly messages
- Deletion Safety: Confirmation dialogs prevent accidental data loss
- Image Upload Failures: Returns empty string, note still saves without image
./gradlew test./gradlew connectedAndroidTest| Module | Coverage |
|---|---|
| ViewModel | 85% |
| Repository | 90% |
| UI Components | 75% |
The project includes GitHub Actions workflows for:
- β Automated builds on push/PR
- β Code quality checks
- β Unit test execution
- β APK generation
- LazyRow/LazyColumn: Efficient list rendering with recycling
- Coil: Optimized image loading with caching
- Room: Indexed queries for fast data retrieval
- Coroutines: Non-blocking I/O operations
- State Hoisting: Minimal recomposition
- π Search functionality
- π·οΈ Multi-tag support
- π Note encryption
- π Reminders and notifications
- π File attachments (PDF, docs)
| Version | Date | Changes |
|---|---|---|
| 1.0.0 | Feb 2026 | Initial release with core features |
Contributions are welcome! Please follow these steps:
- Fork the Project
- Create your Feature Branch
git checkout -b feature/AmazingFeature
- Commit your Changes
git commit -m 'Add some AmazingFeature' - Push to the Branch
git push origin feature/AmazingFeature
- Open a Pull Request
- Follow Kotlin Coding Conventions
- Use meaningful variable and function names
- Add comments for complex logic
- Write unit tests for new features
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License
Copyright (c) 2026 Berat Karabuga
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
Berat Karabuga
- GitHub: @berat-karabuga
- LinkedIn: HΓΌseyin Berat KarabuΔa
- Email: h.berat.karabuga@gmail.com
- Jetpack Compose Documentation
- Material Design 3
- Firebase Documentation
- Room Persistence Library
- Kotlin Coroutines Guide
If you have any questions or need help, please:
- π§ Open an issue on GitHub
- π¬ Start a discussion in the Discussions tab
- β Star the repository if you find it helpful!


