THIS one click and you'll have a website
This is great code to copy if you want a full-fledged site completely free out of the box on day one, that you can customize and extend to suit your needs.
All the repetitive stuff for content, performance, SEO, accessibility, testing, etc. is done, so you can focus on what makes your site special.
Some of the wheels you won't have to reinvent:
Let's say you want to embed a tweet on a page. On any site you can paste the embed code:
<blockquote class="twitter-tweet">
<p lang="en" dir="ltr">
Do you have feedback on how to make the finished-starter github page more appealing?
</p>
— Brad Czerniak solves it once! (@ao5357)
<a href="https://twitter.com/ao5357/status/1336690590893953029?ref_src=twsrc%5Etfw">December 9, 2020</a>
</blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
As far as embed codes go, Twitter's isn't bad. But on a finished-starter site if you use the liquid component built into the system (and pass it some props):
{% include molecules/tweet.html
classes=""
children="Do you have feedback on how to make the finished-starter github page more appealing? "
date="December 9, 2020"
url="https://twitter.com/ao5357/status/1336690590893953029"
%}
...you can manage from the all-in-one component definition things like the "Do not track" attribute and color theme site-wide for consistency and to protect your users.
The site's component script will only load the twitter third-party JavaScript if there's tweets on the page (which is important for privacy and performance), and will automatically load embeds if new ones are added to an already-loaded page.
If you ever need to look up how to embed a tweet, your own site's documentation has a whole section about it. And that's far from the only documentation you get on day one!
user/organization-name
.github.io
* It can also be any name, typically using the gh-pages
branchPresently Cloudflare Pages doesn't have a one-click deploy button (to our knowledge), but the Cloudflare Pages demo here demonstrates that it's quite possible to do:
gh-pages
, "Build command" to jekyll build --config _config.yml,_config.localdev.yml
, and "Build output directory" to _site
cd
into itbundle install
in the root of the project to get the Jekyll standard items (requires
bundler)npm install
in the root of the project for non-required build dependencies (requires node and npm)bundle exec jekyll serve --verbose --config _config.yml,_config.localdev.yml
to build and serve your site to
http://localhost:4000/
Optionally you can look at the comments in the .scripts/
directory for any image (optipng, pngcrush, jpegoptim, webp, avif)
and other dependencies for optimizing assets on the back end. This helps improve front-end performance if you can manage it.
You can run the .scripts/
from the project root, ideally when the server is not running since it will trigger a rebuild.
user@computername $ .scripts/images.sh
and
user@computername $ .scripts/pre-commit.sh
While the service worker cache should increment every time the site builds, often you will have to use the 'Application' tab of the devtools to clear all site storage and caches. Keeping the devtools open also allows you to right-click the refresh button to select "Empty cache and hard reload".
This is a mild inconvenience you learn to live with and admire, and is a reminder that front-end performance and optimization is important.
The original version of this codebase gets four 100s in Lighthouse testing, has valid HTML per the w3 validator, and has zero errors per the WAVE tool. Also the following:
_config.yml
file, for easy start-up (including Google Analytics and social links)prefers-reduced-motion
, and dark mode styles already in place that you'll never need to touch.font-style--italic
, .background-color--main-dark
, and .display--flex
)<meta>
tags of all kinds, for search engine optimization (SEO), social (open graph, twitter, et al), and interoperability.browserslistrc
used for both testing and documentationYou will find a lot of code comments and documentation along the way, but the first four things you should do to customize the base site for your needs:
_config.yml
per the inline instructions to your site's name and informationassets/images/required/
with your logo and defaults (the various sizes are used for
installing to home screens and other purposes)favicon.ico
and apple-touch-icon.png
in the repo root with your logo mark_data/design-tokens/
and update the design tokens in the JSON files to your brand colors and other stylesThe design tokens are broken up into three top-level sections:
The lang folder of the design tokens is for translatable strings mostly. Each JSON file within the directory should be the two-letter language code to which the strings should apply.
Since the content
property of CSS pseudo-elements should be used sparingly and with consideration to accessibility, the
lang folder should be used minimally.
An aside: it is not necessary to use the lang directory for rtl support.
The root folder's contents all get set as CSS custom properties to the :root {}
.
By default, the _data/design-tokens/root/colors.json
file has black, white, three greys, three shades of three brand
colors (main, second, third), and a single shade of an accent color for good measure. For most sites most of the time,
this should be more than enough colors. And assets/css/utility/utility--color.css
provides all those tokens as both
foreground and background color classes to the application front-end.
One color consideration worth over-emphasizing is that the 'main' color should be the most blue-like color if possible. Main is used for links, so using blue helps signify their affordance (along with underlines).
The kit splits the root tokens out by property/namespace, though any file naming strategy you prefer can be used instead. The custom properties are built from the JSON structure rather than the filenames, so renaming any JSON file has no effect.
The _data/design-tokens/scoped/
directory is for styles outside of the :root {}
scope. This could be one-off or non-branded
components, and especially for preventing unintended component pollution.
You can scope to tags and classes, or some combination of those. The filenames of the design tokens within the directory are parsed as the selectory scope:
Double-underscores become spaces, single underscores become periods, with double-underscores evaluated first.
Example: This file:
_data/design-tokens/scoped/div__a_street-sign___font-family--secondary.json
Places all its custom properties in the following scope:div a.street-sign .font-family--secondary {}
Fonts are not design tokens per se like above, but setting a new font includes a trip to the design tokens.
If you'd prefer to switch from the default high-performance Public Sans variable font to a brand font, do the following:
assets/fonts/
in a directory that's the short name of the font, like assets/fonts/lato/lato.woff2
.
The google webfonts helper is great for thisassets/css/font-face.css
with the font name and file locations. Be sure to keep the font-display: swap;
directive
in each declaration for performance_data/design-tokens/root/font-family.json
to reflect the new font namewoff:
section of _config.yml
to prefetch the files and avoid round-trips.scripts/pre-commit.sh
script to update all the CSSassets/fonts/
directoryPlease note for performance and privacy that you should use the above method, rather than making a third-party call to Google Fonts API or similar services.
Almost all the content for the site is within the collections
directory, sub-divided by collection/type. You can update
all the content there to mesh with your site's purpose.
The content included when you install the site is a mix of generic and example content, and the YAML front matter has a
full range of the available modifiers for the collection the content belongs to. Some of it is commented out with a #
;
you can remove the comments to activate some additional matter.
CSS and JavaScript can be edited at assets/css
and assets/js
, respectively. Each of those directories contains a pre-commit-dependency
folder with an optimized file. These files should not be edited by humans, but are rather generated via .scripts/pre-commit.sh
and controlled by the no_pre_commit_dependencies:
directive in _config.yml
.
The pre-commit script runs purgeCSS on the styles to include only CSS in use on the site, and the JavaScript gets minimized using the terser library.
The CSS is broken out into utility files and theme files. Both are appropriate to edit for customization. The distinction
between utility files and theme files is that utility files feel more like they don't need to be edited from project to
project -- they're little classes that do one thing and rely on known :root {}
properties. Theme files more closely match
customizations particular to a site.
When developing, start by getting tag-level styles in assets/css/theme/theme--base.css
as close as possible before adding
or changing class-level styles. This prevents duplication and over-specifying. The documentation pages for style, components,
and mood are great pages to test against for the base styles.
Functionality on the site is broken out into little partials that do one or two things, and are then concatenated and minimized
in the assets/js/behavior.js
file.
Per the JavaScript documentation, the utility--initializer can be used to ensure scripts run dynamically without degrading main-thread performance.
Note that block comments /* Example block comment. */
rather than inline comments // Two slashes
should be used, since
the two-slash inline comments can accidentally comment out subsequent code when the Jekyll-primitive minification is run.
Similarly, all terminating statements should end with semicolons. This is a small price to pay for convenience, and arguably
is the more agreed-upon style for most developers anyway.
The assets/images/
directory contains a 1200x630
sub-folder. You're encouraged to create images at this size for both
social sharing (via <meta>
tags) and on-screen display for cards and similar. This size works well as a responsive middle
ground, and the aspect ratio is pretty standard and attractive. Place all images of the 1200x630 size in that directory.
Graphic designers on your team are best served knowing 1200x630 is the preferred size and aspect ratio for images ahead of time.
See /scripts/images.sh
for instructions and commands to optimize JPEG and PNG files, as well as the script's core purpose
of generating avif/webp versions of image assets. The webp version will be the original filename with '.webp' appended --
and the image component uses this pattern to figure out whether a webp version exists in order to include it.
When including images in content, overwhelmingly prefer the liquid include _includes/atoms/image.html
:
{% include atoms/image.html
alt="A good description of this image"
caption="This prop is optional and renders as a figcaption"
classes=""
src="1200x630/example-image-name.jpg"
%}
over markdown or hard-coded HTML. This ensures the avif/webp images, lazy loading, and <figure>
/<picture>
semantics
work consistently across the site.
Every tool out there -- wordpress, drupal, create-react-app, plain static site generators, even services like Wix and SquareSpace -- come out of the box missing something. For CMSes it's default content and often a bunch of plugins, for frameworks it's everything but the framework, and for services it's flexibility and baked-in accessibility. This codebase is different; it comes with everything you need to have a working, launch-ready site on day one.
And it's free. Free as in beer, speech, dependencies, everything.
The core ideas around which decisions were made for this kit: