AkashaCMS project directories


Getting started with AkashaCMS

Initializing an AkashaCMS project

AkashaCMS project directories

Structure of the Rendered Output Directory

Content files

Templates, Partials, Page Layout, and server-side DOM Manipulation

Project configuration

Theming and CSS/JavaScript frameworks

Using plugins in AkashaCMS projects

Hello, World! This is a new world. Maybe. Game changer? Or unreliable? Better? Try again? Better? Hurm.

As we said earlier a typical AkashaCMS project has these directories:

  • assets is a directory structure containing project assets
  • documents is a directory structure containing the content for the project
  • layouts contains page layout templates used in the project
  • partials contains template snippets used in the project
  • out is the output directory

That's nice and straightforward and simple, yes? But, AkashaCMS supports more flexibility than that, which came with a bit of complexity.

These three use cases drove the development of this feature:

  1. AkashaCMS plugins might provide prebaked Assets, Layouts or Partials.
  2. One AkashaCMS plugin, or an AkashaCMS project, might want to override a file in an Assets, Layouts or Partials directory.
  3. An AkashaCMS project might want to assemble content from several sources.

This led to two concepts:

  1. Stacked directories where there are multiple instances of a given directory
  2. Mounting one or more directories inside the Documents directory

For the rest of this discussion it will be useful to refer to (github.com) the Configuration file for this website.

Stacked directories and overridable files

AkashaCMS plugins supply code that extends or modifies AkashaCMS behavior. A typical case is for a plugin to define a custom tag (using Mahabhuta), and for the tag to have a default template in the Partials directory. This means the plugin has its own partials directory, while the AkashaCMS project also has a partials directory. Since there are several plugins, each with its own partials directory, how does AkashaRender decide which directory from which to retrieve the template?

Both the plugin definition, and the AkashaCMS project configuration, use the same method:

config.addPartialsDir('partials');

The addPartialsDir method adds a directory the partialDirs array in the configuration object. There are similar methods and arrays for Assets, Documents and Layouts, but lets focus on Partials. The config.addPartialsDir method will be called multiple times, each one adding a directory name to the partialDirs array.

It's helpful to think of the partialDirs array as a stack of directories, one on top of the other. To look for a file, we look for which directory/ies in the stack contains this file, using the top-most file.

For example, to render a Partial template, AkashaRender will be given a path like ak_toc_group_element.html.njk. This template is used in constructing a table of contents for a given page, and there is an implementation in both the @akashacms/plugins-base and @akashacms/theme-bootstrap plugins. Further, an AkashaCMS project might have its own implementation of this template. AkashaRender searches in each of the directories named in partialDirs, and it returns the first match it finds.

That's the key pattern: To search through an array of directories, returning the first matching file.

Going back to the configuration you see this code snippet:

config.addPartialsDir('partials');
...
config
    .use(require('@akashacms/theme-bootstrap'))
    .use(require('@akashacms/plugins-base'), {
        generateSitemapFlag: true
    })
    .use(require('@akashacms/plugins-breadcrumbs'))
    ...

Each of these config.addPartialsDir('partials') invocations add a directory to the partialDirs array. The result is an array containing these entries

  • partials
  • /path/to/PROJECT-DIR/node_modules/@akashacms/theme-bootstrap/partials
  • /path/to/PROJECT-DIR/node_modules/@akashacms/plugins-base/partials
  • /path/to/PROJECT-DIR/node_modules/@akashacms/plugins-breadcrumbs/partials
  • ...

To view the full list run akasharender config config.js and look for partialDirs.

When AkashaRender calls findPartial('ak_toc_group_element.html.njk') it looks in each of these directories. The question is, since there are at least two instances of this file, how does it decide which to use?

The simple answer is that it returns the first file it finds. The findPartial function searches the directories in order. Given this arrangement, the instance in @akashacms/theme-bootstrap will be returned because it appears first in the partialDirs array.

Again, the same algorithm is used for Assets, Documents, and Layouts.

Mounting directories

Some projects need to assemble content from multiple locations. For example a website for a software product might have content from the marketing, engineering, or tech-pubs teams. It's best if each team is able to work on its own, and that somehow the content be merged into one website. In this section lets discuss how that's done.

Refer back to the config.js for the AkashaCMS website, and you'll find a long list of declarations like this:

config.addDocumentsDir({
    src: 'node_modules/@akashacms/plugins-base/guide',
    dest: 'plugins/base'
})

This is different from the config.addPartialsDir('partials') case we just discussed. What's going on?

We've supplied an object with two fields, src and dest. The src field refers to a directory within node_modules and if you consult that directory you'll find index.html.md and some other content files. The dest field is interpreted as a location within the Documents directory structure.

Each module in the AkashaCMS project is in its own Github repository, and many of the modules are distributed through the npm repository. We decided that documentation for each plugin should be in a guide directory. What we're doing is to assemble those guide directories so they are used on the AkashaCMS website.

Some examples are:

Project Path Mounted to
@akashacms/plugins-base node_modules/@akashacms/plugins-base/guide plugins/base
AkashaCMS Built-In node_modules/akasharender/built-in-guide plugins/built-in
@akashacms/plugins-authors node_modules/@akashacms/plugins-authors/guide plugins/authors
@akashacms/plugins-booknav node_modules/@akashacms/plugins-booknav/guide plugins/booknav
@akashacms/plugins-blog-podcast node_modules/@akashacms/plugins-blog-podcast/guide plugins/blog-podcast
@akashacms/plugins-breadcrumbs node_modules/@akashacms/plugins-breadcrumbs/guide plugins/breadcrumbs

There are a lot more of these.

The resulting rendered output directory contains this:

$ tree -d out/plugins
out/plugins
├── adblock-checker
├── affiliates
├── akasharender-epub
│   └── img
├── authors
├── base
├── blog-podcast
├── booknav
├── breadcrumbs
├── built-in
├── document-viewers
├── embeddables
├── external-links
├── footnotes
├── tagged-content
└── theme-bootstrap
    └── img

17 directories

There is no single input directory structure. Instead there are several input directories, each coming from their own Github repository, and each virtually mounted into into the documents directory.

In the scenario named earlier, the configuration might be:

config
    .addDocumentsDir({
        src: '/path/to/marketing/content',
        dest: 'marketing'
    })
    .addDocumentsDir({
        src: '/path/to/support/content',
        dest: 'support'
    })
    .addDocumentsDir({
        src: '/path/to/documentation/content',
        dest: 'docs'
    })
    .addDocumentsDir({
        src: '/path/to/blog/content',
        dest: 'blog'
    })

How you organize this is up to you.

This demonstrates that AkashaCMS can be used to draw together content from any number of sources.

A directory for rendered output

We have one last directory to discuss, out, which we described as holding the rendered output from the project.

The final result of AkashaCMS is a collection of rendered files, and this directory is where those files land.

The directory can have any name you like. In config.js simply call this method:

config.setRenderDestination('rendered-output');

Feel free to give it any name you like. If your config.js does not call this method, the default name is out.

(disqus.com) comments powered by Disqus

(twitter.com)

(www.facebook.com) Follow Node.js Web Development on Facebook