{"id":51221238,"url":"https://github.com/zzal/swiflow","last_synced_at":"2026-06-28T07:30:32.359Z","repository":{"id":365487152,"uuid":"1242967031","full_name":"zzal/swiflow","owner":"zzal","description":"Frontend ecosystem for Swift on the web: components, virtual DOM, hot-reloading dev server, WASM output","archived":false,"fork":false,"pushed_at":"2026-06-25T19:04:35.000Z","size":3816,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-25T19:10:12.288Z","etag":null,"topics":["dev-tool","form-validation","frontend-development","frontend-router","hmr","query-caching","reactive","swift","ui-library","virtual-dom","wasm"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zzal.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-18T23:44:24.000Z","updated_at":"2026-06-25T17:17:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/zzal/swiflow","commit_stats":null,"previous_names":["zzal/swiflow"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/zzal/swiflow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzal%2Fswiflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzal%2Fswiflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzal%2Fswiflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzal%2Fswiflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zzal","download_url":"https://codeload.github.com/zzal/swiflow/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzal%2Fswiflow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34881384,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dev-tool","form-validation","frontend-development","frontend-router","hmr","query-caching","reactive","swift","ui-library","virtual-dom","wasm"],"created_at":"2026-06-28T07:30:31.758Z","updated_at":"2026-06-28T07:30:32.354Z","avatar_url":"https://github.com/zzal.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Swiflow\n\n[![CI](https://github.com/zzal/swiflow/actions/workflows/ci.yml/badge.svg)](https://github.com/zzal/swiflow/actions/workflows/ci.yml)\n![Swift 6.3](https://img.shields.io/badge/Swift-6.3-orange.svg)\n![Platform: WebAssembly](https://img.shields.io/badge/platform-WebAssembly-lightgrey.svg)\n[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)\n\n## Why Swiflow?\n\nReact was the right answer to a constraint that no longer holds.\nWebAssembly lets the work move from runtime to compile time, and Swiflow is a bet\non what that makes possible — reactivity with no ceremony, a typed UI with no\ntemplate language, hot reload that keeps your state, and a batched bridge that\nkeeps it fast, with ergonomics bought from compile-time power that's structurally\nhard to copy. 2026 is a fair time to ask whether the old defaults are still the\nbest we can do. Swiflow is one answer worth a look.\n\n**[Why Swiflow exists — a case for re-questioning the defaults →](WHY.md)**\n\n\u003e Swiflow is an independent project, built and maintained by one person as a\nhands-on exploration of Swift on the web. It's **pre-1.0 and experimental** —\nsee the [changelog](CHANGELOG.md) for where things stand.\n\n## Highlights\n\n- **State-preserving HMR** — `swiflow dev` hot-swaps the running WASM on every save; `@State` survives, the page never reloads.\n- **Reactive components** — `@Component` + `@State`, with `onAppear` / `onChange` / `onDisappear` lifecycle hooks firing across the whole tree.\n- **Typed event DSL \u0026 bindings** — `.on(.click) { … }`; two-way `.value($text)`, `.checked($flag)`, `.selection($choice)`.\n- **CSS-in-Swift** — a `css { }` builder, scoped `\u003cstyle\u003e` per component, and exit animations.\n- **Routing** — `SwiflowRouter`: hash + history mode, `RouterRoot` / `Route` / `Link`, `@Environment(\\.router)`.\n- **Data layer** — `SwiflowQuery`: declarative data fetching with caching, request dedup, and stale-while-revalidate.\n- **Forms** — `FormController` / `Field` with blur-triggered validation.\n- **UI kit** — `SwiflowUI`: accessible, token-driven components that adapt to dark mode / contrast / reduced motion with no component code.\n- **Testing** — `SwiflowTesting` headless harness (`render` / `click` / `input`); deterministic async via `AsyncTestHarness`.\n- **DevTools** — a read-only browser **DevTools panel** (Chrome side panel + Safari Web Inspector) that x-rays the live component tree and `@State`; sideload it from [`devtools/`](devtools/).\n- **Safe by default** — `URLSanitizer` scrubs `javascript:` / `data:` / `blob:` URLs at the DSL fold; `rawHTML(_:)` is the loud escape hatch.\n\n## A component\n\n```swift\nimport Swiflow\nimport SwiflowDOM\n\n@MainActor @Component\nfinal class Counter {\n    @State var count = 0\n\n    var body: VNode {\n        div {\n            p(\"Count: \\(count)\")\n            button(\"Increment\").on(.click) { self.count += 1 }\n        }\n    }\n}\n\n@main\nstruct App {\n    @MainActor static func main() {\n        Swiflow.render(into: \"#app\") { Counter() }\n    }\n}\n```\n\nA `@State` mutation schedules a re-render; the diff turns the new tree into one\nbatched patch list and ships it across the bridge in a single crossing.\n\n## Quick start\n\nYou need **Swift 6.3.2** and the **WebAssembly Swift SDK 6.3.2** — the SDK's\nstdlib must match the host compiler exactly. Get the host toolchain first:\n\n- **macOS (15.6+):** install **Xcode 26.2 or newer**, which bundles Swift 6.3.2.\n  Don't reach for swiftly or a standalone swift.org toolchain here — their macOS\n  builds omit the static stdlib, so compiling an app's macros fails to link.\n- **Linux:** use [swiftly](https://www.swift.org/install/): `swiftly install 6.3.2`.\n\nNote that swiftly installs the *toolchain*; the WebAssembly SDK is a separate\ncross-compilation target, added with `swift sdk install` (step 1) on either OS.\n\n```bash\n# 1. Install the WASM SDK (once) — needed at build time, binary or source\nswift sdk install \\\n  https://download.swift.org/swift-6.3.2-release/wasm-sdk/swift-6.3.2-RELEASE/swift-6.3.2-RELEASE_wasm.artifactbundle.tar.gz \\\n  --checksum a61f0584c93283589f8b2f42db05c1f9a182b506c2957271402992655591dd7c\n\n# 2. Install the swiflow CLI (prebuilt: macOS arm64 / Linux x86_64)\ncurl -fsSL https://raw.githubusercontent.com/zzal/swiflow/main/install.sh | sh\n\n# 3. Scaffold and run, with state-preserving hot reload on every save\nswiflow init my-app\ncd my-app \u0026\u0026 swiflow dev      # → http://localhost:3000\n```\n\nThe installer detects your platform, verifies the download's checksum, and drops\nthe binary in `/usr/local/bin` (override with `SWIFLOW_INSTALL_DIR`, or pin a\nversion with `SWIFLOW_VERSION`). Prefer to build from source — or on an unlisted\nhost like an Intel Mac? Skip step 2 and run `swift build -c release --product\nswiflow`, then invoke the CLI from `./.build/release/swiflow`. Either way the\nbinary isn't fully standalone: it shells out to your Swift 6.3.2 toolchain and the\nWASM SDK from step 1 to build your app.\n\nRun `swiflow doctor` to verify your toolchain. Hacking on Swiflow itself? Add\n`--swiflow-source $(pwd)` to `init` so the new project depends on your local clone\ninstead of a published release.\n\n## The ecosystem\n\n| Module | What it is |\n| --- | --- |\n| `Swiflow` | Pure-Swift VDOM core: `VNode`, the patch diff, `@State` / `@Component`, and the `@resultBuilder` DSL. |\n| `SwiflowDOM` | WASM-only renderer + JavaScriptKit bridge. |\n| `SwiflowRouter` | Hash- and history-mode routing. |\n| `SwiflowQuery` | Async data layer — caching, dedup, stale-while-revalidate. |\n| `SwiflowFetcher` | Thin `fetch` wrapper for requests from Swift. |\n| `SwiflowStore` | Persisted app state (IndexedDB). |\n| `SwiflowUI` | Token-driven, accessible component library. |\n| `SwiflowTesting` | Headless test harness. |\n| `swiflow` (CLI) | `init` scaffolds · `build` wraps `swift package js` · `dev` runs the HMR server. |\n\n## Examples\n\nBrowse [`examples/`](examples/):\n\n- **HelloWorld** — the starter: a counter, SwiflowUI controls, a native `\u003cdialog\u003e`, a popover, and toasts.\n- **SwiflowUIDemo** — a gallery of the SwiflowUI components and theming.\n- **TodoCRUD** — list CRUD with bindings and forms.\n- **QueryDemo** — `SwiflowQuery` fetching and caching.\n- **MiniRouter** — `SwiflowRouter` routes and links.\n- **MissionControl** — a larger app: geolocated data with `SwiflowStore` persistence.\n- **AsyncFetch** — `.task` async effects.\n\n(Plus **EdgeCases**, a runtime/diff stress harness.) Serve one with `swiflow dev` from its directory.\n\n## Docs\n\nGuides live in [`docs/guides/`](docs/guides/): [SwiflowUI](docs/guides/swiflowui.md) ·\n[theming](docs/guides/swiflowui-theming.md) · [router](docs/guides/router.md) ·\n[query](docs/guides/query.md) · [forms](docs/guides/forms.md) ·\n[async tasks](docs/guides/async-tasks.md) · [testing](docs/guides/testing.md) ·\n[styling](docs/guides/styling.md) · [environment](docs/guides/environment.md) ·\n[DevTools](docs/guides/devtools.md) · [debugging WASM](docs/guides/debugging.md).\n\nA read-only **DevTools panel** (live component tree + `@State`) lives in\n[`devtools/`](devtools/) — a Chrome side panel (sideload via\n`chrome://extensions` → *Load unpacked*) and a Safari Web Inspector build\n([`devtools/safari/`](devtools/safari/) needs an Xcode conversion).\n\n## Performance \u0026 costs\n\n- **First visit:** ~1.8 MB gzipped WASM on the wire (a loading-percent overlay shows during the download) — comparable to a modest single-page app. Every PR enforces a bundle-size budget in CI.\n- **Repeat visits:** ~0 bytes — a service worker caches the WASM + JS runtime by content hash until you rebuild.\n- **Hot rebuild:** ~8 s WASM rebuild → HMR swap, with `@State` preserved.\n\nMeasured on an Apple M1 Max with Swift 6.3 / WASM SDK 6.3.2 — run the commands\nlocally to calibrate for your hardware.\n\n## Testing\n\n```bash\nswift test                   # ~1,000 Swift tests, 200+ suites (e2e auto-skips without the WASM SDK)\n(cd js-driver \u0026\u0026 npm test)   # 42 jsdom tests: driver, dev reload, service worker\n```\n\nPlaywright e2e (counter, router, progress overlay, SW cache) lives in\n[`Tests/playwright/`](Tests/playwright/) and is opt-in.\n\n## Contributing \u0026 license\n\nContributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Licensed under\n**Apache 2.0** ([LICENSE](LICENSE)).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzzal%2Fswiflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzzal%2Fswiflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzzal%2Fswiflow/lists"}