max / quasi
1 file changed,
+40 insertions,
-0 deletions
| @@ -45,6 +45,46 @@ | |||
| 45 | 45 | //! a [`Destination::External`], and is left alone for the reason given there: a | |
| 46 | 46 | //! method that is ignored is simpler than two shapes of action. | |
| 47 | 47 | //! | |
| 48 | + | //! # A described route answers one [`Outcome`], and assumes a client that runs JS | |
| 49 | + | //! | |
| 50 | + | //! Decided 2026-08-28, `b4304bb1`. A route answers once. It does not answer one | |
| 51 | + | //! way for a client that arrived with htmx and another way for a client that | |
| 52 | + | //! brought no JS at all. This is a property of the vocabulary rather than a | |
| 53 | + | //! limitation of any host: a description says what changed, and something has to | |
| 54 | + | //! be running on the other end to apply that to part of a page. Progressive | |
| 55 | + | //! enhancement stays an Askama concern, in the templates a conversion has not | |
| 56 | + | //! reached. | |
| 57 | + | //! | |
| 58 | + | //! The position is a promise about who a described surface serves, so the | |
| 59 | + | //! evidence behind it travels with it. Measured across the MNW server on | |
| 60 | + | //! 2026-08-28: 72 sites branch on whether the request came from htmx, over 23 | |
| 61 | + | //! files, 56 of them under `src/routes/api/`. They are three shapes, and only | |
| 62 | + | //! the first is progressive enhancement. | |
| 63 | + | //! | |
| 64 | + | //! 1. **Re-render the whole page with the user's input preserved.** Three route | |
| 65 | + | //! files: `src/routes/auth.rs` (login), `pages/email_actions/password.rs` | |
| 66 | + | //! (password reset, with the emailed token intact), and | |
| 67 | + | //! `pages/public/join_wizard.rs` (username and email preserved). All three | |
| 68 | + | //! are public or auth routes. None is under `routes/pages/dashboard/`. | |
| 69 | + | //! 2. **Degrade to the error page.** htmx gets a toast or an inline status, a | |
| 70 | + | //! plain request gets the error. The dominant shape by far, and the one every | |
| 71 | + | //! dashboard site uses, all of them through a single `wizard_validation_toast` | |
| 72 | + | //! helper. There is no full-page re-render anywhere in the dashboard. | |
| 73 | + | //! 3. **Redirect or hand back a file.** `HX-Redirect` against a plain redirect, | |
| 74 | + | //! or a CSV or JSON download. Not a question about assembling a page. | |
| 75 | + | //! | |
| 76 | + | //! Every route doing real progressive enhancement is public, and the public tier | |
| 77 | + | //! stays in Askama, so the position costs nothing where conversion is planned. | |
| 78 | + | //! | |
| 79 | + | //! The consequence, stated so a later reader does not have to find it: describing | |
| 80 | + | //! a **public** page reopens this. A described public page is unreachable without | |
| 81 | + | //! JS. That is a product decision to make deliberately on the day it comes up, | |
| 82 | + | //! not a bug to file against the router. | |
| 83 | + | //! | |
| 84 | + | //! MNW's `src/fragment_redirect.rs` is a separate mechanism, sending a direct | |
| 85 | + | //! navigation to a fragment endpoint back to its parent page. It is not one of | |
| 86 | + | //! the 72 and does not bear on this. | |
| 87 | + | //! | |
| 48 | 88 | //! [`Destination`]: crate::Destination | |
| 49 | 89 | //! [`Destination::External`]: crate::Destination::External | |
| 50 | 90 | //! [`Action::method`]: crate::Action::method |