diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..ca498ab --- /dev/null +++ b/README.en.md @@ -0,0 +1,207 @@ +
+ +# native-feel.skill + +> *"Cross-platform development AND near-native performance — refuse the trade-off."* + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) +[![Agent Skill](https://img.shields.io/badge/Agent-Skill-7c3aed)](https://github.com/yetone/native-feel-skill) + +
+ +**An Agent Skill for designing cross-platform desktop apps that feel native** — distilled from Raycast's 2.0 technical deep-dive and grounded in reverse-engineering of the shipping `Raycast Beta.app` binary. + +Two goals usually pull against each other: convenient cross-platform development, and near-native performance. This skill captures the structural choices — eight architectural tenets, a four-layer architecture, a WebKit/WebView2 survival guide, a 75-item ship audit — that let an app have both. + +
+ +**Install** — pick one: + +
+ +**A. With [`skills`](https://github.com/vercel-labs/skills) (any compatible agent):** + +```bash +npx skills add yetone/native-feel-skill -g +``` + +The `-g` flag installs globally (user-level) so every project picks it up. + +**B. Or paste this prompt to your AI agent:** + +``` +Install the native-feel skill for me: + +1. Clone https://github.com/yetone/native-feel-skill into your + user-level skills directory as `native-feel-cross-platform-desktop/` + (whatever path your agent reads skills from on this machine — e.g. + `~/.claude/skills/` for Claude Code). +2. Verify that SKILL.md plus the references/ and checklists/ subdirs + are present. +3. Confirm the install path when done. +``` + +
+ +[Use cases](#use-cases) · [What this is](#what-this-is) · [Philosophy](#philosophy) · [Layout](#layout) · [Sources](#sources) + +
+ +--- + +## Use cases + +Once installed, the skill activates automatically whenever the conversation touches cross-platform desktop architecture, WebView quirks, or making a UI feel native. Two common ways to use it: + +### Case 1 — Refactor an existing app to feel more native + +You have an Electron / Tauri / web-wrapped app, and a designer (or your own eye) tells you it feels web-y. You want to know where to start and how far you can take it without a full rewrite. + +``` +You ❯ My Electron app feels web-y on macOS — the designer says it + doesn't pass for a real Mac app. Where do I start? + +Agent ❯ Quickest path is the 75-item native-feel audit + (checklists/ship-readiness.md). Most Electron apps fail + the same 6–8 items: + - cursor:pointer on rows (item 21) + - web-style modal overlays instead of native sheets (19) + - hardcoded brand accent instead of system accent (33) + - page fade-transitions (40) + - opaque window background instead of platform material (31) + - WebKit context menu still firing (23) + Each is a 5-to-30-minute fix; together they move you most + of the way to "passes the 30-second skeptical user test." + + Bigger question first: how far do you need to go? If "good + enough" means passing that 30-second test, Electron + this + audit gets you 80% there without rewriting. If you want + "indistinguishable from a Mac app" — Liquid Glass materials, + native popovers, sub-200ms launch — Electron has a ceiling + you'll hit. Want me to run the decision tree first? +``` + +### Case 2 — Build a cross-platform native-feel app from scratch + +Greenfield project, must run on macOS + Windows, and the native feel is the *point* — a launcher, a productivity tool, an AI workspace your users live in all day. + +``` +You ❯ Starting a new desktop app — macOS + Windows, native feel + is the whole pitch. What architecture should I use? + +Agent ❯ Before architecture, the decision tree + (checklists/decision-tree.md) rules this stack out for + several common shapes — quick check first: + - Cold-start budget? (<100ms → build native instead) + - Memory floor? (<150MB → build native instead) + - Extension ecosystem? (yes → need the Node layer) + - Runway? (<3mo → start on Electron) + + If you pass, the four-layer architecture is: + + ┌──────────────────────────────────────────────────┐ + │ Native shell Swift/AppKit + C#/WPF │ + │ ↕ one IPC schema, codegen for all sides │ + │ System WebView WKWebView + WebView2 │ + │ running React + TypeScript, shared 1:1 │ + │ ↕ │ + │ Node backend single long-lived process │ + │ ↕ │ + │ Rust core UniFFI-bridged, sharable │ + │ with iOS and server │ + └──────────────────────────────────────────────────┘ + + The expensive-to-get-wrong decisions, in order: + 1. The IPC contract (one schema, codegen). Get this wrong + and you rebuild it later under duress. + 2. WebView survival flags (occlusion off, alpha-prewarm, + _doAfterNextPresentationUpdate, font prewarming). + 3. Memory hygiene (lazy-load extensions, tear down + secondary windows aggressively). + + Want to start with the seam — where to draw the cross- + platform line — or with the IPC contract, since getting + that schema wrong means rebuilding every bridge later? +``` + +### Other things the skill is good for + +- **"Why is my WKWebView flickering when I hide and re-show it?"** → walks you through `references/03-webview-survival.md` (most likely A.1 throttling or A.2 startup flicker). +- **"How should typed IPC work across Rust, Swift, and TypeScript?"** → the UniFFI-based pattern in `references/04-ipc-contract.md`, with the exact `Coordinator`/`EventHandler` shape Raycast Beta ships. +- **"My app is at 450 MB resident, is that bad?"** → the six common Activity-Monitor mistakes and what to actually measure, in `references/05-memory-truths.md`. +- **"Is my designer's spec ‘native enough’?"** → the 70+ item conventions audit in `references/06-native-conventions.md`. + +--- + +> *"We're not a web app with some native hooks sprinkled on top. We're a native app that uses web for its UI."* — Raycast + +## What this is + +A reference for architects, tech leads, and engineers who must build a desktop app that: + +- runs on **macOS + Windows** (optionally Linux) from a single UI codebase, +- launches in under 500 ms and stays under 500 MB resident, +- is **indistinguishable from a native app** to its users (no `cursor: pointer` tell-tales, no white-flash on launch, no WebKit context menu, no smooth-scroll JS), +- supports a **plugin/extension ecosystem** in TypeScript, +- can share performance-critical code with iOS and a server backend. + +This is the four-layer architecture: **native shell → system WebView (WKWebView/WebView2) → Node backend → Rust core**, wired together with a single typed IPC schema that generates clients for every runtime. + +## What this is not + +- Not for single-OS apps (just build native). +- Not for Electron-style "good enough" apps (the polish budget here is 5–10× higher). +- Not for apps with strict <150 MB or <100 ms cold-start budgets (the floor is real). +- Not for games, document editors, or media players. + +Run [`checklists/decision-tree.md`](checklists/decision-tree.md) to find out if this architecture is even right for your project. It rules itself out for several common cases — saying so directly is more useful than over-fitting advice. + +## Layout + +``` +native-feel-skill/ +├── SKILL.md # entry point for the agent +├── references/ +│ ├── 01-philosophy.md # 8 tenets that drive every decision +│ ├── 02-architecture.md # the four-layer architecture +│ ├── 03-webview-survival.md # WebKit/WebView2 quirks + fixes (the goldmine) +│ ├── 04-ipc-contract.md # typed IPC across Rust/Swift/C#/TS +│ ├── 05-memory-truths.md # why Activity Monitor lies +│ ├── 06-native-conventions.md # 70+ items the native-feel audit checks +│ └── 07-evidence-raycast.md # what a reverse-eng. of Raycast Beta shows +└── checklists/ + ├── decision-tree.md # should you use this architecture? + └── ship-readiness.md # 75-item launch audit +``` + +## Philosophy + +The central tension this architecture resolves: **how can a desktop app deliver convenient cross-platform development AND near-native performance, when those goals usually pull against each other?** Eight tenets name the structural moves: + +1. **Place the seam at the rendering surface** — share above the WebView, diverge below it; this is the only altitude where both DX and native feel survive. +2. **One schema, many languages** — pay the polyglot tax once at the declaration, never at the call site. +3. **Adopt the platform; don't compete with it** — the OS draws blur, scrolling, materials, and dark mode better than you can. +4. **Performance is a property of perception** — what the user feels, not what Activity Monitor reports. +5. **The short iteration loop is the product** — 200 ms hot reload vs 30 s native rebuild is a 150× compounding advantage. +6. **Cross boundaries intentionally** — IPC has a cost; design every crossing as async, batched, schema-typed. +7. **Identity is muscle memory** — the hotkey, the rank order, the verbs are the app; everything else is implementation. +8. **Separate baseline from margin** — the WebView+Node floor is rented; only your dirty pages are yours to optimize. + +Read [`references/01-philosophy.md`](references/01-philosophy.md) first. Everything else is consequence. + +## About Agent Skills + +Agent Skills are the emerging standard for packaging domain knowledge that any compatible agent (Claude Code, the Claude Agent SDK, or other Agent-Skill-aware runtimes) can discover and load. Once installed via the prompt at the top of this README, the skill activates automatically when the agent's conversation touches cross-platform desktop architecture, WebView quirks, or Raycast-style apps — the trigger conditions are declared in `SKILL.md`'s frontmatter. + +## Sources + +- Raycast's public technical post: [A Technical Deep Dive into the New Raycast](https://www.raycast.com/blog/a-technical-deep-dive-into-the-new-raycast) +- Reverse engineering of `Raycast Beta.app` v0.60.0 (macOS 26+ build, Xcode 17, arm64) — see [`references/07-evidence-raycast.md`](references/07-evidence-raycast.md) for what was found and how. + +## License + +MIT — see [`LICENSE`](LICENSE). + +## Credits + +Authored as an Agent Skill. The architecture this skill describes is Raycast's; the philosophy is the author's synthesis; the evidence is from the shipping app.