Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate from Gatsby.js to Eleventy #103

Closed
26 tasks done
simpixelated opened this issue Dec 22, 2022 · 16 comments
Closed
26 tasks done

migrate from Gatsby.js to Eleventy #103

simpixelated opened this issue Dec 22, 2022 · 16 comments

Comments

@simpixelated
Copy link
Owner

simpixelated commented Dec 22, 2022

I've been using Gatsby.js for over 2 years now and while it is a pleasant publishing experience (mostly), it has been an extremely frustrating development experience. The problem isn't Gatsby itself, but the ecosystem, which includes the worst aspects of the entire JavaScript ecosystem: plugins for everything; unmaintained libraries, broken peer dependencies, etc. It feels like I spend more time fixing dependency errors than I do writing and publishing.

Screenshot 2022-12-22 at 11 18 48 AM

It seems I'm not the only one with these issues:

So I'm looking into alternatives. Here's my list of needs/wants:

  • has to be simpler to maintain than current setup (Gatsby.js + LekoArts theme + Netlify)
  • able to publish to Netlify (this is probably the one part of my setup that I still ❤️)
  • can write in Markdown with minimal work to convert to HTML/CSS (this works OK in current setup, but the mix of JSX + Markdown has so many complications)
  • build time is minimal (Gatsby is way too slow)
  • no fucking Webpack
  • no React (it's not needed; Markdown makes this complicated enough without adding JSX)
  • static site generation (site should be 99% the same without JavaScript enabled)
  • maintain existing functionality: dynamic blog post list, categories, read time, social share card, og tags, canonical urls, lighthouse scores, etc.

Currently looking hard at Eleventy, but I'm open to alternatives.


The Process

  1. pick new framework (e.g. Eleventy)
  2. create proof of concept
  3. recreate existing features
  4. migrate content
  5. merge to stable

TODO:

  • create proof of concept with Eleventy
  • dynamic blog list
  • dynamic tagging
  • tag list with links that works on blog index and single blog post
  • top level navigation
  • projects list
  • Markdown to HTML conversion
  • static site generation (everything works without JS)
  • homepage link
  • blog list by tag
  • tag list page
  • homepage social media icons
  • resume
  • auto read time display
  • OG meta tags
  • canonical URLs
  • dark mode toggle
    • style toggle (sun/moon)
    • animate transition
    • hide checkbox/button
    • save to local storage
  • styles
  • pop up avatar in header
  • existing social share cards
  • dynamic social share card
  • 404 page
@simpixelated
Copy link
Owner Author

This will likely be a separate process, but it would be cool to also update how I get content into the blog. Currently I'm writing in Bear/Notion/Trello, copying and pasting into VS Code, and committing via Git. It would be really cool to automate this so that content could go directly from my editor to the website. It's certainly possible with Notion (#98).

@simpixelated
Copy link
Owner Author

Current Lighthouse scores:
Screenshot 2022-12-22 at 11 28 15 AM

@simpixelated simpixelated changed the title migrate from Gatsby.js migrate from Gatsby.js to Eleventy Dec 22, 2022
@simpixelated
Copy link
Owner Author

Currently following this tutorial and enjoying the magical feeling it creates.

@simpixelated
Copy link
Owner Author

Adding Time To Read to Eleventy

  1. Looked at https://www.aleksandrhovhannisyan.com/blog/eleventy-the-good-the-bad-and-the-possum/#filter-all-the-things for example filters
  2. took example JS function to calculate time in minutes per https://dev.to/michaelburrows/calculate-the-estimated-reading-time-of-an-article-using-javascript-2k9l
  3. used Medium's average WPM for read time https://help.medium.com/hc/en-us/articles/214991667-Read-time
  4. copied the HTML stripping function from https://github.com/JKC-Codes/eleventy-plugin-time-to-read

@simpixelated
Copy link
Owner Author

simpixelated commented Jan 1, 2023

Adding Blog Posts By Tag List Page

  1. https://www.11ty.dev/docs/quicktips/tag-pages/
  2. had to fix duplicate tag issue with case insensitive tag being converted to slugs (JavaScript vs javascript) Case sensitivity of individual tags entries 11ty/eleventy#2462

@simpixelated
Copy link
Owner Author

Adding Tag List Page (with post counts)

  1. used example code here to get a list of all tags Collection of Tags 11ty/eleventy#927 (comment)
  2. used official API method to get post count: https://www.11ty.dev/docs/collections/#getfilteredbytag(-tagname-) (this could also be done in the reduce, but I didn't want to think about handling array of tags (may come back to this later)
  3. example code:
    const getAllTags = collections => {

@simpixelated
Copy link
Owner Author

Formatting post dates

  1. https://11ty.rocks/eleventyjs/dates/ - had to switch to fromISO for this to work
  2. https://moment.github.io/luxon/index.html#/tour?id=formatting-your-datetime
const { DateTime } = require("luxon")
 eleventyConfig.addFilter("postDate", (dateString) => DateTime.fromISO(dateString).toLocaleString(DateTime.DATE_MED))

@simpixelated
Copy link
Owner Author

simpixelated commented Jan 8, 2023

Other random tweaks:

@simpixelated
Copy link
Owner Author

Filtering Specific Tag from list

filter:

eleventyConfig.addFilter("exclude", (collection, stringToFilter) => {

usage:

{% set tags = post.data.tags | exclude('posts') %}

@simpixelated
Copy link
Owner Author

simpixelated commented Jan 14, 2023

Group posts by year

While I wanted to accomplish this with just Nunjucks filters, I couldn't figure out how to sort the years correctly. No matter what I did it wanted to go in descending order. First I added a custom attribute (computed data) to my posts like:

module.exports = {
  eleventyComputed: {
    year: data => new Date(data.date).getFullYear()
  }
};

and then I used it in the templates like so:

{% for year, posts in collections.posts | groupby("data.year") %}
<h4>{{ year }}</h4>
<ul>
  {% for post in posts | reverse %}
  {% set tags = post.data.tags | exclude('posts') %}
  <li>
    <a href="{{ post.url }}">{{ post.data.title }} {{ post.data.year }}</a><br />
    <small class="post-meta"><time>{{ post.data.date | postDate }}</time>{% if tags | length %} - {% include "tag-list.html" %}{% endif %}</small>
  </li>
  {% endfor %}
</ul>
{% endfor %}

Like I said, this didn't work, so I eventually gave up and just used a custom collection:

eleventyConfig.addCollection("postsByYear", collection => {
const posts = collection.getFilteredByTag("posts").reverse()
const years = posts.map(post => post.date.getFullYear())
const uniqueYears = [...new Set(years)]
const postsByYear = uniqueYears.reduce((prev, year) => {
const filteredPosts = posts.filter(
post => post.date.getFullYear() === year
)
return [...prev, [year, filteredPosts]]
}, [])
return postsByYear
})

@simpixelated
Copy link
Owner Author

simpixelated commented Jan 15, 2023

Social Share Cards

I already have social share cards generated from https://github.com/emgoto/gatsby-plugin-react-social-cards so I want to use those. I accomplished that by adding a JavaScript data file in my posts directory with computed data:

module.exports = {
eleventyComputed: {
socialImage: data => {
return `${data.site.url}/static/banners/${data.title
.replaceAll(" ", "-")
.toLowerCase()}-social-card.png`
},
},
}

However, the beauty of that plugin is that it dynamically generated new social share cards for every post AND it updated existing posts if the data changed, all based on my own React component for styling. I would need to do something similar for Eleventy.

Dynamic Generation

Most existing plugins and tutorials used Cloudinary, but I wanted something similar to my existing setup which would allow full control of the image by taking a screenshot of a page I designed.

The ☝️ 11ty tutorial above strangely uses Eleventy to create a .json script and populates a template with client-side JavaScript, instead of just having Eleventy generate the pages themselves with templates. It's a good base but needs to be modified to make it work the way I prefer.


Found: 11ty/eleventy#712 (comment)
So this would mean running a local build first to generate the layout, take the screenshot, and add it to the static folder. That would mean a two-step process for building and publishing; it wouldn't just happen automatically on Netlify; but that's the way it currently works with Gatsby so it's no different that way. It would be cool if this was automated, but I'm not sure how to do that without also publishing the social-card as a public URL 🤔


Added a new layout that is used when a different build mode is run. Then I created a puppeteer script which takes a screenshot. I manually move that into the static folder and viola! 🤌💋
https://github.com/simpixelated/simpixelated.com/blob/04f55fb9816d3f15bfe20f4046fa4a825cf3aac9/scripts/generate-social-cards.js

@simpixelated
Copy link
Owner Author

Deploy speed on Netlify went from 1-2 min to ~40 sec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant