Adam Bandel


Project Dashboard

Jan 2026
Type: desktop
Code: 3k lines
Files: 26
Active: Nov 2025 — Jan 2026
Stack:
PythonFastAPINext.js 16React 19TypeScriptCustomTkinterTailwind CSS
Tags:
developer-toolsautomationdesktop

Overview

Project Dashboard is a Windows desktop application that provides instant access to local development projects through a global hotkey command palette. Press Win+Shift+W from anywhere and immediately search, filter, and launch projects in VS Code, terminals, file managers, or AI coding assistants like Claude Code.

The app combines a FastAPI backend, a React/Next.js web dashboard, and native Windows integration via CustomTkinter for the command palette overlay. It runs quietly in the system tray, consuming minimal resources while providing sub-100ms project launching.

Screenshots

Command Palette

Web Dashboard

Project Details

Problem

Developers working on multiple projects waste time navigating file explorers, remembering paths, and context-switching between tools. Opening a project typically requires: finding the folder, launching the IDE, maybe opening a terminal, checking if services are running. This friction adds up across dozens of daily context switches.

Existing launchers like Alfred or Raycast are macOS-only. Windows alternatives lack deep integration with development workflows and don’t understand project structures, git status, or development tooling.

Approach

The solution is a dedicated project launcher that understands developer workflows. A global hotkey summons an instant search interface, and configurable keybindings launch projects directly into the right tool.

Stack

Challenges

Outcomes

The command palette provides reliable sub-100ms project access from any application. Project scanning correctly identifies frameworks (React, Next.js, FastAPI, etc.) and discovers documentation files. Drag-and-drop reordering persists across sessions.

Key learnings:

Implementation Notes

The command palette bypasses HTTP entirely for speed, calling Python services directly:

# Direct store import for speed (bypasses HTTP)
from .services.launcher import Launcher
from .services.store import ProjectStore

_launcher = Launcher()
_store = ProjectStore()

def _launch_project(self, project: Dict, launch_type: str):
    self.hide()
    def do_launch():
        _launcher.launch(project['path'], launch_type)
        _store.mark_palette_open(project['path'])
    threading.Thread(target=do_launch, daemon=True).start()

Project scanning uses defensive timeouts and directory caps to prevent hangs:

SCAN_TIMEOUT = 10  # seconds
MAX_DIR_ENTRIES = 200
KNOWN_SUBDIRS = ['frontend', 'client', 'backend', 'server', 'src', 'docs']

def scan(self, path_str: str) -> Project:
    with ThreadPoolExecutor(max_workers=1) as executor:
        future = executor.submit(self._do_scan, path_str)
        try:
            return future.result(timeout=SCAN_TIMEOUT)
        except FuturesTimeoutError:
            raise ValueError(f"Scan timed out after {SCAN_TIMEOUT}s")

The launcher system supports both built-in commands and custom CLI tools defined in config:

{
  "launchers": [
    {"id": "vscode", "command": "__vscode__", "hotkey": "enter", "builtin": true},
    {"id": "terminal", "command": "__terminal__", "hotkey": "ctrl+enter", "builtin": true},
    {"id": "claude", "command": "claude", "hotkey": "ctrl+c", "builtin": false}
  ]
}

Related Posts

No posts yet.