Skip to content

fx2000/clustering-notes

Repository files navigation

Clustering Notes

An interactive whiteboard for organizing sticky notes into clusters. Notes can be grouped by color, author, or AI-suggested themes using Google Gemini. Supports grid and stacked layouts, drag-and-drop, zoom, and custom AI prompts for flexible clustering.

Tech Stack

  • React 19 with TypeScript
  • Vite 8 for dev server and bundling
  • Tailwind CSS 4 for styling
  • json-server as a mock REST API
  • Google Gemini API (free tier) for AI-powered content clustering

Getting Started

Prerequisites

Installation

npm install

Environment

Copy the example env file and add your Gemini API key:

cp .env.example .env

Edit .env:

VITE_GEMINI_API_KEY=your-api-key-here

Running

npm run dev

This starts both the Vite dev server (port 5173) and the json-server API (port 3001) concurrently.

You can also run them separately:

npm run client   # Vite dev server only
npm run api      # json-server only

Testing

npm test            # Run all tests once
npm run test:watch  # Run in watch mode

Tests use Vitest and cover:

  • Geometry utilities -- groupNotesByField, calculateClusterPositions (grid and stack), getBoardSize, getCenter
  • Gemini response parsing -- clean JSON, markdown fence stripping, unknown ID filtering, empty group handling, API errors, missing API key, custom prompt passthrough

Features

Clustering Modes

  • Color -- groups notes by their color
  • Author -- groups notes by who wrote them
  • Suggested (AI) -- uses Gemini to identify common themes in note content and group accordingly

Layout Modes

  • Grid -- spreads notes in a grid within each group
  • Stack -- piles notes on top of each other with a slight offset per group

AI Prompt Input

Type a custom instruction (e.g., "sort into bug reports and feature requests") and Gemini will cluster notes according to your description.

Cluster Labels

Each group gets an auto-generated title label that can be:

  • Dragged to reposition
  • Renamed by double-clicking
  • Deleted via a trash icon on hover

Labels are persisted to the API.

Whiteboard Interaction

  • Drag notes to reposition them (persisted to the API)
  • Pan by clicking and dragging the background
  • Zoom with toolbar buttons or Cmd/Ctrl + scroll wheel (zooms toward cursor)
  • Zoom range: 25% to 200%

URL Persistence

Clustering parameters (field and mode) are stored in the URL query string, so layouts persist across page reloads and can be shared via link.

Responsive Design

On mobile breakpoints, the AI prompt input moves to a bottom bar while clustering and zoom controls stay at the top.

Project Structure

src/
  api/
    gemini.ts        # Gemini API integration
    notes.ts         # Notes CRUD + clustering logic
    titles.ts        # Cluster label CRUD
  components/
    ClusterLabelComponent.tsx
    Note.tsx
    ToolsPanel.tsx
    Whiteboard.tsx
  media/icons/
    ClusterIcon.tsx
    GridIcon.tsx
    StackIcon.tsx
    ZoomInIcon.tsx
    ZoomOutIcon.tsx
  utils/
    geometry.ts      # Layout calculations, board sizing
  types.ts           # Shared TypeScript types
  App.tsx
  main.tsx
  style.css
db.json              # json-server database (notes + titles)

Security and Privacy Considerations

The AI clustering features send note text content to Google's Gemini API for processing. Keep the following in mind:

  • Note content is transmitted to a third-party service. Do not use AI clustering with sensitive, confidential, or personally identifiable information unless your organization's data policies permit it.
  • The Gemini API key is embedded in the client bundle (via the VITE_ prefix). This is acceptable for development and free-tier usage, but for production deployments the API calls should be proxied through a backend to avoid exposing the key.
  • No data is stored by this application beyond json-server. However, Google's data retention policies for the Gemini API apply to any content sent for classification. Review Google's API Terms of Service for details.

Future Improvements

  • State management with Zustand -- replace prop-drilling and useState in App with a Zustand store. As the app grows (undo/redo, multi-select, collaborative editing), centralized state with slices would be cleaner than threading callbacks through the component tree
  • Google Generative AI SDK for JavaScript -- replace the raw fetch calls to Gemini with the official @google/generative-ai SDK, which handles retries, streaming, error parsing, and type-safe responses out of the box
  • URL state with a custom useSearchParams hook -- replace the manual getParams/setParams functions with a reusable hook that syncs React state with URL query parameters bidirectionally, similar to nuqs or a lightweight custom implementation. This would eliminate the current split between reading params on mount and writing them on change, and make it easy to persist additional state (zoom level, scroll position) to the URL
  • Backend API with AI orchestration -- replace json-server with a proper backend (e.g., Express or Fastify) that owns the Gemini API key, handles batch note updates in a single request, and orchestrates AI calls server-side. This backend could expose a structured AI endpoint that manages prompt templates, caches results, and enforces rate limits
  • Lasso selection tool -- select multiple notes by drawing a freeform shape on the canvas, enabling bulk move, delete, or re-color operations
  • Z-index awareness on drop -- when a note is dropped on top of another, ensure the dropped note stays visually on top regardless of its order in the database
  • Per-note color picker -- allow changing individual note colors directly from the whiteboard
  • Auto-color clusters -- automatically assign a distinct color to all notes within a cluster after grouping
  • Organic cluster layout -- a "messy cluster" mode that arranges notes in a natural, slightly randomized pile rather than a strict grid or uniform stack
  • Create and edit notes -- add new sticky notes directly from the whiteboard and edit existing note text inline

About

Clustering Sticky Notes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages