How to generate your resume with schema.org vocabulary HTML markup using JSON Resume, allowing your resume to be understood by search engine crawlers and other machines.
tl;dr
Using JSON Resume with the jsonresume-theme-microdata theme will create a resume documented with microdata following the Schema.org vocabulary set.
Prerequisites
- You skimmed How to Boost SEO by Enhancing HTML with Microdata or you know how to add microdata to HTML
- You know what objects and arrays are in programming
- You have a general understanding of JSON Schema
Quick Tech Primer
This was originally one article, but I couldn't easily write about adding structured data to JSON Resume without explaining structured data itself. So...it's now a series and this article is gonna focus on adding microdata to your resume using the open source JSON Resume schema. There's a 3rd one, but I'm still cooking it.
What is structured data, microdata, Schema.org vocabulary?
See How to Boost SEO by Enhancing HTML with Microdata for details. The article includes code examples and schema output.
Cliff notes:
- structured data? web 3-ish: Google explains structured data
- Schema.org? Founded by Google, Microsoft, Yahoo and Yandex: Schema.org
- Schema.org Vocabulary? common content Types and property names: the Person type, the Article type
- microdata? micridata primer, YouTube: Microdata vs JSON-LD: Which Structured Data Format Wins?
- microdata in HTML? see 1st article and the Schema.org microdata usage guide
- microdata validation? Schema.org's validator, Google's Rich Results Test
What is JSON Resume?
To explain adding structured data to HTML, it made sense to use a commonly-known set of data. JSON Resume fits that bill and gave me a great reason to update the HTML of my resume.
If you're unfamiliar with JSON Resume, it's core-premise is creating a standard data structure for a resume's content. The JSON in "JSON Resume" refers to the JSON schema which details the expected data structure of each piece of data.
Basically it's a detailed content-model of commonly-used resume content which has been open-sourced and widely adopted.
- JSON Resume website: jsonresume.org - to dig deeper
- the JSON Resume schema - to see our content model
- JSON Resume themes - 400+ themes available!
- JSON Resume tools/projects - resume editors, LinkedIn resume converters, validators, pdf exports, etc
JSON Resume example
Here is my resume.json file in a GitHub gist which is then combined with a JSON Resume theme and served up via the free and open-source JSON-resume-as-a-service here: registry.jsonresume.org/scottnath?theme=even
![Image has four examples of JSON Resume themes styling Scott Nath's resume][img-themes]
kendall
, mantra
, even
, stackoverflow
What is jsonresume-theme-microdata
?
jsonresume-theme-microdata is a JSON Resume theme. It looks pretty much like the ⬆️ third one in the image above.
It is distributed as an npm package and is a fork of jsonresume-theme-even. The jsonresume-theme-microdata
version has the same styles as jsonresume-theme-even
(for the most part). The main differences is the microdata
fork has some HTML changes and the addition of microdata
throughout the HTML.
Luckily, the even
theme already had good semantic HTML structure, so not tons of HTML changes - mostly converting sections to use description lists. DL's are my jam - a totally underused set of elements.
See this basic example usage in the examples directory in the jsonresume-theme-microdata
github repo
Explainer: adding structured data to a JSON Resume theme
A breakdown of how I adjusted the HTML and microdata.
This is just a subset of the changes - the JSON Resume schema is pretty big.
Step 1: Look at two similar, but different sections
basics
is all the metadata about you, the person, so name, phone, label ("e.g. Web Developer"), image, etc.
work
is your work history
volunteer
is your volunteer history
The similarities between volunteer
and work
are that you spent time at an organization, and that you had a position there. Here is the relevant subset of the data, using the JSON Resume schema structure.
{
"basics": {
"name": "Scott Nath",
},
"work": [
{
"name": "Company ABC",
"description": "...company description...",
"position": "Software developer",
"summary": "...details about position...",
},
{
"name": "Company Meow",
"position": "Sitting",
},
],
"volunteer": [
{
"name": "Company 501c3",
"position": "Software developer for free",
"summary": "...details about position...",
}
]
}
Step 2: Write semantic HTML which matches the resume data hierarchy
Making an article
with h1
cause a resume on a page should be the main document.
<article>
<h1>Scott Nath</h1>
<section>
<h2>Work History</h2>
<article>
<h3>Company ABC</h3>
<p>...company description...</p>
<h4>Software developer</h4>
<p>...details about role...</p>
</article>
<article>
<h3>Company Meow</h3>
<h4>Sitting</h4>
</article>
</section>
<section>
<h2>Volunteer History</h2>
<article>
<h3>Company 501c3</h3>
<h4>Software developer for free</h4>
<p>...details about role...</p>
</article>
</section>
</article>
Step 3: Add microdata, using Schema.org types
A resume describes a person, so the primary itemscope
of your resume will be schema.org/Person. For both volunteer
and work
, the person needs to connect to them in the structured data, so they are an alimni of the orgs: schema.org/alumniOf. alumniOf
is a property of Person
The organization for both types would have itemscope
schema.org/Organization, but Organization
has a lot of specific Types available on top of it - Airline
, LocalBusiness
, NGO
, EducationalOrganization
- but since that specificity is hard to automate, for now the microdata
theme labels all these an Organization
Type.
The position is something that happened inside the organization. Here the semantic HTML aligns great with the schema.org Types! (yes, a section
was added...but...still semantic!) To connect the position is itemprop employee
. Then, to describe the employee, we're using a more specific Type of Person, EmployeeRole
.
<article itemscope itemtype="https://schema.org/Person">
<h1 itemprop="name">Scott Nath</h1>
<section>
<h2>Work History</h2>
<article itemprop="alumniOf" itemscope itemtype="https://schema.org/Organization">
<h3 itemprop="name">Company ABC</h3>
<p itemprop="description">...company description...</p>
<section itemprop="employee" itemscope itemtype="https://schema.org/EmployeeRole">
<h4 itemprop="roleName">Software developer</h4>
<p itemprop="description">...details about role...</p>
</section>
</article>
<article itemprop="alumniOf" itemscope itemtype="https://schema.org/Organization">
<h3 itemprop="name">Company Meow</h3>
<section itemprop="employee" itemscope itemtype="https://schema.org/EmployeeRole">
<h4 itemprop="roleName">Sitting</h4>
</section>
</article>
</section>
<section>
<h2>Volunteer History</h2>
<article itemprop="alumniOf" itemscope itemtype="https://schema.org/Organization">
<h3 itemprop="name">Company 501c3</h3>
<section itemprop="employee" itemscope itemtype="https://schema.org/EmployeeRole">
<h4 itemprop="roleName">Software developer for free</h4>
<p itemprop="description">...details about role...</p>
</article>
</section>
</article>
Step 4: Validate your microdata to output the data
Using validator.schema.org, we can copypasta the HTML above and below is the validator output.
Person @type Person name Scott Nath alumniOf @type Organization name Company ABC description ...company description... employee @type EmployeeRole roleName Software developer description ...details about role... alumniOf @type Organization name Company Meow employee @type EmployeeRole roleName Sitting alumniOf @type Organization name Company 501c3 employee @type EmployeeRole roleName Software developer for free description ...details about role...
Other fun data structues that were added
Here's a few of the other data types that came out as interesting ways to connect to Person
basics.profiles is all your social network profiles
These I chose ContactPoint as the Type, making HTML like:
<dl>
<div itemprop="ContactPoint" itemscope="" itemtype="https://schema.org/ContactPoint">
<dt itemprop="contactType">Mastodon</dt>
<dd data-network="Mastodon">
<a href="https://mastodon.social/@scottnath" itemprop="url">
<span itemprop="identifier">scottnath@mastodon.social</span>
</a>
</dd>
</div>
<div itemprop="ContactPoint" itemscope="" itemtype="https://schema.org/ContactPoint">
<dt itemprop="contactType">DEV</dt>
<dd data-network="DEV"><a href="https://dev.to/scottnath" itemprop="url"><span itemprop="identifier">scottnath</span></a></dd>
</div>
</dl>
which ends up with this structure:
Person @type Person name Scott Nath contactPoint @type ContactPoint contactType Mastodon url https://mastodon.social/@scottnath identifier scottnath@mastodon.social contactPoint @type ContactPoint contactType DEV url https://dev.to/scottnath identifier scottnath
I added specificity with skills
to allow itemtype
Here's a couple skills
from my resume.json:
"skills": [
{
"level": "Senior",
"name": "Languages",
"itemtype": "ComputerLanguage",
"keywords": [
"Javascript",
"Typescript",
"CSS",
"HTML",
"Bash/Shell",
"Gherkin",
"Python",
"PHP"
]
},
{
"level": "Senior",
"name": "UI Components",
"itemtype": "SoftwareSourceCode",
"keywords": [
"Web Components",
"VueJS",
"Lit",
"Sass",
"HandlebarsJS",
"ReactJS",
"AngularJS"
]
},
]
which came out as very interesting structured data in that it's nice to have information about me labeled like this in the wild:
Person @type Person name Scott Nath knowsAbout @type ComputerLanguage description Languages name Javascript name Typescript name CSS name HTML name Bash/Shell name Gherkin name Python name PHP knowsAbout @type SoftwareSourceCode description UI Components name Web Components name VueJS name Lit name Sass name HandlebarsJS name ReactJS name AngularJS
kewl!!
This is long, let's stop
Thanks for reading. If you'd like to see the full data model extracted from my resume here is the Google Rich Results Test which shows all the data extracted from my resume using the jsonresume-theme-microdata
theme.
Cheers!
Top comments (1)
This is awesome, I love the link to the actual google parsing at the end.