DEV Community

Cover image for a first look at elder.js: part 1 - setup

a first look at elder.js: part 1 - setup

ajcwebdev profile image ANTHONY_CAMPOLO Updated on ・7 min read

Elder.js is an opinionated static site generator and web framework for Svelte built with SEO in mind. Elder supports Server Side Rendering and Static Site Generation. It is the result of work to build and was purpose built to solve the unique challenges of building flagship SEO sites with 10-100k+ pages.

Elder Guide Co-Founder Nick Reese has worked on five major SEO properties over the past 14 years. After leading the transition of several complex sites to static site generators he loved the benefits of the Jamstack, but wished there was a better solution for complex, data intensive, projects.

As of September 2020, the team expects to maintain the project until at least 2023-2024. For a clearer vision of what is considered "in scope" and what isn't, see this comment.

Getting Started

We're going to use degit to download the Elder.js template. Here is a demo of the template.

Clone Template

I will name my project ajcwebdev-elder. Feel free to give your project a unique name, but make sure to use your own project's name for any terminal commands.

npx degit Elderjs/template ajcwebdev-elder
Enter fullscreen mode Exit fullscreen mode

This will create the starter project.


Install Dependencies

cd ajcwebdev-elder
npm install
Enter fullscreen mode Exit fullscreen mode

This will install dependencies from npm.


Create a GitHub repo

Give it the same name as your project.

git init
git add . && git commit -m "Initial commit"
git branch -M main
git remote add origin
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Start Project

npm start
Enter fullscreen mode Exit fullscreen mode

This will start the development server. Navigate to http://localhost:3000.


If everything worked you should see the default home page. There is a brief explanation of the starting template and instructions for setting up your development environment.


Developing using the Template:

As the page says, it's recommended that you run two separate terminals for development. One is for the server and the other is for watching your changes with Rollup so you don't have to restart your server on every change.

Terminal 1: Server

npm run dev:server
Enter fullscreen mode Exit fullscreen mode

This starts the dev server.



Terminal 2: Rollup

npm run dev:rollup
Enter fullscreen mode Exit fullscreen mode

This tells Rollup to watch your project.



Here is our project structure:


That's a lot of stuff. First we'll just look for our home page. Go to the src folder.


Inside the src folder is a routes folder with a home folder containing Home.svelte.


Svelte components are a superset of HTML and can have up to three main sections. All three sections are optional:

  • script
  • style
  • markup


  import HookDetail from '../../components/HookDetail.svelte';
  import BlogTeaser from '../../components/BlogTeaser.svelte';
  import Clock from '../../components/Clock.svelte';

  export let data, helpers;
  export let foo;

  const hooks = => (
    {...hook, link: helpers.permalinks.hooks({ slug: hook.hook })}
Enter fullscreen mode Exit fullscreen mode

Inside the script tags we setup hooks which we'll talk about in future parts and we import three components:

  • HookDetail
  • BlogTeaser
  • Clock


  .banner {
    padding: 1rem 2rem;
    background: #eee;
    border-radius: 2rem;
    margin-bottom: 1rem;
  .entries {
    display: grid;
    grid-template-columns: 1fr;
    margin: 3rem 0;

  @media (min-width: 768px) {
    .entries {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      margin: 3rem 0;
    :global(.entries .entry) {
      margin-right: 1rem;

  :global(.entry) {
    padding: 1rem;
    border: 1px solid #ddd;
    border-radius: 1rem;
    margin-bottom: 1rem;
    background: white;
  .about {
    margin-bottom: 2rem;

  @media (min-width: 768px) {
    .hydrate {
      display: grid;
      grid-template-columns: 80% 20%;

  .hooks {
    display: grid;
    grid-template-columns: 100%;

  @media (min-width: 768px) {
    .hooks {
      grid-template-columns: 50% 50%;
Enter fullscreen mode Exit fullscreen mode

We have a default style that we'll leave alone.


svelte:head is used to set the title of the page.

  <title>Elder.js Template: Home</title>
Enter fullscreen mode Exit fullscreen mode

Below svelte:head is a conditional that runs a test to make sure the hooks are working.

{#if data.testingHooks}
  <div class="banner">
    <p>Testing hooks worked</p>
    {#if data.cpus}
      <p>If you use Elder.js to build your site, it will span all {data.cpus.length} cpus listed below:</p>
        {#each data.cpus as cpu}
Enter fullscreen mode Exit fullscreen mode

The banner provides links to the docs and GitHub.

<div class="banner">
  <h1>Hello World: Welcome to Elder.js!</h1>

  <p>Woot! You've got Elder.js installed. This template is designed to show you the ropes of how things work.</p>
  <p>We've tried to make this site a bit of a tutorial, but be sure to check out the full <a href="">Elder.js docs.</a></p>
  <p>Enjoy playing around with Elder.js and, if you hit a snag with the template, open a <a href="">GitHub issue.</a></p>

Enter fullscreen mode Exit fullscreen mode


The BlogTeaser component displays a list of blog posts with a title and summary.

<div class="blog">
  <div class="entries">
    {#each as blog}
      <BlogTeaser {blog} {helpers} />
Enter fullscreen mode Exit fullscreen mode


The about section explains the different routes we will explore throughout the series.

<div class="about">
  <h2>About This Template</h2>
  <p>This example project is made up of 4 routes; you can find them by looking within the <span class="code">./src/routes/</span> folder. They are:</p>

    <li><a href={helpers.permalinks.simple({ slug: 'simple' })}>Simple</a> - A barebones route.</li>
    <li>Home - The page you are on.</li>
    <li>Blog - Linked from above, but you can also see a blog post by checking out: <a href={{ slug: 'getting-started' })}>'Getting Started'</a>.</li>
    <li>Hooks - These are how you customize Elder.js. Details are below, and we've used the <span class="code">hookInterface</span> to build out dedicated pages for each hook as well.</li>

  <p>The goal in showing off these 3 routes is to give you enough of an example to see how a site is built with Elder.js (but one that isn't too complex to overwhelm you).</p>
Enter fullscreen mode Exit fullscreen mode


The development environment section explains how to use the dev server and Rollup for local development.

  <h3>Development Environment:</h3>
  <p>If you ran <span class="code">npm start</span> to see this page, we recommend you stop that command. Instead, open two terminals and run:</p>

    <li><span class="code">npm run dev:server</span> - This uses nodemon to restart the development server when files change.</li>
    <li><span class="code">npm run dev:rollup</span> - This uses Rollup to recompile your Svelte templates as you change them.</li>

  <p><strong>Note:</strong> Make sure you also check out <code>npm run build</code>, which will statically generate this same site so that it can be deployed with a static site host such as Netlify, Cloudflare Workers, Vercel, or S3.</p>
Enter fullscreen mode Exit fullscreen mode


The hydrate section uses the Clock component to display a working clock.

<div class="hydrate">
  <div class="left">
    <h2>Partial Hydration:</h2>

    <p>Svelte.js shines at bringing interactivity to otherwise static websites.</p>
    <p>By default, Elder.js statically renders Svelte components, only mounting them in the browser when it encounters a Svelte component which includes the <code>hydrate-client={JSON.stringify({})}</code> prop. Note: the actual prop is 'hydrate-client={}' but Svelte doesn't render empty objects</p>
    <p>The <a href="">clock</a> on this page is an example of a component that has been hydrated on the client.</p>
    <p>This approach makes it easy to build SEO friendly websites, with Svelte for interactivity when needed.</p>
    <p>By default all hydrated components are lazy loaded with an intersection observer.</p>

  <div class="right">
    <Clock hydrate-client={{}} />
Enter fullscreen mode Exit fullscreen mode


The final section explains hooks.

<h2>The Hook Interface</h2>

<p>Once you've digested the guides above and understand how to handle client hydration, we encourage you to explore the hook interface below.</p>
<p>Hooks are the primary way to customize Elder.js and the list below outlines exactly what each hook can be used for.</p>
Enter fullscreen mode Exit fullscreen mode



The HookDetail component displays a list of hooks.

<div class="hooks">
  {#each hooks as hook, i}
    <HookDetail {hook} {i} hookEntityDefinitions={data.hookEntityDefinitions} />
Enter fullscreen mode Exit fullscreen mode


To make sure we have everything set up correctly we'll change the title and the banner.


<div class="banner">
Enter fullscreen mode Exit fullscreen mode

Return to your browser to see the change.


Discussion (2)

Editor guide
feldev profile image
Félix Paradis

Thanks for writing this!
Quick tip: put code in backticks rather than screenshoting your code editor. For the sake of accessibility and copy/pasting

ajcwebdev profile image

Hey Felix, yeah I'm in the process of switching all of the code in my articles to gists. I originally was using screenshots because I find that with a lot of these frameworks the syntax highlighting just doesn't work very well, but gists seem to get the job done for the most part.