12 KiB
As a site and community alike, we have a myriad of ways to contribute to the site and the community at large. Below is the Table of Contents for this CONTRIBUTING.md file, but if you get stuck or want to ask questions, feel free to open an issue on GitHub or reach out to us on our Discord.
Blog Posts
Adding a New Blog Post
To credit you for your new post, we'll start by adding you to the list of authors for the site.
Author Data File
The author data file is located at content/data/unicorns.json 🦄
This section assumes you'd like to contribute directly through GitHub. If you'd rather contribute an article without using Git, reach out to us on our Discord, and we'll work with you to introduce your (attributed) content.
To add yourself as an author in a PR for a new post, you'd add your information as a new JSON object in the array.
This information includes:
-
A username for your profile (used in your profile URL). [IE, our founder's username is
crutchcorn, and their page can be found here] -
Full name
-
A separate field for the first name and last name as well
(this is because SEO meta tags force us to use first names and last names)
-
If you wish to go by an alias, nickname, or any other appropriate identifier, that is absolutely permitted.
-
-
A short description of yourself
- If you need to have a line break, simply add in
\nand the code will handle it for you - We ask that your description is less than 140 characters long
- If you need to have a line break, simply add in
-
Your social media metadata. We currently support the following:
- Twitter
- Please leave your username without a
@preceding it
- Please leave your username without a
- GitHub
- Please leave your username, not the full GitHub profile link
- A personal website
- Do leave the full URI of your website, including
httporhttps
- Do leave the full URI of your website, including
- We have an issue on supporting arbitrary profile links. If you'd like to add other social media options, open an issue or a PR and we'll take a look at it
- You may also leave these fields blank and simply provide an empty object as an alternative. Don't feel forced to leave any social media if you'd rather not
- Twitter
-
Your preferred pronouns
- Please keep our Code of Conduct in mind. We do not accept bigotry of any kind.
- This value must match one of the
idfields of ourpronouns.jsonfile- If your preferred pronouns are not present, simply add a new value inside of said JSON file
-
A profile picture, used on your profile page.
- This profile picture should be a path to a PNG or a JPEG file with the resolution of at least
512x512that's saved inside of./content/data - Don't want to show your real picture on the site? That's alright! We have a myriad of custom unicorn emotes that can be used as profile pictures as well. They're adorable, go check! 🤩
- This profile picture should be a path to a PNG or a JPEG file with the resolution of at least
While this feels like a lot of metadata, keep in mind that all of this is optional or can provide defaults that don't identify you. Please never feel pressured to provide more information than you're comfortable with!
Markdown Post
Now that we have your user attribution data, we can move onto the post data itself. We store all blog posts under a format called "Markdown." This format is a plaintext file with some special syntax for formatting improvements. I recommend using an app like Typora, which allows you to edit markdown files similarly to a Word document. If you're coming from Google Drive, there's an open-source script that may help you convert your documents to Markdown.
Save Location
Once you have your .md file, we'll need a place to put it. We place a subdirectory in our content/blog folder for each of the blog posts on the site. The naming of these subdirectories is integral to keep in mind, as they reflect the URL path of the article once finished. For example, the folder what-is-ssr-and-ssg will turn into the URL for the article:
https://unicorn-utterances.com/posts/what-is-ssr-and-ssg/
Once you've created a subfolder with the URI you'd like your article to have, move the .md file into the folder with the name index.md. If you have linked images or videos, you'll need to save those files in the same folder and change your markdown file to reference them locally:
An example of referencing a video locally is:
<video src="./ios_vs_android.mp4" title="A comparison of how text spacing is applied on iOS and Android"></video>
Where you include the title of the video and the video.
File Naming
We expect images and videos to be fully lowercase with underscores (often called snake_case) for various build reasons. We've often had build issues when files contain uppercase or dashes in the file name.
Static File Linking
There may be instances where you want an image or arbitrary file to be linked within your article. Say you've made a PowerPoint presentation that you'd like to link inside of the article. To do this, create a subfolder with the same name as the URI of the blog post user static/posts. You're then able to reference your files inside of the markdown file:
[styles.xml](./styles.xml)
Frontmatter
Now that we've placed the file in the correct location, we need to add metadata about the blog post itself. We do this inside of the index.md file itself using what's called a "Frontmatter." An example frontmatter looks something like this:
---
{
title: 'Hard grids & baselines: How I achieved 1:1 fidelity on Android',
description: 'Testing the limits of `firstBaselineToTopHeight` and `lastBaselineToBottomHeight` to deliver a perfect result.',
published: '2019-10-07T22:07:09.945Z',
edited: '2020-02-02T22:07:09.945Z',
authors: ['edpratti'],
tags: ['android', 'design'],
attached: [],
license: 'cc-by-nc-nd-4'
}
---
The following data must be present:
-
Title for the article
- We ask that your titles are less than 80 characters.
-
A description of the article
- We ask that your descriptions are less than 190 characters.
-
A published date
- Please follow the format as seen above
-
An array of authors
- This array must have every value match one of the
ids of theunicorns.jsonfile
- This array must have every value match one of the
-
An array of related tags
- Please try to use existing tags if possible. If you don't find any, that's alright
- We ask that you keep it to 4 tags maximum
-
A
licenseto be associated with the post- This must match the
idfield for one of the values in ourlicense.jsonfile - If you're not familiar with what these licenses mean, view the
explainLinkfor each of them in thelicense.jsonfile. It'll help you understand what permissions the public has to the post- For example, can they modify the article and re-release it or not?
- This must match the
Editing a Blog Post
Our blog posts can all be found under /content/blog. Simply find the article based on the URL path and edit the index.md file. We'll have one of our editors review the post changes, and we'll try to reach out to the author for them to review your PR as well.
Translating a Blog Post
If you are adding a translation, make sure to create an Author Data File with the "translator" role so that you are credited for your work on the site!
Finding a Language Code
For any language to be translated, it must have a name and identifier defined in the /content/data/languages.json file. If the language is already defined there, simply use its identifier in the following sections; if not, we will need to add it to the file.
Each language code should consist of two lowercase letters. If it includes a region, append a hyphen followed by two more lowercase letters. For example, the code for French is fr - to specifically refer to the French dialect in Canada, the code would be fr-ca.
Please use
-instead of_in the language region ISO formats. Instead offr_ca, it'd befr-ca.
Refer to Wikipedia: List of ISO 639-1 codes for identifiers to be used in this format.
Creating the Translated Post
Each blog post on the site has a subdirectory inside the content/blog folder. In this folder, the post should have an index.md file with its current contents.
To create a translation file for this post, copy the index.md file and rename it to include the new language identifier as index.(lang).md. For example, a translation for fr would be named index.fr.md. The content inside this file can then be translated into the respective language.
Translating Post Images / Assets
If any images used in the post need to be translated, these should be named in a similar fashion - for example, a translation of dom_tree.svg should be named dom_tree.fr.svg. Any links to these images will need to be updated in the index.fr.md post to point to the translated image.
Code
While we have a lot of code that is not yet this way, we try our best to build our code for the site in such a way that it's generic enough to be useful for others. For example, some of our UI components have led to the creation of our sister NPM library batteries-not-included. We now directly consume said library for our own components. We've also found ourselves requiring a custom markdown processing utility in the form of unist-util-flat-filter.
Keep in mind that we request developers reach out via our Discord or via GitHub issue before extensive development is pursued. If you have a feature you'd like to add to the site, let us know! We'd love to do some brainstorming before coding begins!
We're using a small set of internal forks of deps for the following reasons:
Develop Mode
To start the development server, run npm run develop, it will then start the local instance at http://localhost:8000. You also can check out the GraphiQL tool at http://localhost:8000/___graphql. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the Gatsby tutorial.
Debugging Plugins
We have a few local plugins for Gatsby. However, I've found that while debugging these plugins, Gatsby's cache can often get in the way. If you run npm run debug, it will create a debuggable (using Chrome) instance of the Gatsby develop mode and clear the cache of Gatsby. This script will ensure that your debugger provides proper insight into what's happening in the build process.