# Pages & UI Routing

Nodewood uses Vue Router (opens new window) to handle routing. The main index.html loads a application template that then loads a page into that template's <router-view /> based on the route obtained from the URL.

For maximum build size efficiency, Webpack wants to know exactly what files to include in its build files as well as extra helper information about which files to bundle in which chunks. For this reason, it's best to manually specify your UI routes and pages instead of automatically how controllers do.

# Routes

All UI routes and pages for a feature are defined in its ui/init.js. As an example:

initRoutes(router) {
  const routes = [];

  routes.push({
    path: '/signup',
    name: 'signup',
    component: () => import(/* webpackChunkName: "users" */ '#features/users/ui/pages/Signup'),
  });

  return routes;
}

These parameters represent the minimum needed to define a route.

  • path: All paths are prefixed with /app, so the above example would actually be accessed at /app/signup.
  • name: The name of the route, useful for debugging.
  • component: This is the page that will be displayed in the main view section of the router.

# webpackChunkName

Essentially, all imports that share the same webpackChunkName will be bundled into the same chunk file. This allows the user to load the minimum amount of code necessary to boot the app, and progressively loads additional code as they navigate through your app. This results in faster load times for your users and solves a common complaint against single-page applications (slow load speed).

# meta

You can also include a meta object that can include the following options to configure your route within Nodewood specifically.

initRoutes(router) {
  const routes = [];

  routes.push({
    path: '/metaroute',
    name: 'metaroute',
    component: () => import(/* webpackChunkName: "meta" */ '#features/users/ui/pages/Meta'),
    meta: {
      public: true,
      routeTemplate: 'MinimalTemplate',
      admin: true,
      capabilities: ['general-access', 'special-section-access'],
    }
  });

  return routes;
}
  • public: Non-public pages (the default) will attempt to load the currently-logged in user. If this fails, the user is redirected to /app/login. Public pages will skip this check.
  • routeTemplate: This is the outer template to use to display the page within. The default is AppTemplate, while login and signup pages use MinimalTemplate, and admin pages use AdminTemplate. If you need further customization, you can create your own templates (refer to the UI configuration options for how to properly include those templates).
  • admin: These routes are only accessible by admin users (users whose account_type is set to admin). If a non-admin user attempts to navigate to a route with this option set, they will be redirected to /app.
  • capabilities: These routes are only accessible by users with a subscription that grants these capabilities. If a user without a subscription, or a subscription without these features attempts to navigate to a route with this option set, they will be redirected to /app/subscription. For more information, check the documentation about the Subscriptions Feature.

# Overwriting Nodewood routes

All routes from app will overwrite routes from wood, so if there is a route that exists in the default Nodewood route collection that you wish to display a different page, just add that route in a feature inside app, and the UI will direct to your page instead of Nodewood's.

# Removing Nodewood routes

Assume you wish to rename the /signup route and have it live at /purchase instead. You can create a new purchase route, but the old signup route will still exist. We can take advantage of the fact that routes in app take precedence, and create a new signup route, but have it route to the 404 page instead:

{
  path: '/signup',
  name: 'signup',
  component: () => import(/* webpackMode: "eager" */ '#ui/pages/Error404Page'),
  meta: {
    routeTemplate: 'MinimalTemplate',
    public: true,
  },
},

While a user trying to access the old route will be explicitly sent to the 404 page (instead of implicitly), the results are the same - the route for all intents and purposes does not exist anymore.

# Pages

Pages are stored in a feature's ui/pages folder, and are simply Vue components designed to take up an entire page. For example:

<template>
  <div class="card w-full sm:w-3/5 mx-auto">
    <h2 class="card-header">
      Example Page
    </h2>

    <div class="card-body">
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam pretium aliquam posuere.
        Vestibulum pharetra nisl vel risus facilisis sollicitudin. Nulla id velit at turpis
        scelerisque fringilla. Suspendisse ut maximus urna, vitae egestas elit. Quisque quis pharetra
        metus. Nulla efficitur eleifend diam, et euismod libero fringilla ac. Maecenas blandit, felis
        a tristique venenatis, dui ipsum tincidunt leo, vel vehicula ipsum dui id nisl. Cras
        tincidunt et erat eu molestie. Nunc sodales tellus aliquam diam fermentum lobortis. Phasellus
        sagittis, enim sed congue vulputate, ante odio porttitor turpis, fermentum euismod erat ex id
        neque. Etiam sodales eu velit in imperdiet. Duis consectetur nisl dictum sollicitudin
        finibus. Aliquam tellus lectus, mollis id mollis ac, iaculis ac sapien. Donec nec velit id
        sem aliquam dignissim. Proin et facilisis libero.
      </p>
    </div>
  </div>
</template>

<script>

export default {
  name: 'ExamplePage',
};
</script>

Note the use of Tailwind's responsive design classes (opens new window) in the first <div>. This page will be styled as a card that takes up 3/5ths of the page in desktop mode, and the full page (with small margins) in mobile mode. Keep this in mind when designing your pages to ensure mobile users can use your app easily.

# Adding a new page

To add a new page with some sample code to get you rolling, run:

nodewood add:page FEATURE NAME

Replace FEATURE with the name of the feature you wish to add a page for, and NAME with the name of the page you wish to create. (e.g.: nodewood add:page scheduling calendar to add CalendarsPage to the scheduling feature.) By default, a route for this page will be added to the feature's ui/init.js, but if you wish to add the route manually, add --no-init to the end of the command.