Lachlan's avatar@lachlanjc/notebook

Making a hackathon website with Next.js, MDX, & Theme UI

Recently, I kickstarted the website for AngelHacks. Soon afterward, someone in the Hack Club Slack needed to build a site for their hackathon, & was wondering how to do it. I’m publishing this so anyone else can take advantage, too!

Hackathon sites I’ve designed (you’ll notice some patterns!):

They’re all open source on GitHub if you want to peruse the source code. The last 3 use Gatsby + Hack Club Design System, which is not an easy stack to get started with, & honestly not one I’d recommend to anyone else. The MDX stack, however, is absolutely incredible to work with. I’ve made a few sites like this.

Before we continue, hats off to @jxnblk & friends. His design & code & philosophy are a massive inspiration to my work every day. He wrote many of the libraries & directly inspired much of this.

Note: I also published this section identically as a separate post.

Tech stack lowdown

  1. We’re using the Next.js framework. React is just a library you can run on a webpage—Next makes it easy to build a full, multi-page site (either with dynamic server components or a static site, like these are), handling asset bundling, routing, etc.
    • Next is wildly easy to get started with, & once you’ve got a site, you can add a new page just by making a file at pages/about.mdx with some text in it, & you now have a high-performance static page at /about on your site. This is magical.
  2. We’re using MDX to write content. It’s Markdown with superpowers: all the normal Markdown stuff works, but then you can also embed React components inside your text (great for styling, adding forms, etc!), or include other MDX files as React components in other MDX files. It makes authoring pages super easy, because suddenly you only have to write code if you want custom styling on your page, not just to get text on the screen.
  3. Theme UI handles styling, with Emotion underneath & Rebass on top. Breaking this down: Emotion handles dynamically generating the actual CSS based on which components are on each page. Theme UI is the library that lets you use themes (e.g. dark & light modes) & provides a really nice API for styling React/MDX components. Rebass is a library on top with pre-made Theme UI components, for using CSS Flexbox, or adding buttons or form elements with basic styling applied.

The site is then hosted on Netlify, because it’s free, easy to set up, automatically deploys whenever you push to GitHub, & just works (most of the time).

Update 2020-01-07: I recommend switching Rebass to @theme-ui/components, the newer version. You’ll need to update some dependencies if you’re following this now. Also, I recommend ZEIT Now over Netlify for deployment of Next.js sites.

Spelunking the codebase

This is the AngelHacks codebase, open source & under MIT License (meaning you’re welcome to reuse the code any way you like, with credit), after I made the site:

The two important folders are pages & components—that’s where you’ll spend the vast majority of your time editing the site. Pages are written in MDX (or JSX), components in JSX (React components).


How styling works is a bit complex, but once you wrap your head around the system, it’s incredibly fast to work with.

It starts with a theme. The theme keeps all the primary “components” of your design—all the colors & fonts, but also the amounts of spacing (margin/padding in CSS), the font sizes used, the box-shadows used, etc, all in one place. By not having colors & font sizes & friends all spread out through your codebase, you can super easily modify the look of your whole site just by changing the theme, & you’ll also have fantastic consistency in your design, because you won’t have a random colors used in just one place or the like.

  • Themes also open up having a light mode & a dark mode—or even more craziness, but that’s probably not a good use of your time here :) The default colors set is the light mode, then when the dark mode is in use, the colors dynamically change to what you’ve defined in the theme.
  • You should almost never find yourself manually setting a font size or color on pages/components of the site—keep everything in your theme. Keep reading to see how to use values defined in your theme…

You won’t be writing direct CSS anywhere on the site. You’ll instead see sx={{ on the components & on the pages. A quick guide to what goes inside the sx prop:

  • When you write fontSize: 3 inside sx={{ … }}, you won’t get the CSS font-size: 3px;. Instead, Theme UI will look up the third font size value in your theme.
  • When you pass an array for a property like fontSize, you’re generating CSS Media Queries for responsive styling. fontSize: [3, 4, 5] means that on phones & screens larger than phones, the element will use the theme’s font size #3, then on tablets, theme value #4, then on laptops & larger, theme value #5. As you can see, for very little code, you can make a site that’s optimized for all screen sizes.
  • You might notice weird properties that don’t correspond to standard CSS properties, like my, mr, px, etc. These are for margin & padding, using the theme space scale values like font size. mt means margin-top, mb = margin-bottom, then my is margin on the Y axis, so both top & bottom (full set: my mx my mr mb ml). The same goes for padding, its properties beginning with p (full set: py px pt pr pb pl).
  • bg sets the background-color to one of the colors in your theme. color sets the text color similarly. The superpower here is that if you enable dark mode or another theme, the colors dynamically change to that theme, as defined in your theme file.
  • This is all processed by Theme UI, so check our their website for more details.

I wrote a bit more about how styling is used at a component level over here about the Hack Pennsylvania recap site.

Making your own hackathon site

If I wasn’t in college with way too much to do, I’d open source a template site, but instead, I’ll give instructions on making your own site :)

(Note: I like coding on Glitch because it’s cross-platform including iPads & Chromebooks, you can work with multiple people simultaneously, you can see a live preview as you work, etc. If you prefer your local dev environment, go for it!)

  1. Download the angelhacks/site repo.
  2. Clear everything out of the static folder. Your assets will be entirely unique.
  3. Open components/theme.js & change the colors & fonts. (Loading a webfont? Do that here.)
  4. Rewrite all the copy on all the pages, & update the data (sponsors, team members, social media links in the footer, etc). Your event & your team & your story is unique—tell that story!
  5. Edit components/meta.js with all your event details. This takes forever, but it’ll give you much better placement on Google.
    • You’ll be listed in Google’s events section—with Windy City Hacks, our name & logo & date appeared as the first result on Google for “chicago high school hackathon.” We got a bunch of signups just from that.
    • If you haven’t made a social card, it’s the image that appears when you share a link on Slack/iMessage/Twitter etc. You want it to show your logo and/or people hacking and/or your hackathon name. See the cards I used for my events on my portfolio site.
  6. Update your README file. It’s good form to credit anyone’s work you’re using a chunk of (hi there!).
  7. Publish to GitHub. You’re using dozens & dozens of open source projects to make your site—pay it forward by opening up your code. The next person who comes along will learn from your code, & you’ll have new code in your portfolio as well.
  8. Deploy on Netlify! Sign in with GitHub, then make a new site from Git, pick your repo. The config settings are: npm run build is your build command, out is the resulting folder. Now, whenever you commit & push to GitHub, your site will re-deploy automatically.
  9. DNS time. Head to Netlify’s “domain management” section, add your domain name, then edit your DNS to point to Netlify. This can take a bit to propagate, so don’t worry if it doesn’t work immediately.

That wraps up my hackathon site tutorial. If you have questions, DM me on Slack or email me, & I’ll update this post. & please send me what you make! If you’re looking for design feedback, the #design channel on Hack Club Slack is the best place.