{"id":49561449,"url":"https://github.com/makoni/swift-adwaita","last_synced_at":"2026-05-03T09:08:23.815Z","repository":{"id":346446876,"uuid":"1189801153","full_name":"makoni/swift-adwaita","owner":"makoni","description":"An imperative Swift 6 wrapper for GTK4 and libadwaita, designed for building native GNOME desktop applications.","archived":false,"fork":false,"pushed_at":"2026-04-29T17:41:25.000Z","size":29248,"stargazers_count":6,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-29T18:34:20.807Z","etag":null,"topics":["adwaita","gnome","gtk","libadwaita","linux","swift","swift6"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/makoni.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.txt","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},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":["https://nowpayments.io/donation/makoni"]}},"created_at":"2026-03-23T17:20:41.000Z","updated_at":"2026-04-29T17:41:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/makoni/swift-adwaita","commit_stats":null,"previous_names":["makoni/swift-adwaita"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/makoni/swift-adwaita","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makoni%2Fswift-adwaita","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makoni%2Fswift-adwaita/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makoni%2Fswift-adwaita/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makoni%2Fswift-adwaita/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/makoni","download_url":"https://codeload.github.com/makoni/swift-adwaita/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/makoni%2Fswift-adwaita/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32563577,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["adwaita","gnome","gtk","libadwaita","linux","swift","swift6"],"created_at":"2026-05-03T09:08:19.013Z","updated_at":"2026-05-03T09:08:23.802Z","avatar_url":"https://github.com/makoni.png","language":"Swift","funding_links":["https://nowpayments.io/donation/makoni"],"categories":[],"sub_categories":[],"readme":"# swift-adwaita\n\n[![CI](https://github.com/makoni/swift-adwaita/actions/workflows/ci.yml/badge.svg)](https://github.com/makoni/swift-adwaita/actions/workflows/ci.yml)\n[![Swift 6.2+](https://img.shields.io/badge/Swift-6.2+-F05138.svg)](https://swift.org)\n[![Documentation](https://img.shields.io/badge/Documentation-Online-0A84FF.svg)](https://spaceinbox.me/docs/swift-adwaita/documentation/adwaita)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.txt)\n\n\u003cimg alt=\"Swift Adwaita\" src=\"https://spaceinbox.me/images/swift-adwaita-2.webp\"\u003e\n\nAn imperative Swift 6 wrapper for [GTK4](https://docs.gtk.org/gtk4/) and [libadwaita](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/latest/), designed for building native GNOME desktop applications.\n\nDocumentation: [API Reference](https://spaceinbox.me/docs/swift-adwaita/documentation/adwaita)\n\n## Apps built with swift-adwaita\n- [Swifty Notes](https://github.com/makoni/swifty-notes-gtk)\n\n## Demo app\n\n\u003cimg alt=\"Swift Adwaita\" src=\"https://spaceinbox.me/images/swift-adwaita-demo.gif\"\u003e\n\n\n## Features\n\n- **Imperative API** — no declarative DSL; create and configure widgets directly\n- **177 widget wrappers** — 74 auto-generated Adwaita + 103 hand-written GTK widgets\n- **Zero raw pointers in public API** — all `OpaquePointer`/`gpointer` hidden behind Swift types\n- **Type-safe enums** — `SignalName`, `PropertyName`, `CSSClass`, `IconName` instead of raw strings\n- **Fluent setters** — method chaining: `Label(\"Hi\").halign(.center).cssClass(.title1)`\n- **Type-safe signals** — 50+ signal signatures with `@MainActor` closures\n- **Async/await** — `FileDialog.open()`, `UriLauncher.launch()`, `Clipboard.readText()`\n- **Keyboard shortcuts** — enum-based `Key` + `KeyModifiers` API\n- **Property bindings** — `GObjectRef.bind()` for reactive connections\n- **Container protocol** — unified `append()`/`remove()` for Box, ListBox, FlowBox, WrapBox, Carousel\n- **Convenience initializers** — `SwitchRow(title:)`, `PreferencesGroup(title:description:)`, etc.\n- **Menus \u0026 actions** — `GMenuRef`, `SimpleAction`, `MenuButton`\n- **Drag \u0026 drop** — `DragSource`, `DropTarget`\n- **CSS support** — `CSSProvider` + type-safe `CSSClass` enum\n- **Animations** — `TimedAnimation`, `SpringAnimation` with callbacks\n- **Drawing** — `DrawingArea` with `CairoContext` wrapper\n- **Text attributes** — `TextAttributes` for styling entry text (bold, italic, color)\n- **Media playback** — `MediaStream`, `Video`, `MediaControls`\n- **Localization** — gettext integration via `localized()` and `String.localized`\n- **@Setting property wrapper** — type-safe GSettings binding\n- **Adaptive layout** — `Breakpoint.minWidth()`, `Breakpoint.maxWidth()` helpers\n- **Swift 6 concurrency** — full `@MainActor` isolation, `Sendable` types\n- **1194 tests on Linux / 1181 on macOS**, **78 demo examples**, **CI on Ubuntu + macOS**\n\n## Requirements\n\n- Swift 6.2+\n- libadwaita 1.5+ development headers\n- GtkSourceView 5 development headers\n- Linux **or** macOS 13+ (Apple Silicon recommended; Intel best-effort)\n\n### Ubuntu/Debian\n\n```bash\nsudo apt install libadwaita-1-dev libgtksourceview-5-dev\n```\n\n### Fedora\n\n```bash\nsudo dnf install libadwaita-devel gtksourceview5-devel\n```\n\n### macOS (Homebrew)\n\n```bash\nbrew install libadwaita gtksourceview5 pkgconf\n```\n\n`libadwaita` pulls `gtk4`, `glib`, `cairo`, `pango`, `gdk-pixbuf`,\n`harfbuzz`, `librsvg`, and ~30 more transitive dependencies — about\n1.5–2 GB on disk after install.\n\n**Runtime env var (required).** libadwaita aborts at startup with\n`No GSettings schemas are installed on the system` unless GLib can\nfind Homebrew's compiled schemas. Add this to your shell rc, or\nprepend it to any `swift run …` / `swift test …` invocation:\n\n```bash\nexport XDG_DATA_DIRS=\"/opt/homebrew/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}\"\n```\n\nIntel Macs: replace `/opt/homebrew` with `/usr/local`.\n\n\u003e macOS targets the GTK4 Quartz backend, so HeaderBar / Toast / native\n\u003e dialog chrome will look like libadwaita on macOS rather than native\n\u003e Cocoa. Build/test cycles are fully supported; Flatpak distribution is\n\u003e Linux-only.\n\n## Installation\n\nInstall the system packages above first, then add this package to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/makoni/swift-adwaita.git\", branch: \"main\"),\n],\ntargets: [\n    .executableTarget(\n        name: \"MyApp\",\n        dependencies: [\n            .product(name: \"Adwaita\", package: \"swift-adwaita\"),\n        ]\n    ),\n]\n```\n\n## Quick Start\n\n```swift\nimport Adwaita\n\n@MainActor\nfunc buildApp() {\n    let app = Application(id: \"com.example.HelloWorld\")\n\n    app.onActivate {\n        let window = ApplicationWindow(application: app)\n        window.title = \"Hello\"\n        window.defaultWidth = 400\n        window.defaultHeight = 300\n\n        let box = Box(orientation: .vertical, spacing: 12)\n        box.setMargins(24)\n\n        let label = Label(\"Hello from swift-adwaita!\")\n            .cssClass(.title1)\n        box.append(label)\n\n        let button = Button(label: \"Click Me\")\n            .cssClass(.suggestedAction)\n            .cssClass(.pill)\n            .halign(.center)\n        button.onClicked {\n            label.text = \"Button clicked!\"\n        }\n        box.append(button)\n\n        window.setContent(box)\n        window.present()\n    }\n\n    app.run()\n}\n\nbuildApp()\n```\n\n## Architecture\n\nThree-layer design:\n\n```\nCAdwaita          System library (pkg-config: libadwaita-1)\n  │\nGObjectSupport    GObject lifecycle (ARC), signals, Variant, GValue\n  │\nAdwaita           Widget wrappers (74 generated + 103 hand-written)\n```\n\n### Key Types\n\n| Type | Description |\n|------|-------------|\n| `GObjectRef` | Base class — GObject lifecycle with ARC |\n| `Widget` | Base for all GTK/Adwaita widgets |\n| `SignalConnection` | Handle for signal connections |\n| `Application` | App entry point (`AdwApplication`) |\n| `ApplicationWindow` | Main window |\n\n### Protocols\n\n| Protocol | Purpose | Conforming Types |\n|----------|---------|-----------------|\n| `ListModelConvertible` | Pass models to list views | `ListStore`, `StringList`, `FilterListModel`, `SortListModel`, `MapListModel`, `FlattenListModel`, `TreeListModel`, `SelectionFilterModel` |\n| `SelectionModelConvertible` | Pass selection to views | `SingleSelection`, `MultiSelection`, `NoSelection` |\n| `Container` | Widgets with append/remove | `Box`, `ListBox`, `FlowBox`, `WrapBox`, `Carousel` |\n| `Swipeable` | Swipe gesture target | `Carousel`, `NavigationView`, `OverlaySplitView` |\n\n### Type-Safe Enums\n\n| Enum | Replaces | Example |\n|------|----------|---------|\n| `SignalName` | `\"clicked\"` | `.clicked`, `.changed`, `.notify(\"title\")` |\n| `PropertyName` | `\"active\"` | `.active`, `.title`, `.custom(\"my-prop\")` |\n| `CSSClass` | `\"suggested-action\"` | `.suggestedAction`, `.pill`, `.title1` |\n| `IconName` | `\"go-next-symbolic\"` | `.goNext`, `.dialogError`, `.custom(\"my-icon\")` |\n\n### Widget Categories\n\n**Layout:** `Box`, `Stack`, `Grid`, `Overlay`, `FlowBox`, `Clamp`, `Paned`, `WrapBox`, `CenterBox`, `Fixed`\n\n**Navigation:** `NavigationView`, `NavigationSplitView`, `OverlaySplitView`, `TabView`, `ViewSwitcher`, `Notebook`, `Carousel`\n\n**Input:** `Button`, `Entry`, `Switch`, `CheckButton`, `ToggleButton`, `Scale`, `SpinRow`, `SearchEntry`, `DropDown`, `Calendar`, `ToggleGroup`\n\n**Display:** `Label`, `Image`, `Picture`, `Spinner`, `ProgressBar`, `LevelBar`, `Avatar`, `Banner`, `Separator`, `Video`\n\n**Lists:** `ListBox`, `ActionRow`, `ExpanderRow`, `ComboRow`, `SwitchRow`, `ButtonRow`, `PreferencesGroup`\n\n**Virtualized Lists:** `ListView`, `GridView`, `ColumnView` + `ListStore`, `StringList`, `SignalListItemFactory`, `TreeListModel`, `FilterListModel`, `SortListModel`\n\n**Containers:** `ScrolledWindow`, `ToolbarView`, `HeaderBar`, `BottomSheet`, `Frame`, `Expander`, `Revealer`, `ActionBar`\n\n**Dialogs:** `AlertDialog`, `Dialog`, `AboutDialog`, `PreferencesDialog`, `FileDialog`\n\n**Menus:** `MenuButton`, `PopoverMenu`, `PopoverMenuBar`, `SplitButton`, `GMenuRef`, `SimpleAction`\n\n**Event Controllers:** `GestureClick`, `GestureDrag`, `GestureLongPress`, `GestureSwipe`, `EventControllerKey`, `EventControllerMotion`, `EventControllerScroll`, `EventControllerFocus`, `DragSource`, `DropTarget`, `ShortcutController`\n\n**Feedback:** `Toast`, `ToastOverlay`, `EmojiChooser`\n\n**Styling:** `CSSProvider`, `CSSClass`, `StyleManager`, `TextAttributes`\n\n**Animation:** `TimedAnimation`, `SpringAnimation`, `CallbackAnimationTarget`, `PropertyAnimationTarget`\n\n**Media:** `MediaStream`, `Video`, `MediaControls`\n\n**Drawing:** `DrawingArea`, `CairoContext`\n\n**System:** `Clipboard`, `Display`, `Monitor`, `UriLauncher`, `Settings`\n\n## Examples\n\n### Fluent Setters\n\n```swift\nlet label = Label(\"Welcome\")\n    .halign(.center)\n    .vexpand()\n    .margins(24)\n    .cssClass(.title1)\n    .tooltip(\"A greeting label\")\n\nlet button = Button(icon: .goNext)\n    .cssClass(.suggestedAction)\n    .cssClass(.circular)\n```\n\n### Type-Safe Icons and CSS\n\n```swift\nlet img = Image(icon: .dialogInformation)\nlet btn = Button(icon: .documentSave, onClicked: { print(\"Saved!\") })\n\nlabel.addCSSClass(.dimLabel)\nlist.addCSSClass(.boxedList)\nbutton.addCSSClass(.destructiveAction)\n```\n\n### Dialogs, clipboard, URI launching\n\nEvery async-looking surface in swift-adwaita ships in two shapes:\n\n- A **callback form** — `…(parent: window) { result in … }`. The closure runs on the main actor from the GLib main loop. **Use this inside a running GTK application** (any handler called from `onClicked` / `onActivate` / a GTK signal in general).\n- An **`async` form** — `try await …`. Convenient in tests, macOS CLIs, or anywhere something else is draining Swift's `DispatchQueue.main`. Don't use it inside a `g_application_run` app.\n\n#### Why the split\n\nSwift's default `MainActor` executor is `DispatchQueue.main`, and the GLib main loop does not drain it — so a `Task { @MainActor in await dialog.open(...) }` kicked off from a button click just sits there and the dialog never appears. The callback forms side-step Swift Concurrency entirely and go through a GLib-native `GAsyncReadyCallback`, which GLib's loop does dispatch.\n\n#### Callback form (prefer this in GTK apps)\n\n```swift\nlet dialog = FileDialog()\ndialog.title = \"Open a File\"\n\nopenButton.onClicked {\n    dialog.open(parent: window) { result in\n        switch result {\n        case let .success(path?): print(\"Selected: \\(path)\")\n        case .success(nil):       print(\"User cancelled\")\n        case let .failure(error): print(\"Error: \\(error.message)\")\n        }\n    }\n}\n\n// Clipboard — same idea, no Result wrapping because there's no error domain.\nwidget.clipboard.readText { text in\n    label.text = text ?? \"\"\n}\n\n// URI launcher.\nUriLauncher(uri: \"https://gnome.org\").launch(parent: window) { success in\n    print(\"Launched: \\(success)\")\n}\n```\n\nThe same shape is available on `FileDialog.save/selectFolder`, `ColorDialog.chooseRGBA`, `FontDialog.chooseFont`, `Clipboard.readTexture`, and `Texture.load(from:completion:)`.\n\n#### Async form (tests / non-GTK)\n\n```swift\nlet path = try await dialog.open(parent: window) // ok in XCTest, don't do this inside onClicked.\n```\n\n### Adaptive Layout\n\n```swift\nlet bp = Breakpoint.maxWidth(500)\nbp.addSetter(box, property: .custom(\"orientation\"), value: \"vertical\")\nbp.onApply { sidebar.visible = false }\nbp.onUnapply { sidebar.visible = true }\nwindow.addBreakpoint(bp)\n```\n\n### Drawing\n\n```swift\nlet da = DrawingArea()\nda.contentWidth = 200\nda.contentHeight = 200\nda.setDrawFunc { cr, width, height in\n    cr.setSourceRGB(0.2, 0.4, 0.8)\n    cr.roundedRectangle(x: 10, y: 10, width: 180, height: 180, radius: 20)\n    cr.fill()\n}\n```\n\n### Keyboard Shortcuts\n\n```swift\nbutton.addKeyboardShortcut(key: .s, modifiers: .control) {\n    print(\"Save!\")\n    return true\n}\n\nwidget.addKeyboardShortcut(key: .z, modifiers: [.control, .shift]) {\n    print(\"Redo!\")\n    return true\n}\n```\n\n### Menus \u0026 Actions\n\n```swift\nlet menu = GMenuRef()\nmenu.append(\"Cut\", action: \"win.cut\")\nmenu.append(\"Copy\", action: \"win.copy\")\n\nlet menuBtn = MenuButton()\nmenuBtn.iconName = \"open-menu-symbolic\"\nmenuBtn.setMenuModel(menu)\n\nlet action = SimpleAction(name: \"cut\")\naction.onActivate { print(\"Cut!\") }\nwindow.addAction(action)\n```\n\n### Localization\n\n```swift\nsetTextDomain(\"myapp\")\nlet greeting = localized(\"Hello\")\nlet label = Label(\"Welcome\".localized)\n```\n\n### Virtualized Lists\n\n```swift\nvar items = [\"Apple\", \"Banana\", \"Cherry\"]\nlet store = ListStore()\nfor _ in items { store.appendPlaceholder() }\n\nlet factory = SignalListItemFactory()\nfactory.onSetup { listItem in\n    listItem.child = Label(\"\")\n}\nfactory.onBind { listItem in\n    listItem.child?.cast(Label.self).text = items[listItem.position]\n}\n\nlet selection = SingleSelection(model: store)\nlet listView = ListView(model: selection, factory: factory)\n```\n\n### Drag \u0026 Drop\n\n```swift\nlet drag = DragSource()\ndrag.setTextContent(\"Hello!\")\nsourceWidget.addController(drag)\n\nlet drop = DropTarget.forText()\ndrop.onDrop { text in\n    if let text { label.text = text }\n    return true\n}\ntargetWidget.addController(drop)\n```\n\n### Custom CSS\n\n```swift\nCSSProvider.loadGlobal(\"\"\"\n.my-widget {\n    background: linear-gradient(135deg, @accent_bg_color, @headerbar_bg_color);\n    border-radius: 12px;\n    padding: 24px;\n}\n\"\"\")\nwidget.addCSSClass(\"my-widget\")\n```\n\n## Demo App\n\nAn interactive gallery with 78 examples showcasing every widget:\n\n```bash\nswift run DemoApp\n```\n\nFeatures sidebar navigation with search, source code viewer, and windowed demos for navigation/window-level widgets.\n\n## Building\n\n### Linux\n\n```bash\nswift build                      # Build library\nxvfb-run swift test --no-parallel   # Run the test suite under a virtual display\nswift run DemoApp                # Launch demo gallery\n```\n\n### macOS\n\n```bash\nswift build                      # Build library\n\n# Tests need GSettings schemas at runtime.\nXDG_DATA_DIRS=/opt/homebrew/share swift test --no-parallel\n\n# DemoApp likewise:\nXDG_DATA_DIRS=/opt/homebrew/share swift run DemoApp\n```\n\nFor an Xcode-driven build that produces a regular macOS `.app` bundle\n(Cmd+R, breakpoints, Archive), see `examples/macos/DemoApp/` — it's\na working starter project that wraps the demo gallery via the\n`DemoAppLib` library product.\n\n\u003e Linux runs the test suite via swift-testing; macOS runs an XCTest\n\u003e mirror suite under `Tests/AdwaitaTests/macOS/` because swift-testing's\n\u003e per-test autorelease pool transitions corrupt memory after `gtk_init`\n\u003e registers Cocoa CFRunLoop callbacks. Both paths exercise the same\n\u003e logic. If you add a new test, place the swift-testing version under\n\u003e `Tests/AdwaitaTests/` (gated `#if !os(macOS)`) and an XCTest mirror\n\u003e under `Tests/AdwaitaTests/macOS/` (gated `#if os(macOS)`).\n\n## Distribution with Flatpak\n\nFlatpak is the recommended way to distribute GTK4/libadwaita apps on Linux. The GNOME runtime provides GTK4 and libadwaita, and the Swift SDK extension provides the compiler — your app only ships its own binary.\n\n### Prerequisites\n\nInstall Flatpak tools and runtimes:\n\n```bash\n# Install flatpak-builder\nsudo apt install flatpak-builder   # Ubuntu/Debian\nsudo dnf install flatpak-builder   # Fedora\n\n# Install GNOME SDK and Swift extension\nflatpak install flathub org.gnome.Sdk//48 org.freedesktop.Sdk.Extension.swift6//24.08\n```\n\n### Flatpak Manifest\n\nCreate a manifest file (e.g., `com.example.MyApp.yml`):\n\n```yaml\napp-id: com.example.MyApp\nruntime: org.gnome.Platform\nruntime-version: \"48\"\nsdk: org.gnome.Sdk\nsdk-extensions:\n  - org.freedesktop.Sdk.Extension.swift6\ncommand: MyApp\n\nfinish-args:\n  - --share=ipc\n  - --socket=fallback-x11\n  - --socket=wayland\n  - --device=dri\n\nbuild-options:\n  append-path: /usr/lib/sdk/swift6/bin\n  prepend-ld-library-path: /usr/lib/sdk/swift6/lib\n\nmodules:\n  - name: MyApp\n    buildsystem: simple\n    sources:\n      - type: dir\n        path: .\n    build-commands:\n      - swift build -c release --product MyApp --static-swift-stdlib\n      - install -Dm755 .build/release/MyApp /app/bin/MyApp\n      - install -Dm644 com.example.MyApp.desktop /app/share/applications/com.example.MyApp.desktop\n      - install -Dm644 com.example.MyApp.metainfo.xml /app/share/metainfo/com.example.MyApp.metainfo.xml\n      - install -Dm644 com.example.MyApp.svg /app/share/icons/hicolor/scalable/apps/com.example.MyApp.svg\n```\n\nKey points:\n- `--static-swift-stdlib` links the Swift runtime statically — the SDK extension is only needed at build time\n- The GNOME runtime provides GTK4 and libadwaita at runtime\n- You also need a `.desktop` file, `metainfo.xml`, and an app icon\n\n### Build and Run\n\n```bash\n# Build and install locally\nflatpak-builder --force-clean --user --install build-dir com.example.MyApp.yml\n\n# Run\nflatpak run com.example.MyApp\n```\n\n### Demo App Flatpak\n\nThe included DemoApp has a complete Flatpak setup in the `flatpak/` directory:\n\n```bash\nflatpak-builder --force-clean --user --install build-dir flatpak/io.github.makoni.SwiftAdwaitaDemo.yml\nflatpak run io.github.makoni.SwiftAdwaitaDemo\n```\n\nFor more details, see the \u003cdoc:FlatpakDistribution\u003e guide.\n\n## License\n\nMIT License. See [LICENSE.txt](LICENSE.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmakoni%2Fswift-adwaita","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmakoni%2Fswift-adwaita","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmakoni%2Fswift-adwaita/lists"}