Routing with shadow-grove

Hi everyone,

First, I am curious of how to implement routing with shadow-grove, particularly when there is a slash in the token… er, the path. Pardon me for not providing an example of code where this seems to fail for me—I will do so—but I wanted at first simply to ask if that be possible currently.

Routing is handled by first loading and installing the router in your :init-fn (ie. only done once on initial load). An example is here.

  (history/init! env/rt-ref
    {:start-token "/dashboard"
     :root-el root-el})

root-el is the outermost DOM element it should attach to. Could be js/document.body or so too. :start-token is the token it routes to if the app is opened without one. (eg. / becomes /dashboard on load). There are a few more options, which you may or may not need.

After that routing is handled via a :ui/route! event. The routing in the shadow-cljs UI is done here. Basically you translate that the URI is meant to represent as data and make the proper adjustments in the DB state.

That is it as far as the router is concerned. Everything else is you rendering your UI based on your DB state. There are no Route or Link components or any of that. You take a String and translate it to a proper piece of data.

In your UI if you want to link to some “route” you do so via normal links.

(<< [:a {:href "/foo"} "hello world"])

On click this will trigger the {:e :ui/route! :token "/foo" :tokens ["foo"]} event.

There is one helper, in cases where you use the :path-prefix option. Say your app root is /app and your app internal route would be /app/foo.

;; still emits /foo, and loads normally since it is outside the "app"
;; triggers no :ui/route! event.
(<< [:a {:href "/foo"} "hello world"])

;; combines :path-prefix with given path
(<< [:a {:ui/href "/foo"} "hello world"])

Basically :ui/href ensures to emit an app-specific path. You might not need it, but it works regardless of having a :path-prefix or not.

Redirects and route changes you can trigger from other events like this.

In the shadow-cljs :ui/route! handler you can see that it sets the ::m/current-page key. In the UI that is then queried and used here to decide which “page” to render.

Thanks!—this is all very helpful and will flesh out my understanding…

Say I wanted to have a route “/2022/11” (say for blog entries in the month of November 2022). I wonder if the error I am getting is related rather to my shadow-cljs config than shadow-grove. I’m getting a 404 (Not Found) on GET http://localhost:3000/2022/js/main.cljs.

This likely just means that you have the incorrect path in your HTML to include your JS.

<script src="js/main.js"> or so. Should be <script src="/js/main.js">. Note the extra / which makes it an absolute path. Otherwise the browser will interpret the location to be relativ to the page path, which ends up trying to include /2022/js/main.js which doesn’t exist.

:man_facepalming:
Haha, of course! Thank you :slight_smile: .