.md

Getting Started

From zero to a native app running your Solid code in about three minutes (plus one coffee while the toolchain warms).

Prerequisites

  • bun 1.2+ — runs the CLI, the bundler, and your tests
  • Flutter 3.41+ — the rendering host (flutter doctor should be green for your targets)
  • Xcode for iOS/macOS, or an Android SDK + emulator for Android

Create an app

$ npm create skal my-app
$ cd my-app

The scaffold is a complete, runnable project:

my-app/
├── src/
│   ├── App.jsx          # your Solid app — edit this
│   └── index.jsx        # entry: mounts <App/> on the bridge renderer
├── flutter-host/        # platform shells (android/ios/macos) + libskal
├── .maestro/smoke.yaml  # E2E smoke test, ready to run
└── package.json         # dev / build / test scripts

Run it

$ npm i -g @skal/cli   # once — or use `bun run dev:<target>` directly

$ skal dev macos       # fastest loop for UI work
$ skal dev android     # boots an emulator automatically if none is attached
$ skal dev ios         # iOS Simulator
$ skal dev web         # Solid → DOM at localhost:5173

skal dev builds the JS bundle and launches the platform host. Add --hot and the hot-reload server pushes every save under src/ straight into the running app — navigation and hot state survive.

🍻 First run is slower. The platform host compiles once per target (normal Flutter behavior). Every run after that is seconds.

Make it yours

Open src/App.jsx. It's plain SolidJS — signals, memos, effects, <For>, <Show> — with Skal's widget set instead of DOM tags:

import { createSignal } from 'solid-js';
import { Column, Text, Button } from 'skal';

export default function App() {
  const [name, setName] = createSignal('Skal');
  return (
    <Column padding={24} gap={16}>
      <Text label={`Hello, ${name()}`} fontSize={28} fontWeight={800} />
      <Button label="Skål 🍻" onClick={() => setName('World')} />
    </Column>
  );
}

When a signal changes, Solid updates exactly the widgets that read it — no virtual DOM, no reconciliation pass. The change crosses to Flutter as a handful of binary ops in shared memory. See Components for the full widget set.

Ship it

$ skal build android   # release APK, JSC bytecode cache baked in
$ skal build ios       # release build for TestFlight
$ skal build macos
$ skal build web       # static site bundle

Release builds compile your bundle to JavaScriptCore bytecode, so production cold starts skip the JS parser entirely — that's the 36 ms first-eval.

Where next