Re-engineering the site

Putting new learnings into practice

Posted 2 months ago in code

Some background

In summer of 2017, I was very excited to unleash my latest project: a proper personal webapp to replace my very first static HTML site. You can read all about the thought process here and the technical decisions I made here. In reflection, my implementation largely aligned with my objectives for the site: I could write and edit posts from the deployed site itself and could edit static content and pages by simply redeploying to Heroku.

At the same time, it's pretty incredible how much you can learn in a year, and with those learnings entirely shift your perspective on certain topics. Today, I struggle to find myself wanting to build anything besides simple APIs in Rails. While I once valued the structure the framework lays out for the developer, I increasingly realized every new feature added is more of a band-aid than it is a well-designed programming pattern. What you gain in speed of initial development and consistency you often lose in flexibility and personal-preference. I'm sure it's possible to develop in such a way that does keep to good style and the like, but I find it particularly difficult to do so in Rails when compared to Node.

Rather, I've been developing almost exclusively in Node, largely because I've come to highly value how easy it is to use and import exactly what you need. Handlebars is a lighter, more intuitive ERB; Express paired with JSON is a more rapid, moldable, and intuitive backend than the PostgreSQL and Rails which held together my former app.

Diving into the code

In building this application I tested myself to keep the architecture and code as clean, DRY, and intuitive as possible. Here's a look at the file structure:

├─ public # Files accessible from the frontend │ ├─ img # Images │ │ └─ ... │ ├─ js # Frontend scripts │ │ └─ ... │ ├─ index.css # Compiled CSS file │ └─ ... # Favicon files ├─ src # Assets, data, and content │ ├─ assets │ │ └─ scss # Styles written in SCSS │ │ └─ ... │ ├─ json # Data for posts, projects, etc. │ │ └─ ... │ └─ views # Handlebars files │ ├─ layouts # Data for posts, projects, etc. │ │ └─ layout.hbs # Wrapper HTML for all pages │ ├─ partials # Data for posts, projects, etc. │ │ ├─ posts # HTML partial for each post │ │ │ └─ ... │ │ └─ ... # Other partials │ └─ ... # Page components ├─ .eslintrc # Documentation ├─ .gitignore # Files not included in git repo ├─ index.js # Configure express server ├─ package.json # Layout dependencies ├─ routes.js # App API's and routing ├─ ... # Yarn config files └─ README.md # Documentation

I exported this architecture to a boilerplate repository because I find it so universally useful as a starting point for Handlebars apps. I'm looking forward to using it in a variety of projects going forwards. The repository for the website itself can be found here.

As another testament to the architecture, each post is represented by a JSON file of the form:

{ "createdAt": "123...", "updatedAt": "123...", "title": "Title of the post", "slug": "title-of-the-post", "image": "...", "subtitle": "Subtitle of the post", "topics": [ "..." ] }

There is a corresponding Handlebars file in the /src/views/partials/posts directory indexed by the post's slug, in this case "title-of-the-post". This serves a dual function: (1) it determines the URL for the post and (2) the HTML content which makes up the post itself.

All data is served as simple JSON and is rendered by modular Handlebars components. Take, for example, how I render my education on the homepage:

# On the backend const education = require('./src/json/education'); ... router.get('/', (req, res) => { res.render('home', { title: 'Cameron Cabo', education, experiences, extracurriculars, posts: getRecentPosts(), projects: getRecentProjects(), isRootActive: true, }); });
# On the homepage <div class="marg-bot-2"> <h4 class="mono bold title">Education</h4> {#each education} {> education this} {/each} </div>
# On the education partial <div class="card"> <div class="flex-container"> <div class="flex"> <h4 class="marg-bot-0">{title}</h4> <p class="mono gray-text subtitle">{startYear} - {endYear} / {gpa} GPA</p> </div> {#if image} <div style="background-image: url(img/education/{image})" class="background-image"></div> {/if} </div> <p>{description}</p> </div>

Note that the {curly brackets} should be {{double}}...it's just easier to render this way.

Along the same lines, every page renders the same navbar and footer and keeps to a consistent use of cards, font sizes, and the like. It's simple and flexible—far more easy to iterate on than the Rails app ever was, and I'm excited to do that over the months and years to come.

Read More

← Back to all posts