What you’ll have
- Columns and cards with stable positions
- Cards you can drag within a column and between columns
- Visual feedback while dragging, and a marker showing where the card will land
- A card that moves instantly and rolls back if the server refuses
Which parts of Feather this uses
Islands
The
draggable config and this.optimistic(), rather than hand-written pointer events.OrderingMixin
A position column, and
__ordering_scope__ to make it per-column.API routes
The first route in the series that returns JSON rather than HTML.
feather check
Two rules here catch an island nothing mounts, or a mount with no island.
Step 1: Scaffold
- Continue from part 2
- Start fresh
Nothing to do. You need the SQLite database, the
Column and Card models, the HTMX
routes and the two partials, all of which part 2 produced.Step 2: Run the prompt
The prompt
Step 3: Test it
- Grab a card by its handle and drag it. The card should dim while it moves.
- Drop it above or below another card in the same column.
- Drag one into a different column.
- Watch it land immediately rather than after a pause.
- Refresh. The positions held.
What the framework did
Ordering comes from a mixin.OrderingMixin brought position,
move_to(), insert_at_end() and reorder_all(). The service calls them; nothing
recalculates indexes by hand. See Models.
__ordering_scope__ is the line that matters. Without it, positions would be unique
across the whole cards table and two columns would fight over them. With it, each column’s
cards start again at zero.
The island didn’t call fetch. this.api is the CSRF-aware helper, and raw fetch
is a feather check error, because a POST without the token fails in
production and works in nobody’s test. See Islands.
Rollback is handled for you. this.optimistic() takes the
instant change and the server call, and rolls the first back if the second fails. That’s
the rollback you tested above.
The route returned JSON. Every other route so far returned HTML because the browser
was going to insert it. Here the island already moved the element and only needs to report
where it landed, so routes/api/ is the right home. See Routes.
Next: add real users
Google sign-in, roles, an admin panel, file attachments and PDF export.