Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

resume.github.com User Guide

Generated April 2026 from resume/resume.github.com at f599075

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

resume.github.com is a small, single-page web app that turns any public GitHub profile into a printable, share-friendly résumé. It runs entirely in the browser: a tiny JavaScript file pulls public data from the GitHub REST API, fills in a Mustache template, and renders the result as a styled CV that prints cleanly to PDF or paper.

This guide is written for the end user — the person who wants to generate their own résumé page or look up someone else's. It covers the hosted site (no install required), the optional self-hosted setup, and every visible behaviour of the front-end. For internals, deployment, and security notes, see the companion Administrator & Developer Guide in the same folder.

Note

The repository is dormant — the f599075 commit this guide is pinned to dates from August 2016. The site itself (https://resume.github.com) still works because it depends only on the public GitHub REST API, jQuery, and Mustache. There is no backend, no database, and no account to create.

1. Quick Start

The fastest way to use this project is to visit the hosted site — there is nothing to install, and no account to create.

Generate your résumé in 30 seconds

  1. Open the hosted site: https://resume.github.com.
  2. Sign in to GitHub if you aren't already, and star the resume/resume.github.com repository. This is the project's opt-in mechanism — without a star on that repo, the app will refuse to render your profile.
  3. Append your GitHub username as a query string: https://resume.github.com/?yourusername.
  4. Wait a moment while the page fetches your profile, repos, merged pull requests, and organisations from api.github.com.
  5. When the résumé renders, click the Print button at the top of the page (or use your browser's Ctrl+P / Cmd+P) to save it as a PDF or send it to a physical printer.

Tip

The query-string syntax is unusual — there is no ?username= key, just the bare value: ?octocat, ?defunkt, ?torvalds. The first key from window.location.search is read as the username regardless of its name, so ?u=octocat and ?octocat=anything both resolve to the user octocat or u respectively.

What the page actually shows

A rendered résumé pulls from your public GitHub data only and contains:

  • Identity block — display name (falls back to login), avatar, location, email, blog URL, and join date. If you joined GitHub in the first four months (Feb–May 2008) the page tags you as an Early Adopter.
  • Status label — a single line ranging from Inactive GitHub user to Passionate GitHub user, computed from a weighted score of your repositories, gists, followers, and following counts.
  • Top languages — up to nine programming languages you publish in, ranked by repository count, displayed with a percentage of your total.
  • Featured projects — up to five non-fork repositories ranked by popularity (watchers + forks), with name, year span, language, and description. Emoji shortcodes (:rocket:) are rewritten to GitHub's 20×20 emoji images.
  • Open-source contributions — repositories where your merged pull requests live, ranked by the number of merged PRs you authored.
  • Organisations — up to five organisations you belong to (subject to a shared item-count limit).
  • Print button — calls window.print() for a clean, paginated output.

Important

The site fetches data via JSONP (?callback=?). That means the unauthenticated public GitHub API is used, with its global rate limit of 60 requests per hour per IP address. Multiple résumé loads from the same network can hit the limit and trip the API limit reached screen.

Looking up someone else

The same query-string mechanism works for any GitHub user or organisation. Try https://resume.github.com/?defunkt to see one of GitHub's earliest employees, or substitute any login. The look-up is read-only — no data about the visitor is sent to GitHub beyond what the unauthenticated API calls naturally include.

2. Installation

Most users do not need to install anything. The project is a public website, and the only "installation" required is starring the repository in your GitHub account so the opt-in check passes.

Step Action Where
1 Sign in to GitHub https://github.com
2 Star resume/resume.github.com https://github.com/resume/resume.github.com (click the Star button)
3 Open your résumé https://resume.github.com/?yourusername

That's the entire installation. There is no package to download, no CLI to install, and no configuration file to edit.

Tip

If you ever want to opt out of being rendered, simply unstar the repository. The next time someone visits https://resume.github.com/?yourusername they will see the opt out screen instead of your résumé.

Path B — Run a local copy

You only need to run the project locally if you want to embed it in your own site, customise the styling, or develop a fork. The repository is a plain static site plus a one-line Rack runner; any static file server works.

Prerequisites

  • [x] A copy of the source: git clone https://github.com/resume/resume.github.com.git
  • [x] One of: Ruby + Rack, Python, Node.js, or any other static file server
  • [x] A modern browser with JavaScript enabled

Run with Rack (matches the upstream config.ru)

cd resume.github.com
gem install rack
rackup config.ru
[2026-04-29 10:00:00] INFO  WEBrick 1.7.0
[2026-04-29 10:00:00] INFO  ruby 3.2.2 (2023-03-30) [x86_64-linux]
[2026-04-29 10:00:00] INFO  WEBrick::HTTPServer#start: pid=12345 port=9292

Then visit http://localhost:9292/?yourusername.

Run with Python's built-in server

cd resume.github.com
python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Then visit http://localhost:8000/?yourusername.

Run with Node's http-server

cd resume.github.com
npx http-server -p 8080

Then visit http://localhost:8080/?yourusername.

Warning

If you load index.html directly via file:// (double-clicking the file in your file manager), the $.ajax calls that fetch views/index.html, views/resume.html, etc. will be blocked by your browser's same-origin / file:// policy. Always serve over HTTP, even for local development.

Verifying a local install

Once your server is running, verify each piece in turn:

curl -s http://localhost:9292/index.html | head -5
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Resume</title>

If the index page loads but no résumé appears when you append ?<username>, open your browser's developer console — the front end logs JavaScript errors via console.log(err) from inside the $(document).ready block.

3. Configuration

The repository ships with no configuration file, no environment variables, and no command-line flags. Everything that the page does is controlled by either the URL query string or hard-coded constants in js/githubresume.js.

Runtime input — the URL

Input Where What it does
Bare query string (e.g. ?octocat) After ? in the URL Sets the GitHub username to render. The first key parsed from window.location.search becomes the value of username. Empty query routes to the home page.
https:// vs http:// Page protocol Determines whether Google Analytics loads from https://ssl.google-analytics.com or http://www.google-analytics.com.

Note

The URL parser walks window.location.search once and assigns the result to urlParams[0]. It does NOT support multiple parameters, named keys (?username=…), or fragments. Any extra &key=value pairs are ignored.

Hard-coded knobs (require editing source)

If you self-host and want to tweak behaviour, these are the only values worth knowing about. They live near the top of js/githubresume.js or inside the run() function. See the Admin Guide for the full reference.

Constant Default What it controls
trackerId 'UA-21222559-1' Google Analytics property. Set to falsy to disable analytics entirely.
maxItems 5 Maximum featured projects shown. Also reused as the soft cap for organisations.
maxLanguages 9 Maximum number of languages displayed in the Languages block.
COEF_REPOS, COEF_GISTS, COEF_FOLLOWERS, COEF_FOLLOWING 2, 0.25, 0.5, 0.25 Weighting coefficients for the user-status score.
FIRST_STEP … FIFTH_STEP 0, 5, 20, 50, 150 Score thresholds that map to the Inactive → Passionate labels.

Tip

If you fork the project for your own portfolio, the very first edit almost everyone makes is replacing trackerId with their own Google Analytics ID, or removing the analytics block at the bottom of js/githubresume.js entirely.

Stylesheets

Two CSS files control the appearance:

  • css/resume.css — on-screen styling, layout, colours.
  • css/print.css — applied via @media print, strips colour and chrome for clean PDF output.

You can edit these directly without touching JavaScript. The HTML view fragments in views/*.html are Mustache templates rendered into a single <div id="resume"> host element, so any CSS selector that targets a template's class will style the rendered output.

4. Core Usage

This section walks through every visible behaviour and screen in the app, in the order a real visitor encounters them.

4.1 Landing page (no username)

When you load the site with no query string, the JavaScript falls into the home() branch and AJAX-loads views/index.html into the #resume container. This is the default landing experience — a brief introduction plus an input field for the username.

4.2 Rendering a résumé

When the URL contains a query string, the run() function executes a multi-step pipeline:

  1. Star check — synchronous GET https://api.github.com/users/<user>/starred?per_page=100, paginated 100 at a time. The walker stops as soon as it sees resume/resume.github.com in repo.full_name. If the user has not starred the repo, views/opt_out.html is shown.
  2. User profile — GET https://api.github.com/users/<user>?callback=? (JSONP). Populates the identity block, computes Early Adopter and the Status Label.
  3. Repositories — GET https://api.github.com/users/<user>/repos?per_page=100&callback=?, paginated. Forks are filtered out. The remainder are sorted by watchers + forks, top five rendered into #jobs from views/job.html, and the language histogram populated.
  4. Merged pull requests — GET https://api.github.com/search/issues?q=type:pr+is:merged+author:<user>&per_page=100&callback=?. Results are bucketed by repository_url, sorted by count, and rendered into #contrib-jobs from views/contrib.html.
  5. Organisations — GET https://api.github.com/users/<user>/orgs?callback=?. Up to maxItems organisations are rendered into #orgs from views/org.html.
  6. Title update — the document title becomes <Name>'s Résumé.
  7. Print binding — the #actions #print element is wired to call window.print().

Note

The user profile, repositories, merged PRs, and organisations calls all run in parallel as soon as the star check passes. Render order is therefore not deterministic — the first block that returns from GitHub populates first.

4.3 The status label

Your résumé header includes a single status string. It is derived from this formula:

score = (public_repos    * 2.00)
      + (public_gists    * 0.25)
      + (followers       * 0.50)
      + (following       * 0.25)
      + (early_adopter ? 1 : 0)
      + (location && email && blog ? 1 : 0)

The score then maps to a label:

Score Label
0 Inactive GitHub user
0 < s ≤ 5 Newbie GitHub user
5 < s ≤ 20 Regular GitHub user
20 < s ≤ 50 Advanced GitHub user
50 < s ≤ 150 Enthusiastic GitHub user
> 150 Passionate GitHub user

The Early Adopter tag is awarded if your account was created in 2008 through May (or earlier — the original code includes a since <= '2007' branch even though GitHub launched in February 2008).

The repos table renders five rows. Each row pulls from one of your non-fork repositories, ranked by watchers + forks (so popularity, not recency, drives the order). The shape of each row is:

Field Source
Name repo.name
Date repo.created_at year, optionally created – pushed if different
Language repo.language
Description repo.description (with :emoji: shortcodes rewritten to GitHub's emoji images)
Watchers repo.watchers (label switches between star and stars)
Forks repo.forks (label switches between fork and forks)
Homepage repo.homepage

Note

"Watchers" here is the legacy GitHub field — what's now called Stars. The label 'stars' is shown on rendered output, but the underlying JSON property is watchers.

4.5 Languages bar

The languages histogram counts each non-fork repo's language field once, sorts by frequency, takes the top nine, and renders each as <a href="https://github.com/search?q=user:<name>&l=<encoded language>">…</a> with a percentage of the total. Languages are grouped into rows of three in the rendered HTML.

4.6 Open-source contributions

This block uses GitHub's search-issues endpoint to count merged PRs authored by the user, grouped by repository. Each row links to the /commits?author=<user> URL on the upstream project.

Warning

The search endpoint is heavily rate-limited (separate from the regular 60-per-hour limit) and search results are capped at 1000 items globally. Users with very large contribution histories may see incomplete contribution lists.

4.7 Organisations

The orgs section is rendered from views/org.html. It uses the legacy /orgs endpoint without a per-page parameter and shares the itemCount counter with the projects block — so if a user already has five featured projects rendered, organisations are silently truncated.

4.8 Printing

The #print button at the top of the page calls window.print(). Modern browsers will offer "Save as PDF" as a destination. The css/print.css sheet handles the print-only layout (fewer colours, removal of interactive chrome, page-friendly typography).

Tip

For the cleanest printable output, set your browser's print preview to No headers and footers and Default margins. Chrome and Edge both respect @media print and @page directives shipped in print.css.

5. Common Tasks

A handful of recipes for things visitors and self-hosters routinely need.

5.1 Save your résumé as a PDF

  1. Visit https://resume.github.com/?yourusername and wait for the page to fully render.
  2. Click the Print button or press Ctrl+P (Cmd+P on macOS).
  3. In the print dialog, choose Save as PDF as the destination.
  4. Check Background graphics is enabled if you want the avatar and colour accents to survive the export.
  5. Save. Done.

There is nothing to share other than the URL itself. Send https://resume.github.com/?yourusername in an email, in your LinkedIn Featured section, or as a vCard URL. The page is fully public — no authentication is required for the recipient.

Tip

If the recipient does not have a GitHub account, they can still view your résumé. The star check applies only to the subject of the résumé (the user being looked up), not the visitor.

5.3 Use the project for an organisation

Organisations and users share the same URL pattern: https://resume.github.com/?orgname will render an organisation résumé using the views/resumeOrgs.html template instead of the user template. The decision is made at runtime based on data.type === 'Organization' in the /users/<name> response.

5.4 Customise styling on a fork

  1. Fork resume/resume.github.com to your own GitHub account.
  2. Edit css/resume.css and css/print.css — these contain all visible styling.
  3. Push to your fork's master (or main) branch.
  4. Enable GitHub Pages for your fork on the master branch root.
  5. Visit https://<your-username>.github.io/resume.github.com/?<target-user>.

5.5 Embed in another site

Because the project is purely static and uses window.location.search for input, embedding via <iframe> is straightforward:

<iframe
  src="https://resume.github.com/?yourusername"
  width="800"
  height="1200"
  style="border:0">
</iframe>

Note

The frame will inherit the parent page's print CSS only when the user right-clicks the iframe and chooses Print. A regular full-page print from the parent will not include the iframe content.

5.6 Disable Google Analytics on a fork

Open js/githubresume.js, find the var trackerId = 'UA-21222559-1'; line, and either delete it, comment it out, or set it to a falsy value. The trailing analytics block will skip itself when trackerId is falsy.

6. Troubleshooting

Common failure modes, the cause behind each, and how to recover.

Error: page shows the Opt out screen instead of a résumé

Cause: The user being looked up has not starred the resume/resume.github.com repository on GitHub, so the github_user_starred_resume() check returned false.

Solution:

  1. Sign in to GitHub as the user whose résumé you want to display.
  2. Visit https://github.com/resume/resume.github.com.
  3. Click the Star button at the top right of the repo page.
  4. Reload https://resume.github.com/?yourusername and wait for the star to propagate to GitHub's API cache (usually instant).

Prevention: Star the repo as the very first step. Bookmark the star URL: https://github.com/resume/resume.github.com.

Error: page shows the API limit reached screen

Cause: Your IP has hit GitHub's unauthenticated rate limit (60 requests per hour). The starred-repos check alone consumes one request per 100 starred repos; users with many stars can blow through the budget quickly.

Solution:

  1. Wait until the next hour rolls over (the limit is per UTC hour, not sliding).
  2. Switch to a different network — a mobile hotspot or VPN egress with a different IP often has fresh quota.
  3. If you self-host, see the Admin Guide for the unsupported pattern of adding personal access tokens (the upstream project does not authenticate any of its requests).

Prevention: Avoid reloading the page repeatedly during testing. Cache responses if forking.

Error: page shows the Not found screen

Cause: The ?username you supplied does not match any GitHub user or organisation, so the /users/<name>/starred call returned HTTP 404.

Solution:

  1. Double-check the GitHub username for typos (case-insensitive but exact otherwise).
  2. Confirm the account still exists at https://github.com/<username>.
  3. If the account was renamed, use the new login.

Prevention: Use the exact login string from the user's GitHub URL (https://github.com/<this-part>).

Error: blank page, console shows a $ is not defined or AJAX error

Cause: Either jQuery / Mustache failed to load, or you opened index.html over the file:// protocol where AJAX is blocked.

Solution:

  1. Always serve the site over HTTP — see Section 2 for one-liner commands using Rack, Python, or Node.
  2. Open your browser's network tab and confirm the external scripts (jQuery, Mustache) are resolving without 404s.
  3. If on a corporate network, verify there's no proxy stripping third-party scripts.

Prevention: Use one of the supported local-dev paths in Section 2.

Error: Google Analytics throws a CSP violation in the console

Cause: Your hosting environment enforces a Content Security Policy that blocks Google Analytics scripts.

Solution:

  1. Edit js/githubresume.js and remove or comment out the trailing if (trackerId) block.
  2. Or extend your CSP to allow https://www.google-analytics.com and https://ssl.google-analytics.com.

Prevention: When forking, decide upfront whether you want analytics — many forks delete the block by default.

Error: page renders but the language list is empty

Cause: All of the user's non-fork repositories have a null language field (typical for documentation-only or assets-only repositories).

Solution: Nothing to do — the #mylanguages block is hidden via $('#mylanguages').hide(); when there are no languages to show.

Prevention: This is by design.

Error: only forks listed, message "All of this user's repositories seem to be forks"

Cause: The user genuinely has only forked repositories. The renderer filters out forks before sorting, so an empty sorted array reaches the template.

Solution: None — the message is the intended display. The user must publish original repositories on GitHub to populate the projects block.

Prevention: N/A — this reflects the source data accurately.

Error: organisation count is wrong

Cause: The itemCount counter is shared between the projects block and the organisations block. If the user already has five featured projects, no organisations are rendered.

Solution: Hard-fork and split the counter into projectCount and orgCount if you need both blocks fully populated. Edit the run() function in js/githubresume.js.

Prevention: This is a known quirk of the original code path.

7. FAQ

Q: Do I need to install anything to use this?

No. Visit https://resume.github.com/?yourusername after starring the resume/resume.github.com repo on GitHub. There is no app, no extension, no account.

Q: Why do I have to star the repo?

Starring is the project's opt-in mechanism. Without a star, the front-end shows the opt out screen rather than rendering your data. It also acts as a lightweight "thanks" to the project maintainers.

Q: Can I look up someone else's résumé?

Yes — the URL ?username works for any public user or organisation, provided that user has starred the repo. If they haven't, you'll see the opt-out screen.

Q: Is any data sent to a server I don't control?

The page makes calls to api.github.com (public REST API, JSONP) and to Google Analytics (google-analytics.com). No other endpoints are contacted. There is no first-party backend in this project.

Q: How do I stop people from rendering my profile?

Unstar resume/resume.github.com on GitHub. The next visitor will see the opt-out screen.

Q: Can I use my own domain?

Yes — fork the repo, edit css/resume.css to your taste, and serve the files from any static host (GitHub Pages, S3 + CloudFront, Netlify, Vercel). See Section 2, Path B.

Q: Does this work on mobile?

Yes for viewing. Printing from mobile browsers is generally less reliable than desktop — the Save as PDF destination is hidden behind different menus depending on the OS. For best results, generate PDFs from a desktop browser.

Q: Why is my year listed as "last year" or "this year"?

The renderer collapses year labels relative to the current year for recently-created GitHub accounts. If you joined this calendar year, you will see this year; if you joined the previous calendar year, last year. Older accounts show the four-digit year.

Q: Why does my contribution list look truncated?

GitHub's search-issues API caps results at 1000 items. Users with very high contribution counts will only see the first page of merged PRs. The project does not work around this limit.

Q: Will an organisation account work?

Yes. The renderer checks data.type === 'Organization' and uses views/resumeOrgs.html instead of the user template. The avatar URL is also rewritten to a Gravatar-only form for organisation accounts.

Q: How do I report a bug?

Open an issue at https://github.com/resume/resume.github.com/issues. Include the username you were trying to render, the browser version, and any console output. Note that the project has been quiet for years.

Q: Where is the source for the screen I'm seeing?

Each visible state corresponds to one HTML file in views/: index.html (landing), resume.html (user résumé), resumeOrgs.html (organisation résumé), job.html (one project row), org.html (one organisation row), contrib.html (one contribution row), error.html, api_limit.html, not_found.html, opt_out.html.

Q: Is there a CLI?

No. The project is browser-only.

Q: Is there a public API?

No. The project consumes GitHub's REST API but exposes none of its own.

Q: Are there any configuration files?

No. Apart from config.ru (which is two lines of Rack to serve static files), there are no configuration files.