Sweet! So you've got the Elder.js starter template up and running. What's next?
This project is structured to follow the required Elder.js folder structure which you can see below, but in short you've got several routes in the ./src/routes/
folder.
Each of these routes are designed to showcase something different.
./src/routes/home/route.js
file and look at how the all
and permalink
functions work. Then look at the Home.svelte
to see what is going on there.@elderjs/plugin-markdown
which is configured in your elder.config.js
. You can find this page's markdown at ./src/routes/blog/getting-started.md
. Try duplicating one of the existing markdown files and renaming it. You'll see that the homepage will change next time you build or reload the server../src/routes/hooks/route.js
file you'll see we're importing the hookInterface and then building a page for each hook using the all
and permalink
functions. Next open up the ./src/routes/hooks/route.js
and the ./src/routes/hooks/Hooks.svelte
to see how data is passed from request --> data --> Svelte.dynamic
- This is an example of how to use Elder.js in SSR mode to create dynamic experiences.Now that you've got Elder.js up and running let's talk about some customization options.
Getting started with Elder.js and want to connect with other users? Join us over at the Elder.js channel within the official Svelte discord.
As you play with this template you'll notice that there is some SEO auditing going on.
Under the hood Elder.js uses @elderjs/plugin-seo-check
to check each page generated for more than 50 common search engine optimization (SEO) issues.
If for some reason these warnings are to verbose you can adjust the level by editing your ./elder.config.js
to be:
'@elderjs/plugin-seo-check': {
display: ['errors'], // If the errors are too verbose remove 'warnings'
},
This will silence some of the more opinionated rules.
Currently this template is running two plugins:
@elderjs/plugin-markdown
to help us parse markdown files, generate pages, and make them available within Elder.js.@elderjs/plugin-browser-reload
to reload the browser when in dev server mode.If you are looking for other plugins check out these:
ref
and referenceList
shortcodes.If you want to share an idea for a plugin or want to help develop an Elder.js plugin, check out Plugin Ideas discussion on the Elder.js repo.
Once you've explored the templates above, it is worth looking a bit at how the hooks work.
Open up the ./src/hooks.js
file and look at the hooks this project uses.
You'll see there are a few hooks in there.
If you uncomment the hook with the name of compressHtml
and reload this page, you'll see that the html is now compressed... but the code blocks are broken. (they always say don't compress html with regex!).
In plain english, this hook takes the htmlString
, modifies it (compresses it), and returns it.
Now that you see the power of hooks, let's have you add your first hook which illustrates how you'd add analytics code to every page of your site.
Copy and paste the hook below into your hooks.js
file.
{
hook: 'stacks',
name: 'addAnalyticstoFooter',
description: 'Add analytics to Footer.',
priority: 1, // we want it to be last
run: async ({ footerStack }) => {
footerStack.push({
source: 'hooks',
string: `<!-- your analytics code here -->`,
priority: 1,
});
return { footerStack }
},
},
If you reload your html, you should see the html comment from the hook.
In this hook we are manipulating a "stack."
Under the hood, Elder.js uses stacks to predictably manage in what order strings are rendered.
In this hook we're just adding our analytics code at a priority of 1 (last).
If stacks seem foreign, just remember they are a list of strings with some meta data.
Elder.js runs it's hooks system based on it's 'hookInterface'. This interface defines which hooks can do what and what properties they have.
In building Elder.js we found that if anything can be mutated at anytime, a system quickly gets hard to reason about.
The 'hookInterface' is designed to solve that problem. While you can explore all of the hooks on the homepage, before you go try adding a malicious hook that is designed to corrupt important data during page load.
Add the hook below to your hooks.js
file and reload this page:
{
hook: 'data',
name: 'maliciousHook',
description: 'Can we break anything?',
priority: 1, // this will be called last
run: async ({ helpers, data, settings, request, query }) => {
settings = null;
request = null;
helpers = null;
query = null;
return { settings, request, query, helpers }
},
},
On reload, if you check the console you'll see that this hook wasn't able to mutate any of the props due to the way the hookInterface is configured.
Essentially only properties that are able to be mutated on a hook, will be mutated on the hook. This helps keep plugins and developers honest and makes maintaining the project in the future easier to reason about. :)
If you're interested in exploring hooks more check out the full Elder.js documentation on ElderGuide.
Shortcodes are a great way to customize otherwise static content. They are especially useful when using a CMS or external content store. The most common use cases include:
Here is an example of their power:
This site has 19 pages on it.
If you add another page to this site, you'll see that the number of pages above adjusts accordingly. This dynamic ability is powered via a shortcode which you can see in ./src/shortcodes.js
.
Usually this sort of customization takes a ton of preprocessing, parsing, etc, but Elder.js handles it all for you. Simply define a shortcode and a function that returns what you want it to be replaced with and Elder.js will handle the rest.
Learning Opportunities:
./src/shortcodes.js
)Out of the Box Usecases
ld+json
to your head for a specific page, but don't have it wired into the template. You could use a shortcode to do so.Under the hood Elder.js does quite a bit of magic based on the file structure below but more importantly the rollup.config.js
is setup to match this file structure. Since Rollup handles all of the bundling of our Svelte components, we recommend you follow this structure unless you like tinkering with bundlers.
Project Root
| elder.config.js
| package.json
| rollup.config.js
| ... (other common stuff, .gitignore, svelte.config.js... etc)
| -- src
| -- | -- build.js
| -- | -- server.js
| -- | -- hooks.js
| -- | -- shortcodes.js
| -- helpers
| -- | -- index.js
| -- | -- ...
| -- layouts
| -- | -- Layout.svelte
| -- routes
| -- | -- [route] ('blog' in this example)
| -- | -- | -- Blog.svelte
| -- | -- | -- route.js
| -- plugins
| -- | -- [plugin] ('elderjs-plugin-your-plugin' for example)
| -- | -- | -- index.js
| -- components
| -- | -- [component] ('Contact' in this example)
| -- | -- | -- Contact.svelte
On this Project:
| -- assets
| -- | -- items to be copied to the 'distDir' defined in your 'elder.config.js'. See hooks.js.
If you are looking to deploy your statically generated Elder.js site Cloudflare Pages has a great guide.
For this template any css in the ./src/layouts/Layout.svelte
will be made available on all pages. You can also import CSS like we do with the css file at ./assets/style.css
and that will get added to the CSS file Elder.js generates.
Elder.js started as a static site generator but today it is used in production as an SSR framework as well.
For more information look at the route found in ./src/routes/ssr/
. In short, the req
and next
functions from express
or polka
(used in this template) are made available there. This means you'll have access to sessions
and anything else you'd need to make logged in or otherwise dynamic experiences.
For even more control make sure to checkout the middleware
hook.
Another hook that you'll see is one that copies anything in your ./assets/
to the distDir
defined in your elder.config.js
(which is./public/
folder by default in this project).