Personal site for Carlos Rondón-Moreno — single-page React app served as static files via GitHub Pages at carlosrondonmoreno.com.
No build step. The site is plain static files:
index.html— entry point. Loads React, ReactDOM, and Babel-standalone from the unpkg CDN, then loads the.jsxsource files. JSX is compiled in the browser at page load.data.js— all content (papers, courses, service, command palette items, palette swatches, font pairings) lives here as plain JS objects. This is the file you'll edit most often.app.jsx— top-level React app: state, routing (hash-based), keyboard shortcuts, tweaks panel wiring.variation-a.jsx— homepage layout (the terminal/shell aesthetic).subpages.jsx— Research, Teaching, Service, Code pages.command-palette.jsx—/-triggered command palette.tweaks-panel.jsx— live theming controls (color, font, density, pattern, nav palette).styles.css— all styling.404.html— styled fallback for unknown paths.assets/,content/— images and PDFs (CV lives incontent/).CNAME— custom domain config (carlosrondonmoreno.com).sitemap.xml,robots.txt— for search engines.contact.html,research.html,teaching.html,service.html— legacy URL stubs that redirect to the relevant section of the SPA.
The site uses runtime JSX compilation via Babel, which needs to fetch the .jsx files. Browsers block these fetches when you open index.html directly via file://, so the page will appear blank. Always serve over HTTP:
python3 -m http.server 8000
# then open http://localhost:8000VS Code's built-in HTML preview pane will not work — its webview blocks the unpkg CDN scripts and the JSX fetches. Use a real browser.
Almost every content edit happens in data.js. After editing, just refresh the browser — no build step.
Edit the PAPERS array in data.js. Each entry has the shape:
{
yr: "2025", // year, or "WIP" for work-in-progress
tag: "PUBLISHED", // PUBLISHED | PLOS ONE | WP №xxx | DRAFT
venue: "Journal of ..., Vol X", // shown after author list
title: "Paper title",
authors: "with Coauthor One, Two", // shown only if coauthors[] is empty
coauthors: [ // preferred — renders linked names
{ name: "Coauthor Name", url: "https://..." }
],
pdf: "https://doi.org/...", // optional
github: "https://github.com/...", // optional
appendix: "https://...", // optional
short: "short.slug" // shown on the homepage card
}The homepage shows the first 3 entries (PAPERS.slice(0, 3)), so order matters — put newest first. The Research subpage filters by tag (PUBLISHED/PLOS ONE → "published", WP №... → "working papers", DRAFT → "work in progress").
When adding a paper, also update the static fallback in index.html — the <ul> inside <div id="root"> lists the top 3 papers for SEO/link-preview bots that don't run JavaScript. Keep the two roughly in sync.
Edit the REPOS array in data.js. Each entry has the shape:
{
name: "repo-name", // repository name, shown as the linked title
new: true, // optional — shows a gold "NEW" badge on the card + Code page
yr: "2026", // year
tag: "UTILITY", // short category label (UTILITY, REPLICATION, LIBRARY, …)
lang: "Bash · macOS", // language / platform, shown as a pill and on the homepage card
blurb: "One-paragraph description.", // pulled from the repo's README
github: "https://github.com/...", // repo URL
pdf: "https://...", // optional — docs/paper link, rendered as "docs ↗"
short: "repo.short.slug" // shown on the homepage card
}The homepage recent.code card shows the first 3 entries (REPOS.slice(0, 3)), so order matters — put newest first. The Code subpage lists them all under // repositories. Add extras: [{ label, url }] for any additional links.
Edit the COURSES array in data.js:
{
code: "Fall\n2026*", // semester label; trailing "*" renders as a footnote marker
name: "Course Name",
sub: "Department · University, Location",
where: "Instructor" // or "Teaching Assistant"
}The * suffix flags southern-hemisphere academic-calendar courses (footnote rendered automatically at the bottom of the Teaching page).
Edit the SERVICE array in data.js:
{
when: "January\n2026",
org: "Organization name",
orgUrl: "https://...", // optional — makes the org name a link
body: "Specific committee or event",
role: "Your role",
where: "Location or context",
cat: "society" // "society" → Elected positions; anything else → Conferences & workshops
}Replace content/Rondon_CV.pdf with the new file (keep the same filename so existing links don't break). Update lastmod for the CV entry in sitemap.xml.
The homepage (variation-a.jsx) is a .hero (bio + photo) above a full-width .cards grid holding the recent.papers, recent.code, and sce / news cards. Headline name, bio paragraphs, and the sce / news card text all live in variation-a.jsx. The static SEO fallback bio is in index.html — keep them roughly aligned.
Edit CMD_ITEMS in data.js. New action strings need to be handled in the onAction switch in app.jsx.
GitHub Pages is configured to serve the main branch. Just commit and push:
git add -A
git commit -m "Update papers"
git pushPages picks up the change within a minute or two. No build pipeline, no Actions to wait on.
DNS for carlosrondonmoreno.com points at GitHub Pages, with HTTPS enforced in repo Settings → Pages.
- The
<div id="root">inindex.htmlcontains a static fallback (name, bio, top papers, section links) that crawlers and social-card bots see before React hydrates. Keep it lightly maintained when papers change. - JSON-LD
Personschema is in the<head>for richer search results. sitemap.xmllists the canonical URLs (homepage hash anchors plus the CV).- The legacy
*.htmlfiles (research.html,teaching.html, etc.) redirect to the relevant SPA hash — preserves any external links pointing at the old multi-page version of the site.
MIT — see LICENSE.