How Mustache Templating Powers Resume Generation in GitHub Resume

Mustache templating generates dynamic résumés by merging static HTML templates with JSON data from the GitHub API, rendering the final page entirely on the client side without server-side processing.

The resume.github.com project transforms GitHub profiles into polished résumés using client-side Mustache templating. Instead of server-side rendering, the application fetches static HTML templates and populates them with data retrieved from the GitHub API, creating a lightweight, dynamic user experience.

The Mustache Templating Architecture

Template Loading Strategy

Located in js/githubresume.js (lines 998-1003), the application determines which template to load based on the GitHub account type. For individual users, it fetches views/resume.html; for organizations, it uses views/resumeOrgs.html.

// githubresume.js – line 998-1003
var resume = (data.type == 'User' ? 'views/resume.html' :
              'views/resumeOrgs.html');
$.ajax({
    url: resume,
    dataType: 'html',
    success: function(data) {
        var template = data,
            html = Mustache.to_html(template, view);
        $('#resume').html(html);
});

View Object Construction

Before rendering, the script constructs a view object (lines 22-39 in js/githubresume.js) that maps GitHub API fields to template variables. This object includes user metadata, repository counts, follower statistics, and derived fields like userStatus and since.

// githubresume.js – lines 22-39
var view = {
    name: name,
    type: data.type,
    email: data.email,
    gravatar_id: data.gravatar_id,
    avatar_url: avatar,
    repos: data.public_repos,
    reposLabel: data.public_repos > 1 ? 'repositories' : 'repository',
    followers: data.followers,
    followersLabel: data.followers > 1 ? 'followers' : 'follower',
    username: username,
    userStatus: getUserStatus(),
    since: since,
    resume_url: window.location
};

Rendering Process

Main Resume Template

The Mustache.to_html() function merges the template with the view object. In views/resume.html, placeholders like {{name}}, {{userStatus}}, and conditional blocks like {{#gravatar_id}} render user-specific content.

<!-- views/resume.html -->
<h1 class="fn">{{name}}</h1>
<h2>{{userStatus}}</h2>
{{#gravatar_id}}
<img src="https://secure.gravatar.com/avatar/{{gravatar_id}}?s=140&d=…" class="photo"/>
{{/gravatar_id}}
{{#email}}<a href="mailto:{{email}}" class="email">{{email}}</a>{{/email}}

Fragment Templates for Dynamic Content

After the main template renders, the application loads secondary templates for specific sections. Files like views/job.html, views/contrib.html, and views/org.html receive their own view objects containing repository details, contribution statistics, and organization memberships.

Each fragment template is processed using the same Mustache.to_html(template, view) pattern, allowing modular rendering of repository lists, contribution graphs, and organizational affiliations without reloading the page.

Key Source Files and Implementation Details

File Role Link
js/githubresume.js Core JavaScript: fetches GitHub data, builds the view objects, loads Mustache templates and renders them. githubresume.js
views/resume.html Main Mustache template for a regular user résumé. resume.html
views/resumeOrgs.html Template used when the target is a GitHub organization. resumeOrgs.html
views/job.html Fragment template that renders each repository entry (language bar, description, stars, forks). job.html
views/contrib.html Fragment template for the contributions list (merged PRs). contrib.html
views/org.html Fragment template for the organizations section. org.html
index.html Entry point; loads Mustache library (mustache.js) and starts the JavaScript app. index.html

These files together illustrate the full flow: data → view object → Mustache template → rendered résumé.

Summary

  • Mustache templating enables fully client-side résumé generation without server-side rendering
  • The view object in js/githubresume.js bridges GitHub API data and HTML templates
  • Template selection logic distinguishes between individual users (views/resume.html) and organizations (views/resumeOrgs.html)
  • Fragment templates (views/job.html, views/contrib.html) handle dynamic content sections
  • The Mustache.to_html() function performs the final template-to-HTML transformation

Frequently Asked Questions

What is Mustache templating and why is it used in resume.github.com?

Mustache is a logic-less template syntax that uses double braces for variable substitution. The resume.github.com project uses it to separate presentation (HTML templates) from data (GitHub API responses), enabling clean client-side rendering without server-side dependencies. This approach keeps the application lightweight and allows the same JavaScript code to serve different layouts for users versus organizations.

How does the application decide which template to load?

The JavaScript code in js/githubresume.js checks the data.type property from the GitHub API response. If the value is "User", it loads views/resume.html; otherwise, it loads views/resumeOrgs.html for organizations. This conditional logic ensures that individuals see repository-focused layouts while organizations display member and team information.

Can I customize the Mustache templates for my own résumé?

Yes, the template files in the views/ directory are standard Mustache HTML files. You can modify resume.html, job.html, or other fragments to change the layout, styling, or content structure, provided you maintain the variable names expected by the view object in githubresume.js. Since rendering happens client-side, any changes to these templates take effect immediately without rebuilding the application.

What happens if a GitHub user has no email or Gravatar configured?

The templates use Mustache sections (e.g., {{#email}}...{{/email}}) to conditionally render content. If the email or gravatar_id properties are missing or empty in the view object, those sections are omitted from the final HTML output, preventing broken links or empty elements. This logic-less conditional rendering ensures the résumé displays only available information.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →