Case study · Stack

How Raycast built a native launcher that runs on Mac and Windows

Raycast is a keyboard launcher with extensions, AI chat and file search. It started as a pure Swift and AppKit Mac app, and Raycast 2.0 became a hybrid: thin native shells, a shared React UI in system web views, a Node.js core and Rust where speed matters.
Copy this stackraycast.com Productivity launcher for Mac and Windows · United Kingdom · founded 2020

Language

  • Swiftraycast.com

    Writes the macOS host app that handles windows, hotkeys and the menu bar.

  • TypeScriptraycast.com

    Is the language of the front end, the Node core and third-party extensions.

UI library

  • AppKitraycast.com

    Provides the native macOS layer of the app.

    Why: They weren't confident SwiftUI wouldn't raise crash rates or hurt performance.

  • Reactraycast.com

    Builds the shared UI for every window and the extensions API.

    Why: One web UI codebase serves both platforms while the native shells keep full access to OS APIs.

  • WebKitraycast.com

    Renders the UI on macOS through the system WKWebView, with WebView2 doing the same on Windows.

    Why: They didn't want to bundle Chromium on macOS when the system's WebKit was already there.

Full-stack framework

  • .NETraycast.com

    Runs the Windows host app, written in C# with .NET 8 and WPF.

Build and runtime

  • esbuildraycast.com

    Transpiles extension TypeScript inside the ray CLI.

  • Goraycast.com

    Is the language of the ray CLI that extension developers use to build and publish.

Data fetching

  • JSON-RPCraycast.com

    Carries messages between the extension runtime and the app over standard streams.

    Why: It is lightweight, well supported, fast enough and easy to debug because it is plain text.

Backend framework

  • Node.jsraycast.com

    Runs one long-lived process with database access, the extension runtime and other services.

    Why: Node is the shared layer for both platforms, so feature work is done only once.

  • Rustraycast.com

    Powers the shared data layer, cloud sync and the file indexer.

    Why: They use it where performance or portability matter more than convenience.

AI model

  • OpenAIraycast.com

    Was the first and for a while only model provider behind Raycast AI.

  • Anthropicraycast.com

    Supplies the Claude models offered in Raycast AI.

    Why: No single model is best at speed, intelligence and context window at once, so users pick per task.

How they built it

Native from day one

The original Mac app was written in Swift with AppKit. The team skipped SwiftUI because they weren't confident it wouldn't raise crash rates or hurt performance, two things a launcher you open dozens of times a day can't afford.

Sources:raycast.com

Extensions in React, rendered as native UI

Raycast wanted extensions to feel first-class, not like mini-apps in a web frame. Developers write React and TypeScript, and a custom React reconciler turns their components into a JSON render tree that the Swift side draws with AppKit, diffing each render with JSON Patch.

The first attempt ran extensions on JavaScriptCore, but developers couldn't use their favorite npm packages. So Raycast moved to Node.js, running each extension in its own worker thread with memory limits and crash isolation, and talking to the app over JSON-RPC 2.0.

Sources:raycast.com

Raycast 2.0: a hybrid stack for Windows

To ship on Windows, Raycast rewrote the app from scratch. Each platform keeps a native host (Swift and AppKit on macOS, C# with .NET 8 and WPF on Windows) that loads one shared React and TypeScript front end in the system web view and supervises a long-lived Node.js process holding the business logic.

They looked at Electron, Tauri, Flutter, Qt and React Native for desktop. Electron made deep OS integration painful and meant bundling Chromium on macOS, and Tauri gave less native control and felt too young to bet the company on. The trade-off is that Raycast now maintains its own IPC, and memory use went up compared with v1.

Sources:raycast.com

Rust where performance and portability count

Rust is reserved for the places where performance or portability matter more than convenience: a data layer that the iOS app can share, cloud sync and a file indexer running as its own process.

The indexer exists because Windows has no system-wide index good enough for Raycast. On Windows it reads the NTFS Master File Table directly to scan drives quickly.

Sources:raycast.com raycast.com

From one AI provider to many

Raycast AI launched on OpenAI models only. In April 2024, after the community kept asking for more models, Raycast added Anthropic, Perplexity and open models served by Groq, arguing that no single model wins on speed, intelligence and context window at once.

Sources:raycast.com

Also detected on their website

Found on the homepage with the open Wappalyzer rules (HTML, scripts and headers). It shows what runs in the browser, not the whole backend.

  • HSTS
  • Next.js
  • Vercel
  • Webpack