There may have been instances where old bookmarks broke after changes, but if that happened, it was due to changes in app behavior, not because of poor URL design. For example, I might have introduced breaking changes that made older URLs incompatible with newer app versions.
Most of the time, when I update an app, it’s to add features or options, which often means introducing additional URL fields. To maintain compatibility with older, simpler URLs, I usually add new routes rather than modify existing ones. That way, if someone opens the app with an outdated URL that lacks some parameters, those missing values simply fall back to defaults, and the app keeps working as expected.
EDIT
Thinking about it more, maintaining backward compatibility in URLs is actually a strong argument against tightly designing them up front. As the app evolves and its forms, options, and attributes change, we don’t want previously valid URLs to break just because the interface moved on.
The new version of the app might support things the old one didn’t, but that’s no reason to invalidate old URLs. So yes, it’s intentionally a bit of a mess: a well-structured app, with consistent forms and behavior, will inevitably accumulate outdated, deprecated, limited, but still functional, routes over time.
So this is a very interesting thread! keen to understand if we should switch strategy, we currently have a top level Anvil SPA which allows users to login and then decide what feature they wish to use, we the use and iframe to load the next level app, this inherits the jwt from top level.
I’d like to be able to use routing and it seems that we could merge what we have which allows multiple developers to work in isolation easily with routing,
Is this possible if we keep separate apps per function?
I’m inclined to make one app per user-role, but that could just be my desktop/SPA history speaking. It works best when there is a small number of roles, and when each user has only one role. At startup, the user logs in, and can quickly get to any of their queries, tools and responsibilities.
When it’s not pigeonholed like that, it looks like routing has a decided edge. Based on the discussion so far, routing seems to facilitate finer-grained access control, dynamically assessed and enforced per destination.
As I understand it so far, routing works within an App. I have no idea (yet) how it might be used to tie together a suite of Apps.
All my apps share the same user table, and several also share other core tables. Each app typically owns its own specific tables, and that often defines the boundary between apps. For example, the Crating app handles the final production and crating process—it’s the only one using the crates and trucks tables, but it shares tables like users and projects with other apps.
In cases where a shared table needed additional fields, like with projects, I created a second table rather than altering the shared one. I avoid using table reference links because they’re inflexible and can trigger unexpected round trips. Instead, I do separate queries on both tables using a common key (like the project number).
Linking between apps is simple: if the Crating app shows a job’s schedule, it includes a link to the Scheduling app with the job number in the URL.
This is a super important point. As soon as you give your app URLs, you lose control over where those URLs might be. Users might bookmark them, share them on social media, etc. Invalidating any of those can lose you users.