Lachlan's avatar@lachlanjc/notebook

Hack Pennsylvania site

Though the event ran last January, Hack Pennsylvania is one of the things I'm most proud of. I wanted there to be a nice recap of the event online, so I made it: hackpenn.com

Behind the scenes

The site is built using Next.js + MDX + Theme UI, with Rebass + Emotion. Breaking it down:

  • Next.js is the framework that bundles & serves the site. https://nextjs.org/
  • MDX is a technology for Markdown ↔ React. It lets you use React components directly inside Markdown, & vice versa. https://mdxjs.com/
  • Theme UI is a new React library for making themeable React apps. https://theme-ui.com/
  • Rebass is a React component library wrapping Theme UI. It exposes components like <Text /> for styling. https://rebassjs.org/
  • Emotion is the "backend" of rendering the CSS-in-JS from Theme UI/Rebass. https://emotion.sh/
  • The site is deployed on Netlify. Since the site has no dynamic content, it can be statically exported, so Netlify generates a folder of HTML & JS files when I push to GitHub it's then serving via CDN. Next.js automatically detects static vs dynamic pages & builds appropriately.

So all the content of the site is written in standard Markdown, with a sprinkling of React components wrapping parts of the site like the top banner, grid of people, etc with special styling.

Here’s an example of MDX:

<Banner>
# Hack Pennsylvania
Write text here
</Banner>

Then in a JS file, define the component:

const Banner = props => (
<Box
{...props}
sx={{
h1: {
color: 'primary'
},
p: {
fontFamily: 'mono'
}
}}
/>
)

The Box component is coming from Rebass—it's actually just a <div> with Theme UI magic applied. Everything inside the sx prop is running via Theme UI. The {...props} forwards on all the other props passed to Banner—which include the Markdown content, via children.

The primary color & the mono font family are coming from a global theme. You can define multiple color modes, like the dark theme, & use a React Hook on any component to get the current colors based on the color mode or control the current mode. When you use color & bg inside the sx prop, Theme UI automatically applies the correct color for the mode. A basic theme could look like this:

export default {
fonts: {
body: 'system-ui, sans-serif',
mono: 'Menlo, monospace'
},
initialColorMode: 'light',
colors: {
text: '#123',
background: '#fff',
primary: '#f03',
modes: {
dark: {
text: '#fff',
background: '#000',
primary: '#0ef'
}
}
}
}

If you've used Styled System before (also by the brilliant @jxnblk), you're familiar with the idea of themes & scales for whitespace, color, etc. Theme UI takes that to the next level by allowing props you're used to from Styled System (included in the Hack Club Design System) like py & bg right alongside full CSS-in-JS, with full support for psuedoselectors, complex selectors, nesting, & more, via Emotion. I wrote some rambling thoughts on Theme UI & the sx prop yesterday, if you're interested. TLDR, Theme UI is brilliant.

(This isn't a great explanation & there's a lot more to Theme UI than this. If you'd be interested in more writing from me on using Theme UI, let me know!)

The goods are on Glitch

I developed the site 100% on Glitch, without setting it up locally. Big fan. https://glitch.com/~hackpenn

If you want to set up a site with the same basic tech stack, remix my starter project here: https://glitch.com/~next-mdx-rebass-theme-ui

If you want to see all the code for the site in one place, check out this file first, then scroll up through the rest.

If you want to see more projects from Hack Pennsylvania, I've put a few in a Collection on Glitch.


Questions/feedback? Email me: lachlan@hackpenn.com