Skip to content

Repository files navigation

Ilham

Ilham is the Arabic word for inspiration. It is a local-first, infinite mood board for arranging references and finding new inspiration in the collection you have built.

Drop images onto the board, arrange them freely, extract palettes, add labels, and optionally use semantic captions and embeddings to search or organize visual ideas. Your board stays in the browser; AI is an opt-in enhancement rather than a dependency of the core experience.

Ilham board overview

Quick start

Prerequisites: a recent Node.js release and pnpm.

pnpm install
pnpm dev

Open the Vite address shown in the terminal. Ilham is desktop-first; the compact viewport shows a desktop-only message instead of a reduced board.

pnpm test
pnpm lint
pnpm build

Using the board

  1. Drop image files onto the canvas or paste an image from the clipboard.
  2. Use the toolbar to select, marquee-select, zoom, pan, extract colors, add a label, search, organize, undo, redo, or change layer order.
  3. Drag nodes to move them. The selection transformer handles resize and rotation.
  4. Open the right-side panel to inspect selected nodes and monitor processing activity.
  5. Use Export in the header to preview and download the board or current selection.

The footer shows the board position, zoom level, organizer progress, and local storage status.

Shortcut Action
V Select
M Area select
H Pan
Z Zoom
T Add label
⌘ Z Undo
⇧ ⌘ Z Redo
Delete Delete selection
⌘ ] Bring forward
⌘ [ Send backward

Local-first data

Ilham has no application backend. IndexedDB is the local source of truth for:

  • Image blobs.
  • Assets and generated metadata.
  • Nodes, transforms, and stacking order.

The UI updates immediately. A small write queue persists board changes in order and combines rapid updates to the same node before they reach IndexedDB. The footer reports whether the queue is saved, saving, or failed; a failed write can be retried.

Browser storage is scoped to the current browser profile and origin. Clearing site data removes the local board. Live synchronization between tabs and remote backup are not implemented.

Optional Gemini features

AI features require your own Gemini API key:

  1. Open Settings.
  2. Paste the key under Gemini.
  3. Select Use for this tab.

The key remains only in module memory for the current tab. It is not saved to IndexedDB, localStorage, Zustand, or the board. Closing the tab or choosing Clear removes it. The selected model IDs and request limits are ordinary non-secret preferences and may be saved locally in production.

With a key, newly added images are processed in the background:

image file
  -> image embedding
  -> concise visual caption
  -> caption embedding
  -> ready for semantic search and organization

Caption and embedding requests are independently serialized and rate-limited. Configure the limits to match your Gemini tier. If processing fails, the image remains on the board and the activity panel offers feedback and removal.

For development-only defaults, copy .env.example to .env.local and fill the values you want:

cp .env.example .env.local
VITE_GOOGLE_GENAI_API_KEY=
VITE_GOOGLE_CAPTION_MODEL=gemini-3.6-flash
VITE_GOOGLE_CAPTION_REQUESTS_PER_MINUTE=5
VITE_GOOGLE_CAPTION_REQUESTS_PER_DAY=20
VITE_GOOGLE_EMBEDDING_MODEL=gemini-embedding-2
VITE_GOOGLE_EMBEDDING_REQUESTS_PER_MINUTE=5
VITE_GOOGLE_EMBEDDING_REQUESTS_PER_DAY=100
VITE_BOARD_HISTORY_LIMIT=16

All VITE_* values are included in a Vite development build. Do not use this mechanism for a shared production key. Production ignores these defaults and asks each user to provide their own key for the active tab.

How it is built

React components  -> interface and browser gestures
board commands    -> state, history, persistence, and async coordination
Zustand           -> reactive board and interface state
IndexedDB         -> local assets, image blobs, and nodes
React Konva       -> infinite board rendering and direct manipulation
Gemini            -> optional captioning and embeddings
Web Worker        -> bounded organization calculation

The core models are validated with Zod:

  • Asset is reusable content: an image, palette, or text label.
  • Node places an asset on the board and owns stacking order and transform data.
  • Transform stores centre-based x, y, width, height, and rotation.
  • Board describes ordered node IDs and durable groups.

The project keeps rendering, board behavior, storage, semantic work, and schemas as separate boundaries:

src/
├── board/        board commands, history, layout, persistence, and state helpers
├── components/   board, layout, search, toolbar, and shadcn/Base UI components
├── schemas/      Zod asset, board, and node models
├── semantic/     Gemini integration, rate limiting, cosine scoring, and search
├── storage/      IndexedDB access and the local write queue
├── workers/      off-main-thread layout calculation
└── store.ts      small reactive Zustand store

For a detailed account of semantic search and the layout algorithm, see Layout and Search.

Development notes

  • TypeScript is strict and React Compiler is enabled.
  • Tailwind CSS v4 provides styling; shadcn components use Base UI primitives.
  • Tests are deliberately offline and do not require an API key, IndexedDB, or network access.
  • pnpm build runs the TypeScript build before Vite’s production build.

Current boundaries

  • This is a desktop-first web application, not a packaged desktop app.
  • The board is local to one browser profile and does not sync between devices or tabs.
  • The Gemini key is a user-supplied browser key for a local experience. A hosted multi-user deployment should use a server-side proxy or another appropriate credential boundary.
  • Organization is applied immediately as one undoable operation; a preview-and-apply flow is not yet available.

Future improvements

  • Use a local or remote vector database for higher-quality similarity search as boards grow.
  • Support additional AI providers and local models alongside Gemini.
  • Add a chat surface with safe, user-approved board tool calls.
  • Add image generation for creating new visual references directly on the board.

Built with Codex

Codex was used as an iterative engineering collaborator throughout the project. It helped turn ideas into small implementation steps, review and simplify the React/Konva architecture, add offline tests, audit performance and persistence behavior, and write project documentation. Product decisions, interaction design, and final direction remained human-led.

Author

Created by reuteelf.

I enjoy finding unexpected usecases for familiar tools and turning that curiosity into something tangible. This MVP is largely vibe-coded, made possible by OpenAI Build Weeks free Codex credits. I may not win and will probably die broke ... but I hope it inspires someone to build an even better product.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages