Configuring Gatsby as a simple blog site.
2019-02-02GatsbySemantic UINetlifyPrism.js
This website uses the Gatsby static site generator with Semantic UI React components, markdown for blog entries, and hosting on Netlify.
The process is actually fairly straightforward and there are excellent tutorials for most of it, however there are a few areas that took a little research. For future reference, here are the relevant links and fixes:
The Gatsby.js Tutorial is absolutely excellent. Following it through fully sets up the markdown to blog conversion. While each stage tends to start by asking you to create a new page from scratch, this often isn’t necessary. The sections on styling are also not required if you intend to use a self-contained UI like Semantic.
Once you’re finished with the tutorial, you can remove any styling you added, and copy the relevant parts of this Gatsby Semantic UI starter. There’s actually not much needed here, so just merge in the webpack config from gatsby-node.js
and add any packages from package.json
you are missing (less + gatsby plugin, semantic-ui-less and semantic-ui-react). You can now just import and use Semantic components in pages.
Replace the layout provided by the tutorial with one using Semantic - I started from the homepage layout example which shows the use of a Menu
, Container
etc. to give a fixed top bar. This was tweaked substantially to give the current header.js used on this site.
The semantic theme can be overriden in src/semantic/site
. For example fonts and colors are defined in in site.variables
. We can add new colors:
@themeDarkGrey : #2E3947;
@themeGrey : #37474F;
@themeLightGrey : #4F5A5A;
@themeBrightYellow : #FFECB2;
@themeRed : #EC6B6B;
@themeCyan : #16E6E6;
@themeBrightCyan : #8DF7F7;
@themeYellow : #FFC400;
@themePurple : #AD82F9;
@themeBrightPurple : #C3A0FF;
These will be available in other less
files. site.overrides
can be used for styling custom classes etc.
To find other variables to customise, have a look in node_modules/semantic-ui-less/themes/default
- you can copy and paste to the corresponding location in your site’s theme, then modify. You only need to copy the variables you want to modify, other values will be inherited from the default theme.
Fonts are also configured in src/semantic/site/site.variables
. The default theme only uses one, Lato. We can add more variables to define a font for code examples:
@codeFontName : 'Fira Mono';
@codeGoogleFontName : 'Fira+Mono';
@codeGoogleFontSizes : '400';
@codeFont : @codeFontName, Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
We then need to modify the font request to get both the existing page font and our new code font:
@googleFontRequest : '@{googleFontName}:@{googleFontSizes}|@{codeGoogleFontName}:@{codeGoogleFontSizes}&subset=@{googleSubset}';
We can then use the @codeFont
variable for the font-family
of code samples - see later section on configuring prism.js
.
Using a plain image file (or an SVG as used for the logo on this site) was not covered by the Gatsby tutorial - however there is a good doc page on adding images, fonts and files - essentially just import the file as if it were a JS file, and this will give you a path you can use in an img
’s src
attribute.
The next step was to make the navbar/header for the site responsive. Initially I tried using the Responsive
component from Semantic. This works well in gatsby develop
, but using gatsby build
and then gatsby serve
produced odd errors. When viewed at desktop window sizes, the styling of some elements of the navbar was incorrect (this is intermittent, but can be reproduced consistently by running a lightouse audit - the page is incorrect after the audit completes). The root cause of this is SSR, server-side rendering. Because this is done on the server, it doesn’t (easily) know what resolution the browser window will display when the server-rendered React components are “hydrated” on the client. In fact it renders at a window width of 0, and so selects the smallest display size. If this isn’t what the client displays on its first render then React can’t match up the server rendered data to the actual components. There are several solutions to this discussed in Semantic and React issues and docs, for example attempting to estimate the client size from its requests, or using state in components to trigger a re-render on the client. However these each have issues. As a simpler solution, the header just renders both the mobile and desktop components (they are both fixed to the top of the window so overlap), and uses plain CSS media queries to set the one we don’t need to display: none
. While this is a little less efficient (there is an extra set of invisible components at all times) it does work fine with SSR.
Here’s the mobile version of the header:
// Mobile header
<Menu
className='mobile-header'
fixed='top'
inverted
size='huge'
style={{ background: '#464444' }}>
<Container>
<Link to='/' key='rebeam'>
<LogoMobile />
</Link>
<Dropdown item text='rebeam' floating pointing>
<Dropdown.Menu >
{links.map(({name, color, to}) => (
<LinkedDropdownItem color={color} to={to} key={name}>
{name}
</LinkedDropdownItem>
))}
</Dropdown.Menu>
</Dropdown>
<Menu.Menu position='right'>
<Menu.Item as='a' href='https://github.com/trepidacious' title='Github' target="_blank" rel="noreferrer">
<Icon name="github" link inverted size='large' fitted></Icon>
</Menu.Item>
</Menu.Menu>
</Container>
</Menu>
Finally, the image.js
page shows a very simple example of the use of the gatsby-image
plugin/component to display the site logo. This uses a source image at 512x512 resolution, displaying at 256x256. If you check the page you can see that this produces a picture
tag with multiple sources for 1x, 1.5x and 2x screens (i.e. normal and “hidpi” or “retina” displays). In addition, the image has a preloaded thumbnail that is then “blurred up” to the real image when it loads. This does show a possible issue with the plugin - each time the page displays (e.g. using forward/back in browser) the low-resolution thumbnail image is displayed behind the real one and then faded out. This is only visible because the image is non-rectangular with an alpha channel - should probably file an issue on this!
There’s an excellent tutorial for the gatsby-remark-prism plugin. There’s a lot of detail here, covering displaying line numbers, line highlighting etc., and since we have semantic-ui set up we can use less for our code styling. Feel free to read the whole tutorial, but the required parts are:
gatsby-config.js
. You might want to set noInlineHighlight: true
.src/semantic/site/site.overrides
, where we have translated the tomorrow
theme into less, allowing the colors to be chosen with variables. This allows us to reuse our theme colors from site.variables
, and use the @codeFont
font family we defined in “Semantic fonts” earlier. We’ve also tweaked the formatting a little to give us rounded borders, to align the text to our columns, and to add some responsive variations. Finally we’ve adjusted the inline-code styles since we are not using prism.js for these, so we can remove the required "language-"
class and use a light grey background with dark text - using the dark background here is a little jarring.If you want nice “fancy quotes”, correct apostrophe’s (I think that’s a totally grammatical apostrophe in the right place…), small - and large — dashes then add gatsby-remark-smartypants.
2020-04-19
2020-04-18
2019-04-21
2019-03-24
2019-02-26
2019-02-20
2019-02-16
2019-02-15
2019-02-02