LivelyKernel / lively.next

This is the repository of the lively.next project (https://lively-next.org).
MIT License
63 stars 16 forks source link

Routing in `lively.next` #1479

Open linusha opened 1 month ago

linusha commented 1 month ago

This is more of a brain dump as of now, as I do not have a good solution to the problem yet. However, the following is something I want to continuously think about while working on the relaunch of the lively web page:

When building static websites, as opposed to truly interactive applications, one needs the capability to route between different URLs. The two most important benefits this brings is that

  1. It is possible to link to specific places on the site.
  2. One can use the browsers "back" button in the expected way.

For SPAs such as lively applications, the easiest and most flexible way of doing is by using hash routing.

The current way I implement this in the website is by instantiating multiple HashRouter instances (a class I implemented inside of the website project) which manage different prefixes of the page (e.g., there is a router solely responsible for all things under the /blog prefix). Then, I write specific bindings for every UI elements that should route somewhere.

The question this bags is twofold:

  1. Can we streamline this to provide an easily pluggable solution so that not every page needs to write all this boilerplate code?
  2. In the case that we cannot do 1, what is the cleanest way to order this boilerplate code, so that we can provide a passable "cook book" for this problem.
merryman commented 1 month ago

Once the basic implementation of the router is in place we can make it easily accessible via a custom ViewModel class that can then be parametrized like so:

const Webpage = component({
   defaultViewModel: RouterSubclass,
   viewModel: {
      'home': LandingPage,
      'about': AboutPage,
      'contact': ContactPage,
   }
  // ...
}); 

The Router- viewModel will then internally take care of any layout applications, component loads or swapping the morphs in response to navigation and url requests.

merryman commented 1 month ago

Another idea is to further supply the Router with fine grained state information about the components themselves. For instance we could store away the scroll information and some other custom viewModel property automatically in the router to reconstruct the state of a page more correctly, by wrapping the property values with a track() function.

  const AboutPage = component({
     defaultViewModel: AboutPageModel,
     viewModel: {
         selectedSlideNumber: track(0)
     },
     submorphs: [
        {
           name: 'scroll wrapper',
           scroll: track(pt(0,0)),
          submorphs: [
            // ...
          ]
        }
     ]
  });