[NJS] Project structure and layout tips

:  ~ 2 min read

In the previous posts I mentioned file locations, but I haven't been explicit on what my structure is, so let's go through it:

- assets
    |___ javascripts (3rd party js)
    |___ stylesheets
    |___ images
    |___ files (random files I want to serve, like my resume)
- lib (let's call them helpers)
    |___ tasks (anything I want to run on Heroku)
    |_ db.js (for communicating with Postgres)
    |_ dropbox.js (for communicating with Dropbox APIs)
    |_ feed.js (just one function to create the feed.xml)
    |_ sitemap.js (just one function to create the sitemap.xml)
- models
    |_ post.js (the post model and its helpers)
    |_ dbResult.js
    |_ dbConfig.js
- public (public files)
    |_ robot.txt
    |_ humans.txt
    |_ favico.ico
- routes (for express, at least, these can also be considered controllers)
    |___ projects
        |___ all.js
        |___ my.js
        |___ projects.js
    |_ article.js
    |_ page.js
    |_ routes.js (to keep all routes in one file)
    |_ etc.js
- views
    |___ partials
        |_ header.ejs
        |_ footer.ejs
        |_ etc.ejs
    |_ about.ejs
    |_ index.ejs (the main page)
    |_ layout.ejs (the layout mentioned in one of the previous posts)
    |_ etc.ejs

It might not be the best structure, but it made sense to me.

As a layout tip: when you're creating partials, and your views' structure, try to do it from your code's perspective. For example the search page is a partial, and the main page is created from search + page navigation:

// Main page.
<% include ./partials/search %>

<% if (totalPages > 1) { %>
	<% include ./partials/page-navigation %>
<% } %>

It might seem counterintuitive, but the thing is that the search page is just the main page, but without page navigation, so it makes sense to compose the latter from the former:

// Search partial.
<% layout('layout') %>
<% block('head').append('<link rel = "stylesheet" href = "/assets/post.css">') %>

<div class="content">
<% posts.forEach(function(post) { %>
<% include ./post %>
<% }) %>
</div>

Now, if we replace <% include ./post %> with the actual contents of the file, the main page will ultimately look like this:

<% layout('layout') %>
<% block('head').append('<link rel = "stylesheet" href = "/assets/post.css">') %>

<div class="content">
  <article>
    <header>
      <h1>
        <a href="/<%= post.link %>"><%= post.title -%></a>
      </h1>
      <h4>
        <% var month = post.date.toLocaleString('en-us', { month: "short" }) %>
        <% var date = month + ' ' + post.date.getDate() + ', ' + post.date.getFullYear() %>
        <time datetime="<%= date %>">
        <%= date %>
        </time>
        <% if (post.readingTime) { %>
          : <span class="tilde">&nbsp;&#126;</span> <%= post.readingTime %>
        <% } %>
      </h4>
    </header>
    <%- post.body %>
  </article>
</div>

<% if (totalPages > 1) { %>
  <% include ./partials/page-navigation %>
<% } %>

which is just what we need!