An intelligent, AI-powered note-taking platform that automatically generates summaries, tags, and flashcards from your notes.
| Documentation | Purpose |
|---|---|
| ๐ Setup Guide | Installation & environment configuration |
| ๐ API Reference | Complete API endpoints & curl examples |
| ๐ก๏ธ Security | Authentication, best practices & configuration |
| ๐ Troubleshooting | Common issues & solutions |
| ๐ค Contributing | Development guidelines & code style |
- Overview
- Features
- Architecture
- Tech Stack
- Quick Start
- API Basics
- Testing
- Contributing
- Roadmap
- Author
NoteMind AI is a full-stack intelligent notes platform built with Spring Boot 4.0 and PostgreSQL. It goes beyond basic CRUD โ every note you create is automatically enriched by AI with a generated summary, contextual tags, and optional study flashcards.
The backend features a clean, layered architecture with JWT + refresh token authentication, Redis caching, Cloudinary-based image storage, PostgreSQL full-text search, and AI integration through both Google Gemini and OpenRouter APIs.
- ๐ค AI-first โ Summaries and tags are generated automatically on every save
- ๐ Flashcard generation โ AI creates Q&A flashcards from any note for active recall study
- โ Quiz generation โ AI creates multiple-choice quizzes with answers and explanations
- ๐ Full-text search โ PostgreSQL
tsvector/tsquerywith GIN indexing searches across titles, content, and AI summaries - ๐ Folder organization โ Organize notes into user-scoped folders
- ๐ผ๏ธ Multimodal AI โ Vision models analyze attached images alongside text content
- โก Redis caching โ Notes are cached with smart eviction on mutations
| Feature | Details |
|---|---|
| JWT Authentication | Stateless, token-based auth with HMAC-SHA signed JWTs |
| Refresh Tokens | Persistent refresh tokens with expiry & revocation support |
| Password Encryption | BCrypt hashing via Spring Security |
| Session Management | Fully stateless โ no server-side sessions |
| Access Control | Every note, folder, and flashcard is scoped to the authenticated user |
| Logout | Revokes refresh token on logout |
- Create / Read / Update / Delete notes with title, content, and optional image
- AI-generated summaries are created automatically on every create & update
- AI-generated tags are extracted and persisted as reusable entities
- Image attachments โ upload images that get stored on Cloudinary; vision-capable AI models analyze them
- Summary types โ choose between
SHORT,DETAILED, orBULLET_POINTSsummaries - Refresh summary โ regenerate the summary with a different type on demand
- Generate Q&A flashcards from any note using AI (configurable count, 1โ50)
- Regenerate โ wipe existing flashcards and generate a fresh set
- Manual CRUD โ create, update, and delete individual flashcards
- Bulk delete โ remove all flashcards for a note at once
- AI uses both text content and attached images to produce flashcards
- Generate 1โ20 multiple-choice questions from any note
- Each question includes four options, the correct answer, and an explanation
- AI uses note text and attached images as quiz sources
- Create, rename, and delete folders (unique name per user)
- Move notes into/out of folders
- Fetch folders with or without nested notes (
?includeNotes=true)
- Powered by PostgreSQL's native full-text search engine
- Uses
tsvectorcolumns withGINindexing for fast ranked results - Searches across note title, content, and AI-generated summary
- Results ranked by
ts_rankrelevance scoring
Client uploads image
โ
โผ
Cloudinary CDN
โ
โผ
Returns secure URL
โ
โผ
URL stored in PostgreSQL
- Max upload size: 10 MB
- Cloud-hosted on Cloudinary for fast CDN delivery
- Image URLs are persisted alongside the note
- Individual notes cached by ID (
@Cacheable) - Cache updated on create/update (
@CachePut) - Smart eviction on delete and folder mutations (
@CacheEvict) - Jackson-serialized values with
StringRedisSerializerkeys
The project follows a layered 3-tier architecture:
Controllers โ Services โ Repositories โ Database
โ โ
Exceptions, Security, Caching
Key components:
- Controllers - REST endpoints at
/api/v1/ - Services - Business logic & AI integration
- Repositories - JPA data access layer
- Security - JWT authentication & authorization
- Caching - Redis for performance
- External APIs - Google Gemini, OpenRouter for AI
See docs/API.md for endpoint details and docs/SECURITY.md for authentication strategy.
| Layer | Technology |
|---|---|
| Language | Java 21 |
| Framework | Spring Boot 4.0.5 |
| Security | Spring Security, JWT (jjwt 0.13.0), BCrypt |
| Data | Spring Data JPA, Hibernate |
| Database | PostgreSQL (with Full-Text Search + GIN indexes) |
| Caching | Redis + Spring Cache |
| AI | Google Gemini SDK (google-genai), OpenRouter API |
| Image Storage | Cloudinary (cloudinary-http44) |
| Mapping | MapStruct 1.5.5 |
| Utilities | Lombok, Jackson |
| Testing | JUnit 5, Spring Test, Testcontainers (PostgreSQL) |
| Build | Gradle (Kotlin DSL) |
| Android (planned) | Kotlin, Jetpack Compose |
NoteMind-AI/
โโโ android-app/ # Planned Android client
โโโ backend/
โ โโโ build.gradle.kts # Dependencies & plugins
โ โโโ settings.gradle.kts
โ โโโ src/
โ โโโ main/
โ โ โโโ java/com/dhaliwal/notemind/
โ โ โ โโโ NotemindApiApplication.java
โ โ โ โโโ config/
โ โ โ โ โโโ CloudinaryConfig.java
โ โ โ โ โโโ RedisConfig.java
โ โ โ โ โโโ RequiredBeans.java
โ โ โ โ โโโ StaticResourceConfig.java
โ โ โ โโโ controller/
โ โ โ โ โโโ AuthController.java
โ โ โ โ โโโ NoteController.java
โ โ โ โ โโโ FlashCardController.java
โ โ โ โ โโโ FolderController.java
โ โ โ โโโ dto/
โ โ โ โ โโโ NoteDto.java
โ โ โ โ โโโ AINoteResponse.java
โ โ โ โ โโโ TagDto.java
โ โ โ โ โโโ flashCard/
โ โ โ โ โโโ folder/
โ โ โ โโโ entity/
โ โ โ โ โโโ Note.java
โ โ โ โ โโโ User.java
โ โ โ โ โโโ FlashCard.java
โ โ โ โ โโโ Folder.java
โ โ โ โ โโโ Tag.java
โ โ โ โ โโโ RefreshToken.java
โ โ โ โ โโโ type/
โ โ โ โ โโโ SummaryType.java
โ โ โ โโโ exception/
โ โ โ โ โโโ GlobalExceptionHandler.java
โ โ โ โ โโโ ... (16 custom exceptions)
โ โ โ โโโ mapper/
โ โ โ โ โโโ NoteMapper.java
โ โ โ โ โโโ FlashCardMapper.java
โ โ โ โ โโโ FolderMapper.java
โ โ โ โ โโโ TagMapper.java
โ โ โ โโโ repository/
โ โ โ โ โโโ NoteRepository.java
โ โ โ โ โโโ UserRepository.java
โ โ โ โ โโโ FlashCardRepository.java
โ โ โ โ โโโ FolderRepository.java
โ โ โ โ โโโ TagRepository.java
โ โ โ โโโ security/
โ โ โ โ โโโ config/SecurityConfig.java
โ โ โ โ โโโ AuthFilter/JwtAuthFilter.java
โ โ โ โ โโโ service/AuthService.java
โ โ โ โ โโโ refresh/RefreshTokenService.java
โ โ โ โ โโโ util/SecurityUtils.java
โ โ โ โ โโโ dto/
โ โ โ โโโ service/
โ โ โ โ โโโ AIService.java
โ โ โ โ โโโ NotesService.java
โ โ โ โ โโโ FlashCardService.java
โ โ โ โ โโโ FolderService.java
โ โ โ โ โโโ ImageManagerService.java
โ โ โ โ โโโ impl/
โ โ โ โ โโโ AIServiceImpl.java
โ โ โ โ โโโ NotesServiceImpl.java
โ โ โ โ โโโ FlashCardServiceImpl.java
โ โ โ โ โโโ FolderServiceImpl.java
โ โ โ โ โโโ ImageManagerServiceImpl.java
โ โ โ โโโ util/
โ โ โ โโโ Util.java
โ โ โโโ resources/
โ โ โโโ application.properties
โ โโโ test/
โโโ README.md
Get the project running in 5 minutes:
# 1. Clone repository
git clone https://github.com/sukhmmeet/NoteMind-AI.git
cd NoteMind-AI/backend
# 2. Set environment variables (see docs/SETUP.md for details)
export DB_URL="jdbc:postgresql://localhost:5432/notemind_ai"
export JWT_SECRET_KEY="your-256-bit-secret-key"
export GOOGLE_API_KEY="AIza..."
# 3. Start services (PostgreSQL & Redis must be running)
./gradlew bootRun
# 4. Test the API
curl http://localhost:8080/api/v1/auth/signupFull setup instructions โ ๐ Setup Guide
- Step-by-step installation for all platforms
- Environment variable configuration
- Docker Compose setup
- Verification checklist
|
PUT|/notes/{id}| Update a note (multipart) | |DELETE|/notes/{id}| Delete a note | |GET|/notes/search?query=...| Full-text search across notes | |GET|/notes/refresh-summary/{id}?type=SHORT| Regenerate AI summary |
๐ Detailed Notes Examples
POST /notes โ Create a new note with AI-generated summary
# Basic note (without image)
curl -X POST http://localhost:8080/api/v1/notes \
-H "Authorization: Bearer <your-jwt-token>" \
-F 'note={"title":"Quantum Computing","content":"Quantum computers use qubits instead of bits...","summaryType":"DETAILED"};type=application/json'
# Response 201
{
"id": 1,
"title": "Quantum Computing",
"content": "Quantum computers use qubits instead of bits...",
"summary": "Quantum computing is a revolutionary computing paradigm...",
"summaryType": "DETAILED",
"tags": [
{ "id": 1, "name": "quantum-computing" },
{ "id": 2, "name": "technology" }
],
"imageUrl": null,
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z",
"folderId": null
}POST /notes (with image) โ Create a note with an image
curl -X POST http://localhost:8080/api/v1/notes \
-H "Authorization: Bearer <your-jwt-token>" \
-F 'note={"title":"Architecture Diagram","content":"This is our microservices architecture...","summaryType":"BULLET_POINTS"};type=application/json' \
-F 'image=@diagram.png'
# Response 201 (with image URL from Cloudinary)
{
"id": 2,
"title": "Architecture Diagram",
"imageUrl": "https://res.cloudinary.com/.../diagram.png",
"summary": "โข Microservices architecture\nโข API Gateway pattern\nโข Database per service",
...
}GET /notes โ Retrieve all notes (paginated)
curl -X GET "http://localhost:8080/api/v1/notes?page=0&size=10" \
-H "Authorization: Bearer <your-jwt-token>"
# Response 200
{
"content": [
{
"id": 1,
"title": "Quantum Computing",
"summary": "...",
"tags": [...],
"createdAt": "2024-01-15T10:30:00Z"
}
],
"pageable": {
"pageNumber": 0,
"pageSize": 10,
"totalElements": 42,
"totalPages": 5
}
}GET /notes/{id} โ Retrieve a specific note
curl -X GET http://localhost:8080/api/v1/notes/1 \
-H "Authorization: Bearer <your-jwt-token>"
# Response 200
{
"id": 1,
"title": "Quantum Computing",
"content": "...",
"summary": "...",
"tags": [...],
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}PUT /notes/{id} โ Update a note
curl -X PUT http://localhost:8080/api/v1/notes/1 \
-H "Authorization: Bearer <your-jwt-token>" \
-F 'note={"title":"Updated Title","content":"Updated content...","summaryType":"SHORT"};type=application/json' \
-F 'image=@new-image.jpg'
# Response 200 (with regenerated summary and tags)GET /notes/search?query=... โ Full-text search
curl -X GET "http://localhost:8080/api/v1/notes/search?query=quantum&limit=20" \
-H "Authorization: Bearer <your-jwt-token>"
# Response 200
{
"results": [
{
"id": 1,
"title": "Quantum Computing",
"summary": "...",
"relevanceScore": 0.95
}
],
"totalResults": 5
}GET /notes/refresh-summary/{id}?type=... โ Regenerate summary
# Available types: SHORT, DETAILED, BULLET_POINTS
curl -X GET "http://localhost:8080/api/v1/notes/1/refresh-summary?type=BULLET_POINTS" \
-H "Authorization: Bearer <your-jwt-token>"
# Response 200
{
"id": 1,
"summary": "โข Point 1\nโข Point 2\nโข Point 3",
"summaryType": "BULLET_POINTS"
}DELETE /notes/{id} โ Delete a note
curl -X DELETE http://localhost:8080/api/v1/notes/1 \
-H "Authorization: Bearer <your-jwt-token>"
# Response 204 (No Content)| Method | Endpoint | Description |
|---|---|---|
POST |
/notes/{noteId}/flashcards/generate?count=5 |
AI-generate flashcards from a note |
POST |
/notes/{noteId}/flashcards/regenerate?count=5 |
Delete existing & regenerate flashcards |
GET |
/notes/{noteId}/flashcards |
Get all flashcards for a note |
GET |
/flashcards/{flashCardId} |
Get a specific flashcard |
POST |
/notes/{noteId}/flashcards |
Manually create a flashcard |
PATCH |
/flashcards/{flashCardId} |
Update a flashcard |
DELETE |
/flashcards/{flashCardId} |
Delete a flashcard |
DELETE |
/notes/{noteId}/flashcards |
Delete all flashcards of a note |
๐ Detailed Flashcard Examples
POST /notes/{noteId}/flashcards/generate โ Generate flashcards from note
curl -X POST "http://localhost:8080/api/v1/notes/1/flashcards/generate?count=5" \
-H "Authorization: Bearer <your-jwt-token>"
# Response 201
{
"noteId": 1,
"flashcards": [
{
"id": 1,
"question": "What is a qubit?",
"answer": "A qubit (quantum bit) is the fundamental unit of quantum computing...",
"createdAt": "2024-01-15T10:35:00Z"
},
{
"id": 2,
"question": "How does quantum superposition work?",
"answer": "Quantum superposition allows a qubit to exist in multiple states...",
"createdAt": "2024-01-15T10:35:00Z"
}
],
"totalGenerated": 5
}GET /notes/{noteId}/flashcards โ List all flashcards for a note
curl -X GET http://localhost:8080/api/v1/notes/1/flashcards \
-H "Authorization: Bearer <your-jwt-token>"
# Response 200
{
"flashcards": [
{
"id": 1,
"question": "What is a qubit?",
"answer": "...",
"createdAt": "2024-01-15T10:35:00Z"
}
],
"totalCount": 5
}PATCH /flashcards/{flashCardId} โ Update a flashcard
curl -X PATCH http://localhost:8080/api/v1/flashcards/1 \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"question": "What is a quantum bit?",
"answer": "Updated answer with more detail..."
}'
# Response 200DELETE /notes/{noteId}/flashcards โ Delete all flashcards for a note
curl -X DELETE http://localhost:8080/api/v1/notes/1/flashcards \
-H "Authorization: Bearer <your-jwt-token>"
# Response 204 (No Content)| Method | Endpoint | Description |
|---|---|---|
POST |
/folder |
Create a folder |
GET |
/folder |
Get all folders (add ?includeNotes=true for nested notes) |
GET |
/folder/{id} |
Get folder by ID |
PATCH |
/folder/{id} |
Rename a folder |
DELETE |
/folder/{id} |
Delete a folder |
๐ Detailed Folder Examples
POST /folder โ Create a new folder
curl -X POST http://localhost:8080/api/v1/folder \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Study Notes"
}'
# Response 201
{
"id": 1,
"name": "Study Notes",
"createdAt": "2024-01-15T10:40:00Z"
}GET /folder โ Get all folders with nested notes
curl -X GET "http://localhost:8080/api/v1/folder?includeNotes=true" \
-H "Authorization: Bearer <your-jwt-token>"
# Response 200
{
"folders": [
{
"id": 1,
"name": "Study Notes",
"notes": [
{
"id": 1,
"title": "Quantum Computing",
"summary": "..."
}
],
"noteCount": 1
}
]
}PATCH /folder/{id} โ Rename a folder
curl -X PATCH http://localhost:8080/api/v1/folder/1 \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Advanced Study Notes"
}'
# Response 200DELETE /folder/{id} โ Delete a folder
curl -X DELETE http://localhost:8080/api/v1/folder/1 \
-H "Authorization: Bearer <your-jwt-token>"
# Response 204 (No Content)The project includes comprehensive test coverage using JUnit 5, Spring Test, and Testcontainers.
# Run all tests
./gradlew test
# Run a specific test class
./gradlew test --tests com.dhaliwal.notemind.controller.NoteControllerTest
# Run with coverage report
./gradlew test jacocoTestReport
# View coverage report (generated in build/reports/jacoco/test/html/index.html)src/test/java/com/dhaliwal/notemind/
โโโ controller/ # Controller integration tests
โโโ service/ # Service unit tests
โโโ repository/ # Repository tests with Testcontainers
โโโ security/ # JWT and Auth filter tests
โโโ resources/
โโโ application-test.properties
- Integration Tests: Use
@SpringBootTestwithTestcontainersfor PostgreSQL - Unit Tests: Mock dependencies using Mockito
- Security Tests: Use
@WithMockUserfor testing secured endpoints - Repository Tests: Test complex JPA queries with real database
@SpringBootTest
@Testcontainers
public class NoteControllerTest {
@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("notemind_ai_test");
@Test
void testCreateNote_shouldGenerateSummary() {
// Test implementation
}
}- L1 Cache (Redis): Individual notes cached with TTL
- Cache Invalidation: Automatic eviction on update/delete operations
- Cache Keys: Structured as
note::{id}for easy management
| Optimization | Implementation |
|---|---|
| Full-Text Search | PostgreSQL tsvector with GIN indexes |
| Query Indexing | Indexes on user_id, folder_id, created_at |
| Pagination | All list endpoints support page and size parameters |
| N+1 Prevention | JPA lazy loading with @Fetch(FetchMode.JOIN) |
-- Automatically created indexes
CREATE INDEX idx_note_user_id ON note(user_id);
CREATE INDEX idx_note_folder_id ON note(folder_id);
CREATE INDEX idx_note_search_vector ON note USING GIN(search_vector);
CREATE INDEX idx_flashcard_note_id ON flash_card(note_id);
CREATE INDEX idx_refresh_token_user_id ON refresh_token(user_id);- Use tools like JMeter or Locust
- Test with concurrent users (10, 50, 100)
- Monitor Redis memory usage and eviction rates
- Monitor PostgreSQL query performance with
pg_stat_statements
Example Load Test Command:
# Using Apache JMeter
jmeter -n -t load-test.jmx -l results.jtl -j logs.log -Jthreads=50 -Jduration=300| Practice | Implementation |
|---|---|
| Password Storage | BCrypt hashing (strength 10) |
| JWT Signing | HMAC-SHA256 with 256-bit key |
| Token Expiry | 15-minute access tokens, 7-day refresh tokens |
| Refresh Token Revocation | Database tracking with revocation flag |
| User Isolation | All queries automatically filtered by @AuthenticationPrincipal |
// Example: All user notes are scoped
@GetMapping
public ResponseEntity<?> getAllNotes() {
User currentUser = securityUtils.getCurrentUser(); // Automatic
List<Note> notes = noteRepository.findByUser(currentUser);
// Only current user's notes are returned
}- HTTPS Only: Configure SSL/TLS certificates in production
- CORS Configuration: Restrict to trusted origins only
- Rate Limiting: Implement to prevent brute force attacks
- Input Validation: All DTOs validated with
@Validand custom validators - SQL Injection Prevention: All queries use JPA parameterized queries
Never commit secrets! Use environment variables:
# โ
Good - Environment variable
export GOOGLE_API_KEY="${GOOGLE_API_KEY}"
# โ Bad - Hardcoded in code
String apiKey = "AIza...";Key configuration in SecurityConfig.java:
- CORS policies
- CSRF protection disabled for stateless APIs
- JWT filter registration
- Password encoder configuration
Problem: org.postgresql.util.PSQLException: Connection refused
Solution:
# Verify PostgreSQL is running
psql -U postgres -d postgres -c "SELECT version();"
# If not running, start it
# macOS
brew services start postgresql
# Linux
sudo systemctl start postgresql
# Verify connection string in application.properties
# Should be: jdbc:postgresql://localhost:5432/notemind_aiProblem: io.lettuce.core.RedisConnectionException
Solution:
# Verify Redis is running
redis-cli ping # Should return PONG
# If not running, start it
# macOS
brew services start redis
# Linux
sudo systemctl start redis-serverProblem: 401 Unauthorized
Solution:
# Get a new token using refresh token
curl -X POST http://localhost:8080/api/v1/auth/refresh-token \
-H "Content-Type: application/json" \
-d '{"refreshToken": "your-refresh-token"}'
# Or login again
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "user", "password": "pass"}'Problem: java.lang.NullPointerException or missing config values
Solution:
# Verify environment variables are set
echo $JWT_SECRET_KEY
echo $GOOGLE_API_KEY
# If missing, set them
export JWT_SECRET_KEY="your-secret"
export GOOGLE_API_KEY="your-key"
# Or uncomment values in application.properties for local developmentProblem: 403 Forbidden or Invalid Cloudinary credentials
Solution:
# Verify Cloudinary credentials
export CLOUD_NAME_CLOUDINARY="your-cloud-name"
export CLOUD_API_KEY_CLOUDINARY="your-api-key"
export CLOUD_API_SECRET_CLOUDINARY="your-api-secret"
# Test API key validity
curl -X GET "https://api.cloudinary.com/v1_1/${CLOUD_NAME_CLOUDINARY}/resources/image" \
-u "${CLOUD_API_KEY_CLOUDINARY}:${CLOUD_API_SECRET_CLOUDINARY}"Problem: java.lang.OutOfMemoryError: Java heap space
Solution:
# Increase Gradle memory
export GRADLE_OPTS="-Xmx1024m"
# Or configure in gradle.properties
echo "org.gradle.jvmargs=-Xmx1024m" >> gradle.properties
# Run build
./gradlew buildProblem: Docker not running or Testcontainers configuration issue
Solution:
# Ensure Docker is running
docker --version
docker ps
# If Docker is not installed, install it
# Visit: https://www.docker.com/products/docker-desktop
# Run tests again
./gradlew testEnable debug logging to troubleshoot issues:
# Set debug level in application.properties
logging.level.root=INFO
logging.level.com.dhaliwal.notemind=DEBUG
logging.level.org.springframework.security=DEBUG
logging.level.org.springframework.web=DEBUG
# Or via environment variable
export LOGGING_LEVEL_COM_DHALIWAL_NOTEMIND=DEBUG
./gradlew bootRun# Check application health (once added to config)
curl http://localhost:8080/actuator/health
# Expected response
{
"status": "UP",
"components": {
"db": { "status": "UP" },
"redis": { "status": "UP" }
}
}- Check logs: Look in
build/reports/tests/test/index.htmlfor test failures - Database logs: Check PostgreSQL logs in
/var/log/postgresql/ - Redis logs: Check Redis logs with
redis-cli monitor - Spring Boot logs: Look for stack traces in terminal output or logs directory
-
Fork the repository
git clone https://github.com/sukhmmeet/NoteMind-AI.git cd NoteMind-AI -
Create a feature branch
git checkout -b feature/your-feature-name
-
Make changes and commit
git add . git commit -m "feat: add your feature description"
-
Push and create a Pull Request
git push origin feature/your-feature-name
- Java: Follow Google Java Style Guide
- Naming: Use descriptive names for variables, methods, and classes
- Comments: Add comments for complex logic
- Tests: Write tests for new features
- Formatting: Use IDE auto-format (Ctrl+Alt+L in IntelliJ)
type(scope): description
feat(auth): add OAuth2 support
fix(notes): resolve N+1 query issue
docs(readme): add Docker setup instructions
test(flashcards): add test for regenerate endpoint
refactor(services): extract AI logic to separate class
Commit Types:
feat: New featurefix: Bug fixdocs: Documentationtest: Testsrefactor: Code refactoringperf: Performance improvementchore: Dependency/build updates
When reporting bugs, include:
- Clear title and description
- Steps to reproduce
- Expected vs actual behavior
- Environment details (OS, Java version, etc.)
- Error logs/stack traces
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ app_users โ โ note โ โ flash_card โ
โโโโโโโโโโโโโโโโค โโโโโโโโโโโโโโโโค โโโโโโโโโโโโโโโโค
โ id (PK) โโโโ โ id (PK) โโโโ โ id (PK) โ
โ username โ โ โ title โ โ โ question โ
โ password โ โ โ content โ โ โ answer โ
โโโโโโโโโโโโโโโโ โ โ summary โ โ โ created_at โ
โ โ summary_type โ โ โ note_id (FK) โโโโ note
โ โ image_url โ โ โโโโโโโโโโโโโโโโ
โ โ search_vectorโ โ
โ โ created_at โ โ โโโโโโโโโโโโโโโโ
โ โ updated_at โ โ โ tag โ
โโโโ โ user_id (FK) โ โ โโโโโโโโโโโโโโโโค
โ folder_id(FK)โโโโผโโโ โ id (PK) โ
โโโโโโโโโโโโโโโโ โ โ name (UNIQUE)โ
โ โ โโโโโโโโโโโโโโโโ
โ โ โ
โโโโโโโโดโโโโโโโโ โ โโโโโโโโดโโโโโโโโ
โ note_tags โ โ โ folder โ
โ (join table)โ โ โโโโโโโโโโโโโโโโค
โโโโโโโโโโโโโโโโค โ โ id (PK) โ
โ note_id (FK) โ โ โ name โ
โ tag_id (FK) โ โ โ user_id (FK) โ
โโโโโโโโโโโโโโโโ โ โโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโ
โ โ refresh_token โ
โ โโโโโโโโโโโโโโโโโค
โ โ id (PK) โ
โ โ token (UNIQUE)โ
โโโโ โ user_id (FK) โ
โ expiry_date โ
โ revoked โ
โโโโโโโโโโโโโโโโโ
Key indexes:
GINindex onnote.search_vectorfor full-text search- Unique constraint on
(user_id, name)infoldertable - Unique constraint on
tag.name
- Authentication & JWT
- Note CRUD operations
- AI summaries & tags
- Flashcard generation
- Image storage (Cloudinary)
- Full-text search
- Android app with Kotlin & Jetpack Compose
- Offline mode with local database
- Push notifications
- Mobile-optimized UI
- ๐ฌ AI chat with notes (conversational Q&A over your notes)
- ๐๏ธ Voice notes with speech-to-text transcription
- โ๏ธ Rich Markdown editor with live preview
- ๐ Study analytics & spaced repetition scheduling
- ๐ฏ Flashcard performance tracking
- ๐ Note sharing & collaboration links
- ๐ฅ Real-time collaboration (WebSocket)
- ๐ Elasticsearch integration for advanced search
- ๐๏ธ Tags and labels system enhancements
- ๐ค Export notes to PDF, Word, Markdown
- Notion API integration
- Google Drive sync
- Slack bot for quick notes
- Browser extension for web clipping
| Metric | Value |
|---|---|
| Backend Controllers | 4 |
| Service Classes | 5+ |
| Entities | 8 |
| API Endpoints | 20+ |
| Test Coverage | 16+ test classes |
| External Integrations | 3 (Google AI, OpenRouter, Cloudinary) |
- Spring Boot Documentation: https://spring.io/projects/spring-boot
- PostgreSQL Full-Text Search: https://www.postgresql.org/docs/current/textsearch.html
- JWT Best Practices: https://tools.ietf.org/html/rfc8725
- Google Gemini API: https://ai.google.dev/
- OpenRouter: https://openrouter.ai/
- Cloudinary: https://cloudinary.com/documentation
Sukhmeet Dhaliwal โ Computer Science Engineering Student
- ๐ง Email: officialsukhmeet9@gmail.com
- ๐ GitHub: @sukhmmeet
- ๐ผ LinkedIn: Sukhmeet Singh Dhaliwal
Special thanks to the open-source community for amazing tools like:
- Spring Boot framework
- PostgreSQL database
- Redis caching
- Google AI & OpenRouter for AI capabilities
- Cloudinary for image storage
This project is open source and available under the MIT License.
โญ If you find this project useful, please consider giving it a star!
Built with โค๏ธ using Java, Spring Boot, PostgreSQL & AI