kaito

A modern dark resume theme for Zola that doubles as a personal website landing page, with inner pages for blog and links.

Live demo

Kaito resume homepage with a circular portrait, dark background, and gold section separator

Features

Installation

Requires Zola 0.23.4 or later; this demo is validated with 0.23.4.

From your Zola site's root, add the theme as a Git submodule:

git submodule add https://git.colorized.life/demo.kaitokawasaka.net.git themes/kaito

Alternatively, clone it into the same directory:

git clone https://git.colorized.life/demo.kaitokawasaka.net.git themes/kaito

Set the top-level theme = "kaito" in your site's zola.toml, as shown below.

Minimal configuration

Minimal consumer configuration for your site's zola.toml:

base_url = "https://example.com"
title = "My Site"
theme = "kaito"
compile_sass = true
build_search_index = false

[extra]
site_title = "My Site"
copyright_holder = "Your Name"
footer_links = []

[extra.resume]
name = "Your Name"
nav_links = []

The homepage always renders a profile image. Add your portrait at static/profile.jpg. Create your own content under content/; the demo's content is not installed as your site's content. Empty navigation arrays avoid links to pages you have not created yet. Run zola serve to preview and zola build for production output.

Full options

These are the active theme defaults from theme.toml:

[extra]
site_title = "My Site"
copyright_holder = "Your Name"
footer_links = [{ name = "acknowledgements", path = "/acknowledgements" }]

# Footer links use a simple schema: { name, path }
#   name    — display text
#   path    — local path or absolute URL (e.g. "/about", "https://example.com")

[extra.resume]
name = "First Last"
contact = [
  { text = "email@example.com", url = "mailto:email@example.com" },
  { text = "example.com", url = "https://example.com" },
]
summary = "Two-line professional impact statement goes here."
skills = ["Skill One", "Skill Two", "Skill Three", "Skill Four"]

nav_links = [
  { name = "blog", path = "/blog" },
  { name = "git", url = "https://example.com" },
  { name = "links", path = "/links" },
]

# Nav links use { name, path } for local or { name, url } for external links.
KeyTheme default / fallbackDescription
site_titleMy SiteHomepage heading when resume.name is absent; final template fallback is My Site
copyright_holderYour Name; template fallback config.titleFooter copyright text
copyright_urlUnset; falls back to config.base_urlOptional copyright destination
footer_linksAcknowledgements link aboveEntries use name and path; path accepts local paths and absolute URLs
feed_pathUnset; no feed buttonSection path without a trailing slash; the footer appends /atom.xml

Consumer customization example (merge into your existing configuration):

feed_filenames = ["atom.xml"]

[extra]
copyright_url = "https://example.com"
feed_path = "/blog"
footer_links = [
  { name = "acknowledgements", path = "/acknowledgements" },
  { name = "sites", path = "/sites" },
]

Create the linked pages yourself. For the feed, set generate_feeds = true in your blog section's frontmatter; feed_path only displays the link and does not generate a feed.

Branded demo configuration excerpt (the source entry retains its existing footer position):

[extra]
footer_links = [
  { name = "home", path = "/" },
  { name = "source", path = "https://git.colorized.life/demo.kaitokawasaka.net/about/" },
  { name = "palette", path = "/palette" },
  { name = "acknowledgements", path = "/acknowledgements" },
  { name = "sites", path = "/sites" },
]

Footer path accepts an absolute URL, so the source link works without a deployment redirect. Footer entries do not support url.

Pages

RouteTemplateDescription
/index.htmlResume landing page
/blogblog.htmlPaginated blog listing
/blog/*post.htmlIndividual blog post
/linkslinks.htmlExternal links (header nav)
/siteslinks.htmlCross-site family navigation (footer)
/palettepalette.htmlColor palette reference
/acknowledgementspage.htmlFont and tool credits

Resume data

All resume content is driven from [extra.resume] in your zola.toml. Sections are optional; omit a section to skip it. Installed theme defaults may supply values: override arrays with [] to clear them. If name is absent, the homepage uses site_title.

Consumer customization example:

[extra.resume]
name = "First Last"
contact = [
  { text = "email@example.com", url = "mailto:email@example.com" },
  { text = "example.com", url = "https://example.com" },
]
summary = "Two-line professional impact statement goes here."
skills = ["Skill One", "Skill Two", "Skill Three", "Skill Four"]
KeyDescription
nameDisplay name, rendered as an <h1> at 700 weight; overrides site_title
contactArray of { text, url } entries, separated by middots
summaryShort impact statement (two lines max, content guideline)
skillsArray of strings, separated by middots

Contact items without a url render as plain text. Items with a url render as links.

Theme-default navigation excerpt:

[extra.resume]
nav_links = [
  { name = "blog", path = "/blog" },
  { name = "git", url = "https://example.com" },
  { name = "links", path = "/links" },
]

Resume navigation supports path (local or absolute) and url (external); url takes precedence when present. Rendered as a horizontal row with the vertical separator starting at this line.

Experience

Consumer customization example:

[[extra.resume.experience]]
company = "Company Name"
positions = [
  { title = "Senior Engineer", start = "2022", end = "Present", items = [
    "Accomplishment one",
    "Accomplishment two",
  ] },
]

Each [[extra.resume.experience]] entry represents a company. Multiple positions within the same company are listed under positions.

KeyDescription
companyCompany name (Martian Mono, muted color)
positionsArray of position objects
titlePosition title (Space Grotesk)
startStart date
endEnd date
itemsArray of bullet point strings (optional)

Education

Consumer customization example:

[[extra.resume.education]]
school = "State University"
date = "2016"
degree = "B.S. Computer Science"
KeyDescription
schoolSchool name (Martian Mono, muted)
dateYear or date range (Martian Mono, muted)
degreeDegree name (Space Grotesk)

Consumer page-frontmatter example; links pages use [[extra.links]] with name, url, and description:

[[extra.links]]
name = "example.com"
url = "https://example.com"
description = "Description text"

Customization

CSS tuning knobs

The resume stylesheet (sass/_resume.scss) exposes tunable values marked with // knob: comments. All values can be adjusted directly in the file.

Desktop

SelectorPropertyDefaultDescription
.resume-headergap2.5remSpace between photo and text stack
.resume-photowidth / height200pxProfile picture size (keep square)
.resume-namefont-size3remName size (largest text on page)
.resume-contactgap0.4remMiddot spacing (contact line)
.resume-skillsgap0.4remMiddot spacing (skills line)
.resume-navgap2remSpace between nav links
.resume-navtop1remHow far nav floats into separator bridge
.resume-section-titlefont-size2.5remSection header size
.resume-entrymargin-bottom1.5remSpace between companies

Mobile (max-width: 600px)

SelectorPropertyDefaultDescription
.resume-photowidth / height140pxMobile photo size
.resume-namefont-size2.25remMobile name size (75% of desktop)
.resume-section-titlefont-size1.875remMobile section header (75% of desktop)

Colors

Add [extra.colors] to your zola.toml to override any color. Only the keys you specify change. Consumer customization example:

[extra.colors]
bg = "#1e1e1e"
accent = "#025fa1"
KeyDefaultRole
bg#1e1e1ePage background
text#f6f4f1Primary text
muted#999999Metadata text, nav links
accent#025fa1Link hover color
glow#d4a824Vertical separator color

Palette labels

The palette page displays five fixed swatches. Names and roles can be overridden with extra.palette_names and extra.palette_roles; both accept the five color keys. Consumer customization example:

[extra.palette_names]
bg = "Blackout"
text = "Bone White"
muted = "Super Grey"
accent = "Brigadier Blue"
glow = "Burnt Gold"

Sass variables (sass/_variables.scss)

Theme stylesheet defaults:

$font-body: "Space Grotesk", sans-serif !default;
$font-mono: "Martian Mono", monospace !default;
$container-max: 860px !default;

License

MIT; see LICENSE.