# Cascading Filesystem

The two main folders in your project, app and wood, are set up to be nearly-identical to each other in terms of sub-folder layout. This not only reduces the complexity of the mental model you have to understand in order to reference files in either folder, it enables the Cascading Filesystem that Nodewood uses to require files.

Whenever Nodewood encounters an import/require statement that beings with a #, it first attempts to require that file from the app folder, and if it cannot find it there, it attempts to require it from the wood folder. (If it fails there, it throws an error.) This means that you can effectively override any Nodewood file, simply by adding a replacement version of that file in the same location in app.

For example, assume we are importing the LoadingSpinner component for use in a page:

import LoadingSpinner from '#ui/components/LoadingSpinner';

First, Nodewood will attempt to load from ./app/ui/components/LoadingSpinner.vue. This will fail, because there is no file in that location. Next, it will check in ./wood/ui/components/LoadingSpinner.vue, which will succeed, and that file will be required.

But say you wanted to put your own spin (pun very much intended) on the LoadingSpinner component? All you need to do is place a file in ./app/ui/components/LoadingSpinner.vue and it will be required instead of the one in the wood folder.

For Vue components, you generally have to replace the entire component, as Vue components don't include well inside other Vue components, but for other Javascript classes, you can require a file from the wood folder directly and extend it, instead of replacing it entirely. For example, if you wanted to extend the UserController:

  1. First, run nodewood eject features/users/api/controllers/UsersController to create a copy of that file in the app folder.
  2. Change the contents of that file to:
const WoodUsersController = require('@wood/features/users/api/controllers/UsersController');

module.exports = class UsersController extends WoodUsersController {
  // Your code goes here

As you can see, requiring something with @wood/FOLDER requires the file directly from that sub-folder in the wood folder. From there, you can use normal JavaScript class extends syntax to build on the existing controller, instead of replacing it entirely with one of your own.


The one folder this does not apply to is the migrations folder. All migrations in both app and wood will be run when you run the nodewood migrate command, and attempting to add a similarly-named file to app that also exists in wood will cause an error.