A notes application with real-time filtering, tag management, and persistent state—built to practice CRUD operations and modern React patterns.
A note-taking app with real-time search, multi-tag filtering, and persistent filter state across navigation. I built this to practice full CRUD with a real API while solving a UX friction pattern most note apps ignore: keeping your context when jumping between filtered lists and single note views.
Following foundational work in frontend development, I sought to build an application demonstrating complete CRUD (Create, Read, Update, Delete) operations with external API integration.
The core technical challenge centered on state management: preserving filter selections when users navigate from a filtered list view into individual note details and back.
The main UX problem:
• most apps reset filters when you open/read a note → breaking mental context.
I designed filter state to survive route changes so users stay in their current subset instead of starting over.
Visual Design: The interface draws from Bear Notes' minimalist aesthetic, prioritizing content legibility over decorative elements. A card-based grid layout presents note previews, while the editor view maintains focus on writing with minimal chrome. The color palette remains neutral, allowing user content to command attention. Typography choices emphasize readability across different note lengths and content types.
Component Architecture: Implementation utilized shadcn/ui, a component library providing accessible, customizable base elements.
Theme System: Light, dark, and system-preference theme modes were implemented using Tailwind CSS utilities, accommodating user environment preferences and visual accessibility needs.
Search filters on every keystroke — no submit flow.
Search query syncs to URL (?search=query) → shareable + browser history friendly.
If the user applies tag filters → open a note → go back — ...the previously selected filters remain active.
This decision allows users maintain their mental model of working within a filtered subset rather than repeatedly reorienting to the full collection.
Autocomplete Prevention: When adding tags, the input displays a filtered dropdown of existing tags as users type, preventing tag proliferation through minor variations (e.g., "work" vs "Work" vs "work-related").
Implicit Tag Lifecycle: Rather than implementing a separate tag management interface, tags exist only while notes reference them. This reduces cognitive overhead—users manage notes, and tags manage themselves.
MockAPI.io provides the backend endpoints for CRUD operations:
• GET /notes - Retrieve all notes
• POST /notes - Create new note
• PUT /notes/:id - Update existing note
• DELETE /notes/:id - Delete note
This setup enabled practice with real API patterns—asynchronous operations, error handling, loading states—without backend development overhead.
Component Libraries in Production Development: Working with shadcn/ui demonstrated how professional development leverages existing solutions. Rather than building every UI element from scratch, effective development involves selecting appropriate libraries, understanding their APIs, and customizing them for specific needs.
URL as State Container: Query parameters proved surprisingly capable for managing application state. For features like filtering, search, and view preferences, URL-based state often provides simpler implementation than state management libraries.
• User authentication for private note collections
• Rich text editing capabilities
• Color theme customization beyond light/dark modes
• Note linking for connected thought documentation
Role: UX Designer / React Developer
Timeline: April - May 2025
View Live Site View Code
React

Tailwind CSS

React Router

shadcn/ui