Powers the ahurle.dev website and developer blog. Heavily modified fork of Devii.
I wrote a blog post about this project if you want some more context on why it exists.
Feel free to fork this repo for your own website! I know how annoying it is to get everything working nicely if you were to start from scratch instead. All I ask is that you style it a little differently - make it "yours". And remove my blog posts and stuff, of course. It would also be nice if you linked back to me, but it's all MIT licensed so... 🤷♂️
- Modern Next.js, React, TypeScript stack
- Author blog posts and other pages in MDX, export "front matter" as a JS object validated by
zod
- Syntax highlighting for code blocks in your blog posts
- Dark mode support with
theme-ui
- All pages get automatic smoke tests from
next-page-tester
- All pages use static generation and the site functions with client-side JS disabled
- Effortless image optimization with
next/image
- Free analytics from GoatCounter
- Free hosting from Vercel
- Free client-side exception reporting from Sentry
- ESLint, Prettier, Jest, and a CI config for Github Actions - Free!
- Newsletter signup with TinyLetter
- Excerpt, Table of Contents, and Reading Time get extracted from each blog post
- SEO, a11y, RSS, sitemap, page speed are all in pretty good shape
nvm use # see .nvmrc
yarn install
yarn dev
You should now see my site running on http://localhost:3000
M1 Mac Special Instructions
I ran this on node 14.x for a while without problems. At some point it started exploding on yarn install
. I was able to get around it like so:
nvm install v15.11.0
nvm use v15.*
vim package.json # change engines -> node to "15.x"
Note that vercel does not support node 15.x or higher yet. It will probably also work if you use Rosetta for Node 14 rather than trying to compile it natively for arm64.
yarn dev
- Starts the development server. Equivalent tonext dev
.yarn build
- Creates an optimized, production build of your site. Equivalent tonext build
. Useyarn start
to run this build locally.ANALYZE=true yarn build
- Also opens webpack-bundle-analyzer output in your browseryarn export
- Exports your site to static files. Equivalent tonext export
.yarn lint
- Run eslint and prettier checks. Useyarn lint:eslint
oryarn lint:prettier
for specific checksyarn test
- Run tests
There are a few basic things you'll want to change right away to make it "your" site:
The constants in this file are pretty self-explanatory. Change the name to match your name, the domain to match yours, etc.
I got lazy here and duplicated some config from globals.ts
- change the URL to match your prodUrl, and add any exclusions for e.g. unpublished blog posts.
If you want to use GoatCounter for site analytics, sign up for an account and replace goatCounterId
with your own. If you don't want to use it, you can set goatCounterId
to null.
GoatCounterScript
and GoatCounterPixel
contain some hardcoded checks to make sure you don't accidentally dump your data into my account in case you haven't read these instructions yet. Changing/Removing these is left as an exercise for the reader.
By default, analytics are only enabled in the prod environment, but you can test in dev by commenting out the prod checks.
You can use Sentry to catch unhandled exceptions on the client side of your app. Sign up for an account and replace sentryPublicKey
and sentryDsn
with your own. If you don't want to use it, you can set either constant to null.
Like with GoatCounterPixel
, there are some hardcoded checks in SentryLoader
that you might want to remove.
By default, sentry only runs in prod and preview mode, but it can run in dev by commenting out the checks. Try calling window.onerror("hello world")
to make Sentry log an error.
The site contains newsletter signup forms thanks to TinyLetter. Sign up for an account and replace tinyLetterUsername
with your own, or set it to null to disable the forms.
Once you've changed all this stuff, run yarn test
. You'll probably have a bunch of failing snapshots that used to contain my globals. Press u
to update the snapshots to contain your globals. Making sure yarn lint
still passes is also a good idea.
This project contains a CI config that should run whenever you open/update a PR or push to master. It's a good idea to make sure that's passing now. Here's some documentation to get you started.
You may also need to do some separate setup for the specific actions I'm using - especially bundlewatch - but I don't remember the specifics 🤷♂️
The easiest way to deploy this app is through Vercel. Sign up for an account and you can have it deploy your repo with a few clicks. You should be able to visit your site at a *.vercel.app
domain for now, and later you can point a domain at it like ahurle.dev
. Remember to change prodUrl
in globals.ts
if your domain changes.
If you want to use something else then it's probably not very difficult to switch. Note that I depend on some VERCEL_*
environment variables, and next/image
requires a server to transform image URLs.
- me.jpg: Change this to be an image of you, or delete it if you don't want one
- favicon.ico, logo.png, and logo.svg: This is the favicon for your site. You'll want to replace these with images of your own creation.
- The rest of the non-SVG files in /public can probably be deleted
Most of the text on the site lives in /pages. If you aren't familiar with the concept of pages in Next.js, I recommend reading the docs. You will probably also want to change the Footer and Header.
The rest is up to you!
Most code © 2021 Andrew Hurle, MIT License
Based on Devii, © 2020 Colin McDonnell, MIT License
imageSizeLoader.js based on image-size-loader, © 2015 Patrick Collins and Boopathi Rajaa, Apache License 2.0
mdxDefaultLayout.js based on a file from silvenon.com, © 2020 Matija Marohnić matija.marohnic@gmail.com (silvenon.com), MIT License
mdxImageMetadata.js based on a file from kylepfromer.com, © 2019 Kyle Pfromer, MIT License
prismStyle.ts based on the darcula theme from react-syntax-highlighter, © 2019 Conor Hastings, MIT License