Advanced color management for designers and developers.
ColorClip Pro is a cross-platform Electron desktop app that acts as a professional color clipboard — pick colors from anywhere on screen, organize them into palettes, and sync them across devices.
- Screen Eyedropper — pick any color directly from your screen
- Interactive Color Wheel — HSV-based selector with gradient controls
- Multi-format Input — RGB sliders, HSV fields, HEX input, and Alpha slider
- Drag-to-Adjust Inputs — click and drag on any label to adjust values (Shift = 10×, Alt = 0.1×)
- Transparency Preview — checkered background on alpha slider and swatches
- 240-Slot Grid — 12-row expandable swatch grid
- Draggable Resize — grab the resize handle to adjust the grid height live
- Multiple Palettes — create, rename, and delete palettes; each persists independently
- Color History — per-swatch edit history
- Copy / Paste / Duplicate — full swatch operations with context menus
| Mode | When Active | How it Works |
|---|---|---|
| Cloud Sync | Logged in via OAuth | Real-time WebSocket + 30-min polling fallback; syncs to cloud API |
| Folder Sync | Offline / no login | Auto-saves to a user-chosen folder (works with Google Drive, Dropbox, OneDrive, etc.) |
Cloud and folder sync are mutually exclusive. Folder settings are always preserved locally, even when switching between modes.
- Grid dimensions (swatch width, height, row count)
- Background colour, font family, language
- Configurable folder sync interval (1–60 minutes)
Ctrl+Alt+P/Cmd+Alt+P— toggle FPS counterCtrl+Shift+P/Cmd+Shift+P— open performance dashboard (memory, CPU, event-loop lag, hardware acceleration)Ctrl+Shift+I/Cmd+Shift+I— open Chrome DevTools
| Platform | Formats |
|---|---|
| Windows | NSIS installer, ZIP (x64) |
| macOS | ZIP (x64 + Apple Silicon) |
| Layer | Technology |
|---|---|
| Desktop | Electron 39 |
| UI | React 19 + TypeScript 5 |
| Build | Webpack 5 |
| Package manager | bun |
| Components | Radix UI |
| Storage | electron-store |
| Cloud API | Vercel serverless — https://api.mantisarts.com |
| Database | Neon PostgreSQL |
| Real-time | Socket.io (HTTP long-polling) |
| Auth | OAuth 2.0 (Google, GitHub, Discord) + JWT |
| Testing | Jest, Playwright |
- bun (package manager)
- Node.js 20+
# Clone the repo
git clone https://github.com/daveprout/colorclip-pro.git
cd colorclip-pro
# Install dependencies
bun install
# Start dev server (renderer hot-reload + Electron)
bun startbun run build # Full production build (main + renderer)
bun run build:main # Main process only
bun run build:renderer # Renderer onlybun run package # All platforms
bun run package:win # Windows (ZIP + NSIS installer)
bun run package:mac # macOS (ZIP)Create a .env file in the project root:
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...
DISCORD_CLIENT_ID=...
DISCORD_CLIENT_SECRET=...
API_BASE_URL=https://api.mantisarts.com # optional override# Unit tests (Jest)
bun test
bun test -- --watch
bun run test:coverage
# Electron E2E (Playwright — real Electron app)
bun run test:electron
bun run test:electron:headed # see the window during tests
bun run test:electron:ui # Playwright UI
# Browser E2E (Playwright — renderer in browser)
bun run test:e2e
bun run test:e2e:smoke
# Load tests (requires k6)
bun run test:load:smoke # 5 VU
bun run test:load # 100 VU
bun run test:load:stress # 200 VUCurrent test status:
- Unit tests: 27/27 passing
- Electron E2E: 60/60 passing
- Browser E2E: infrastructure working; some tests need mock-data updates
src/
├── main/
│ ├── index.ts # Entry point & IPC handlers
│ ├── syncService.ts # Cloud sync (WebSocket, polling)
│ ├── fileSyncService.ts # Folder sync (offline mode)
│ ├── colorPickerStore.ts # Local storage & data repair
│ ├── auth-backend.ts # OAuth flows
│ ├── eyedropperOverlay.ts # Screen colour picking
│ └── performanceMonitor.ts # Metrics, FPS, hardware info
├── preload/
│ └── index.ts # contextBridge IPC bridge
├── renderer/
│ └── components/ColorPicker/
│ ├── index.tsx # Root UI component
│ ├── ColorWheel.tsx # HSV selector canvas
│ ├── ColorInputs.tsx # RGB / HSV / HEX fields
│ ├── SwatchGrid.tsx # 240-slot swatch grid
│ ├── SwatchItem.tsx # Individual swatch
│ ├── PaletteSelector.tsx
│ ├── EyedropperTool.tsx
│ ├── ResizeHandle.tsx # Draggable grid resize
│ └── Settings.tsx # Settings dialog
└── shared/
└── types/color-picker.ts # Shared TypeScript types
All main-process communication flows through a three-layer contract. When changing any IPC channel, update all three:
src/main/index.ts—ipcMain.handle('channel:name', ...)src/preload/index.ts— contextBridge mapping- Renderer callers —
window.electronAPI.*
Every Color object carries all three representations simultaneously:
interface Color {
rgb: { r, g, b, a }; // 0–255
hsva: { h, s, v, a }; // h: 0–360, s/v/a: 0–255
hex: string; // 8-digit #RRGGBBAA
}palette.swatches is positional — swatches[5] is always grid slot 5. null entries represent empty slots. Never filter or compact this array.
This project is licensed under a Personal Non-Commercial License (see LICENSE). Individuals can use and modify it for personal, non-commercial purposes only. Company or commercial use requires a separate license from the author.