▲ 3 r/Kotlin

I built Laydr: file-based, type-safe navigation for Compose Multiplatform and Android Compose

Hi,

I built **Laydr**, a file-based, type-safe navigation framework for Compose Multiplatform and Android Compose apps.

Repo: https://github.com/mobiletoly/laydr

I created Laydr because Compose navigation can become hard to see as an app grows: copied route strings, duplicated graph setup, repeated argument parsing, tab registries, layout wrappers,
and stale navigation glue all have to agree with each other.

The AHA moment with Laydr is that the route tree becomes the app map.

Instead of spreading route structure across constants and graph builders, you put routes in a visible `routes/` directory, add small route-local `Route.kt` declarations, and Laydr generates
the typed Kotlin wiring from that structure.

A route tree looks like this:

src/commonMain/kotlin/routes/
contacts/
Route.kt
Screen.kt
by_id/
Route.kt
Screen.kt
settings/
Route.kt
Screen.kt

That gives you generated route objects such as:

LaydrRoutes.Contacts
LaydrRoutes.Contacts.ById
LaydrRoutes.Settings

And app code navigates with generated destinations instead of raw strings:

navigator.push(
LaydrRoutes.Contacts.ById.destination(
id = LaydrRoutes.Contacts.ById.id("ada"),
),
)

Laydr gives you:

* filesystem routes under `routes/`
* route-local `Route.kt`, `Screen.kt`, and `Layout.kt` files
* typed destinations instead of copied route strings
* typed dynamic parameters instead of repeated argument parsing
* generated path builders when your app deliberately owns path state
* generated route maps and app graphs
* generated Compose route definitions for `LaydrRouteHost`
* generated Nav3 helpers for sections, stacks, payloads, and route results
* support for plain Compose hosting, Nav3 KMP, and AndroidX Navigation 3
* build-time route validation through the Gradle plugin
* optional route-local workflow for private multi-step flows inside an already matched route

The part I like most is that Laydr does not try to become your whole app architecture.

Your app still owns Compose UI, state, DI, ViewModels, repositories, tabs, labels, icons, chrome, auth, analytics, retained state, deep links, platform lifecycle policy, and `NavDisplay`.
Laydr gives those app-owned pieces stable generated route values to work with.

There are three main app shapes:

* Compose Multiplatform app with simple path state: use `LaydrRouteHost`
* Compose Multiplatform app with Nav3 stacks or tabs: use `laydr-nav3-kmp`
* Android-only Compose app with Google AndroidX Navigation 3: use `laydr-nav3-androidx`

Laydr is still v0, so APIs may change, but the current docs and examples are meant to be practical and runnable.

Examples included in the repo:

* `examples/compose-basic`
* `examples/nav3-kmp`
* `examples/nav3-kmp-shopping`
* `examples/nav3-androidx`

And yes, `docs/skills/laydr` is available if you want to copy a skillset so your AI agent can understand Laydr routing, generated APIs, Nav3 usage, workflow, validation, and troubleshooting
without wasting tokens.

Repo: https://github.com/mobiletoly/laydr

reddit.com
u/Adventurous-Action66 — 6 days ago
▲ 36 r/JetpackCompose+4 crossposts

goldr: Go + HTMX framework I’m already using in production

Hi,

I built goldr, a server-first Go framework for building templ + HTMX web applications. I created it because I wanted the structure and ergonomics of a modern web framework, but without moving my app into SPA, hydration, or client-state territory. I'm already using Goldr in production, and the main goal is to keep Go web apps easy to see, run, debug, and ship as they grow.

Repo: https://github.com/mobiletoly/goldr

Goldr gives you:

  • filesystem routes under app/routes
  • route-local pages, HTMX fragments, and POST actions
  • nested layouts based on the route tree
  • reusable mounted route subtrees, so the same workflow can live in multiple parts of an app without copying route folders
  • generated URL helpers, so templates and redirects do not copy path strings
  • visible HTMX in .templ files
  • live reload with route generation, templ generation, app restart, asset fingerprinting, and browser reload
  • fingerprinted and embedded static assets using simple directory conventions
  • CLI inspection for routes, layouts, HTMX references, and packaged assets
  • a browser visual inspector that can outline which layout, page, fragment, or labeled component produced a page region

The part I like most is that the app still feels like a Go app. Goldr does not own your server, middleware, auth, sessions, database layer, asset compiler, deployment, or client state. It gives structure around the boring repeated parts while leaving application policy explicit.

A route tree looks like this:

app/routes/
  layout.go
  layout.templ
  route.go
  page.templ
  users/
    route.go
    page.templ
    frag_table.templ
    by_id/
      route.go
      page.templ

Goldr turns that into generated net/http dispatch and URL helpers, while the source files stay ordinary Go and templ.

Goldr is still pre-v1, so APIs may change, but it is already useful enough that I'm using it for real production work.

Repo: https://github.com/mobiletoly/goldr

u/Adventurous-Action66 — 7 days ago
▲ 13 r/android_devs+3 crossposts

I released SQLiteNow for Flutter/Dart: SQL-first, type-safe SQLite codegen

Hey Flutter folks,

I just published the first Dart/Flutter release of SQLiteNow. If you used SQLDelight before with Kotlin Multiplatform - you would feel right at home.

Short version: SQLiteNow lets you keep your database schema and queries as normal .sql files, then generates typed Dart code around them: params, result models, migrations, transactions, query namespaces, and reactive watch() APIs.

It is not trying to hide SQLite behind a big ORM. The idea is closer to: write real SQL, keep full control over the database, but stop manually mapping rows and passing dynamic parameter maps everywhere. No plugins needed, you write your code in any editor that supports .sql files, you just use your knowledge of SQL and SQLite. Additionally there are annotations available as comments --@@{...} to shape and control data generated.

The part I personally care about is that SQLiteNow is not trying to make SQLite disappear. You still write normal SQLite:

  -- @@{ queryResult=TaskWithTags }
  SELECT
    t.id,
    t.title,
    t.completed,

    tag.id AS tag__id,
    tag.name AS tag__name

  /* @@{ dynamicField=tags,
         mappingType=collection,
         propertyType=List<TaskTag>,
         sourceTable=tag,
         collectionKey=tag__id } */
  FROM task t 
  LEFT JOIN task_tag tt ON tt.task_id = t.id
  LEFT JOIN tag ON tag.id = tt.tag_id
  ORDER BY t.id, tag.name;

and SQLiteNow generates the Dart result type and query method around it. So instead of hand-reading rows, building maps, or doing a second pass to group tags under tasks, you get a typed result shaped like your app actually wants:

  final tasks = await db.task.selectWithTags().asList();
  for (final task in tasks) {
    print('${task.title}: ${task.tags.map((t) => t.name).join(', ')}');
  }

That is the main difference from using sqlite3/sqflite directly: I still get real SQL, but not all the manual row mapping.

And yes, when you use a watch() - any changes to `task` or `tag` tables will reactively update your data.

Compared with higher-level database libraries, the design goal is a bit different too. SQLiteNow is very SQLite-specific and SQL-file-first. Schema, migrations, seed data, and queries live as SQL assets, and annotations are just SQL comments. I wanted the generated code to stay close to my domain model without moving the real database logic into a Dart DSL or ORM layer.

A bit of context: SQLiteNow originally started as a Kotlin Multiplatform project and KMP version is used in production by quite a few of people. And now Dart/Flutter packages are published on pub.dev.

There is also an optional sqlitenow_oversqlite package for sync/multi-device work, but you can ignore that completely if you only want local SQLite.

Current honest status:

- first public Dart/Flutter release, 0.9.0

- targets Dart VM and Flutter native runtimes through package:sqlite3

- web support is not public yet

- docs may still show some KMP history, but the Flutter path is there now

Links:

- GitHub: https://github.com/mobiletoly/sqlitenow-kmp

- Flutter docs: https://mobiletoly.github.io/sqlitenow-kmp/flutter/

- Runtime: https://pub.dev/packages/sqlitenow_runtime

- CLI: https://pub.dev/packages/sqlitenow_cli

- Optional sync runtime: https://pub.dev/packages/sqlitenow_oversqlite

I'd really appreciate feedback from people who build SQLite-heavy Flutter apps. Especially if you've used drift, sqflite, or handwritten sqlite3 code and have opinions about where this approach feels useful or annoying.

u/Adventurous-Action66 — 2 months ago