Reference doc for how hackhpc.github.io is built, how to run it locally, and how to add data (events, partners, resources, etc.) without touching templates.
A static site built with Jekyll and published via GitHub Pages. There's
no build step beyond Jekyll's own — GitHub Pages runs jekyll build automatically on every push
to main. Content pages are plain HTML with Liquid templating; almost everything that changes
regularly (events, partners, resources) lives in _data/*.json / .yml files rather than being
hand-written into pages, so adding an event or partner is a data edit, not a template edit.
gem install jekyll bundler
jekyll serveThen visit http://localhost:4000. Add --livereload to auto-refresh on file changes, or
--incremental for faster rebuilds while iterating. There's no Gemfile checked in, so a plain
gem install jekyll (not bundle exec) is the working path today.
To sanity-check the production build (the one GitHub Pages actually serves):
jekyll buildOutput lands in _site/ (gitignored).
_config.yml site title, URL, github_org_url, and other global Liquid variables
_layouts/
default.html the only layout — head + nav + <main>{{ content }}</main> + footer
_includes/
head.html <head>: meta tags, Open Graph, fonts, Font Awesome, favicon
nav.html top navbar (desktop links + mobile hamburger menu)
footer.html site footer: link columns, social icons, copyright
resource-icon.html renders one resource's icon (Font Awesome brand/solid, or an <img>)
citation-modal.html shared "cite this event" modal used on the Events Archive
assets/
css/main.css the entire design system — one file, no preprocessor
js/main.js mobile nav toggle + every page's search/filter behavior
js/citations.js citation modal logic (APA/IEEE/BibTeX)
img/logos/ HackHPC logo files (mark, wordmark, square, light/dark)
img/partners/ partner org logos (SVG, referenced from partners.json)
img/schools/ school logos (SVG, referenced from schools.json)
img/organizers/ organizer headshots
icons/favicons/ auto-fetched favicon SVGs for external resource links (see §5)
_data/ see §4 — every JSON/YAML file that feeds the site's content
Each top-level content directory is one site section, always index.html (+ occasionally more
pages) with Jekyll front matter (layout: default, title:, description:):
| Directory | Section |
|---|---|
/ (index.html) |
Homepage |
about/ |
About, Organizers, FAQs, Code of Conduct |
events/ |
Events Archive (filterable grid over events.json) |
programs/ |
Programs overview, Participants, Mentors, Faculty |
partners/ |
Schools + partner organizations, by tier |
resources/ |
Brand guide, repos, curricula, data sources, resource library |
research/ |
Publications & media coverage (from research.yml) |
get-involved/ |
Ways to join (participant / mentor / partner / funder) |
Styling conventions (see main.css :root for the full token list): sections alternate
section (white) / section--soft (light gray) backgrounds; .card is the base content-card
class; .events-grid / .grid-3 / .grid-4 are the common grid layouts; long lists on the
Resources page are wrapped in <details class="section-collapse"> so they load collapsed.
Search/filter pages are server-rendered (every item is real HTML, good for SEO/no-JS) and
then progressively enhanced by a matching block in assets/js/main.js — each block finds its
grid by id, reads a data-search="..." attribute off each card, and hides non-matching cards
on input. If you add a new searchable grid, give each card a data-search attribute and add a
matching filter block (copy the "Data sources search" block as a template).
Every file below is an array of objects (JSON) or an equivalent YAML list, looped over directly
in the page templates with {% for x in site.data.<file-without-extension> %}. To add a new
item, add a new object to the array/list — no other file needs to change unless noted.
Source of truth for the Events Archive, homepage event cards, the events network graph, and the
per-program pages (programs/faculty.html filters this by type: "faculty", etc.).
{
"id": "unique-slug",
"name": "HackHPC@Example26",
"url": "https://hackhpc.github.io/example26/",
"github_repo": "https://github.com/HackHPC/example26",
"start_date": "2026-06-22",
"end_date": "2026-06-26",
"date_display": "June 22–26, 2026",
"type": "hackathon",
"category": "ADMI",
"description": "One-sentence description shown on event cards.",
"partners": ["ADMI", "SGX3"],
"teams_url": "https://hackhpc.github.io/example26/teams.html",
"schedule_url": null,
"organizers_url": null,
"mentors_url": null,
"doi": null,
"citation_url": "https://hackhpc.github.io/example26/",
"citation_key": "hackhpc2026example26",
"citation_apa": "HackHPC. (2026). *HackHPC@Example26*. https://hackhpc.github.io/example26/",
"citation_ieee": "HackHPC, \"HackHPC@Example26,\" 2026. [Online]. Available: https://hackhpc.github.io/example26/",
"citation_bibtex": "@misc{hackhpc2026example26,\n author = {HackHPC},\n title = {HackHPC@Example26},\n year = {2026},\n url = {https://hackhpc.github.io/example26/}\n}",
"teams": [
{ "name": "Team Name", "github": "https://github.com/org/repo", "award": null }
],
"videos": [
{ "name": "Session Title", "summary": "One-sentence summary.", "url": "https://www.youtube.com/watch?v=..." }
]
}typedrives the badge color/label and which "Programs" page picks it up:hackathon,codeathon,faculty, ortraining.categoryis the hosting conference/program (ADMI, Gateways, SGX3, TACC, PEARC, SC, MS-CC, International, …) — it's the hub grouping used by the network graph on the About page (seeevents_network.jsonbelow). Reuse an existing category where it fits.teamsandvideosare optional arrays; omit the key entirely if an event has neither.- Fields left
nullare simply not rendered (e.g. no "Mentors" link shown ifmentors_urlisnull).
Powers the homepage "Core Partners" strip and the full tiered list on /partners/.
{
"name": "Organization Name",
"url": "https://example.org/",
"mentions": 3,
"tier": "core",
"description": "One sentence on how they've supported HackHPC.",
"icon": "/assets/img/partners/organization-name.svg",
"fa_icon": null
}tiercontrols which section it appears in and is a manual editorial call, not purely derived frommentions:core("Core Partners", homepage strip + top billing on/partners/),program("Program & Event Partners"), orcollaborating("Collaborating Organizations").mentionsis just a display count (shown as "N events") — update it by hand when you add an event that credits this partner; nothing recomputes it automatically.- Icon: set either
icon(a path to an SVG/PNG underassets/img/partners/orassets/icons/favicons/) orfa_icon(a Font Awesome brand icon name, e.g."github"→ rendered asfa-brands fa-github) — not both. Leave bothnullfor a plain letter-avatar fallback.
Powers the searchable school grid on /partners/.
{
"name": "Example University",
"url": "https://www.example.edu",
"slug": "example-university",
"icon": "/assets/img/schools/example-university.svg",
"event_count": 2,
"events": ["event-id-one", "event-id-two"]
}events is a list of events.json ids. event_count is just the length of that list, kept
as a separate field for quick display — update both together.
The small "Mentor Gallery / curricula / etc." grid at the top of /resources/. Deliberately
short — this is for a handful of permanent, non-event-specific resources.
{
"name": "Resource Name",
"url": "https://example.org/",
"github_repo": "https://github.com/HackHPC/repo",
"type": "Mentor Directory",
"description": "One sentence describing it."
}Powers the searchable "FacultyHack Modified Courses" grid on /resources/.
{
"event": "FacultyHack@Gateways 2026",
"event_id": "facultyhack-gateways26",
"course_name": "Intro to Data Science",
"course_number": "CSC 1311",
"school": "Example University",
"description": "What the faculty member changed about the course.",
"github": null
}event_id should match an id in events.json so the card can link back to that event; if it
doesn't match anything, the card still renders with plain (non-linked) event text.
The "Data Sources" grid on /resources/ — external datasets useful for hack projects.
{
"name": "Dataset Name",
"description": "One sentence on what it is.",
"url": "https://example.org/data",
"icon_type": "img",
"icon": "/assets/icons/favicons/example-org.svg"
}See §5 for icon_type/icon.
The big, categorized "Resource Library" grid on /resources/ (science gateways, computing
platforms, dev tools, AI tools, careers, etc.).
{
"category": "AI Tools & Resources",
"name": "Resource Name",
"url": "https://example.org/",
"description": "One sentence describing it.",
"icon_type": "img",
"icon": "/assets/icons/favicons/example-org.svg"
}Items are grouped on the page by category (via Liquid's group_by), in the order each
category first appears in the file — reuse an existing category string to land a new item in an
existing group, or introduce a new category string to create a new group automatically.
Powers /about/organizers.html.
{
"name": "Full Name",
"slug": "full-name",
"affiliation": "Institution or Company",
"affiliation_url": "https://example.org/",
"bio": "A few sentences.",
"linkedin": null,
"twitter": null,
"github": null,
"website": null,
"google_scholar": null,
"orcid": null,
"photo": "/assets/img/organizers/full-name.png",
"affiliation_icon": "/assets/img/partners/institution.svg"
}Every social/profile field is optional — set unused ones to null and that link is omitted.
slug is used for in-page anchors (other pages link to /about/organizers.html#slug).
Powers /research/. YAML instead of JSON (long multi-line summary/citation_bibtex fields
read better as YAML block scalars). Header comment in the file itself documents the schema; the
short version:
- category: paper # paper | media | video
authors: "Last, F., Last, F."
title: "Paper Title"
venue: "Conference or Publication Name"
date: "2026-06-01" # ISO date, used for sorting
date_display: "June 2026" # human-readable date shown on the page
summary: >-
A paragraph describing the work, using YAML's folded block scalar (>-) so long
prose can wrap across lines in the source file.
citation_key: "lastname2026title"
citation_apa: "..."
citation_ieee: "..."
citation_bibtex: |
@article{lastname2026title,
...
}media and video entries follow the same shape but typically omit the citation fields.
Powers the icon row in the footer.
- name: Mastodon
url: "https://example.social/@hackhpc"
username: hackhpc
icon: "fa-brands fa-mastodon"icon is a full Font Awesome class string (fa-brands fa-<name>), used as-is — check
fontawesome.com for available brand icons. The
footer renders every entry in the list in order, so just append a new item.
A short list shown at the top of the Events Archive's video section (things like the Code of Conduct video that aren't tied to one event).
{
"name": "Video Title",
"summary": "One sentence.",
"url": "https://www.youtube.com/watch?v=..."
}These two are not simple append-to-a-list files:
participants_dashboard.jsonis a pre-aggregated snapshot (counts, percentages, chart data) computed from a participant roster that isn't itself in this repo — see its owngenerated_notefield. It powers the "Community Dashboard" charts on/about/. To update it, regenerate the whole file from the source roster; don't hand-edit individual numbers.events_network.jsonholds precomputed(x, y)node/edge positions for the network graph on/about/(conferences as hubs, events as spokes), laid out once with Python'snetworkx(spring_layout) because Jekyll/Liquid can't run a force-directed layout. If you add or remove events inevents.json, this file goes stale — regenerate it by rebuilding the graph fromevents.json(root → one hub per uniquecategory→ one node per event) and rerunning the layout; there's no way to add a single node by hand and have it look right.
data_sources.json and external_resources.json (and partners.json, less formally) share one
icon convention, rendered through _includes/resource-icon.html:
icon_type |
icon value |
Renders as |
|---|---|---|
fa-brand |
a Font Awesome brand name, e.g. "github" |
<i class="fa-brands fa-github"> |
fa-solid |
a Font Awesome solid icon name, e.g. "globe" |
<i class="fa-solid fa-globe"> — the fallback used when no logo/favicon is available |
img |
a path, e.g. "/assets/icons/favicons/example-org.svg" |
<img src="..."> |
For img, the convention used across assets/icons/favicons/ is: fetch the site's real favicon
if one exists, and if it's a raster image (ICO/PNG/JPG), wrap it in a minimal SVG (a single
<image> element with the raster embedded as a base64 href) so every icon file is a .svg
regardless of source format. Fall back to fa-solid fa-globe only when no usable favicon exists
at all.
- New event → add an object to
events.json. If it should show up as a hub-connected node on the About page graph, also regenerateevents_network.json(§4). - New partner → add an object to
partners.json, pick atier, drop a logo inassets/img/partners/(or usefa_iconif it's a recognizable brand already in Font Awesome). - New resource link (dataset or general resource) → add an object to
data_sources.jsonorexternal_resources.json, and fetch/convert an icon per §5. - New team/video on an existing event → edit that event's
teams/videosarray inevents.jsondirectly. - New publication → append to
research.yml.
None of these require editing an .html template — the templates iterate over site.data.*
already.