How Lepton Handles Paginated Results from the GitHub Gist API

Lepton employs a dual-strategy pagination system that uses parallel fetching when GitHub's Link headers are present and falls back to sequential iteration for accounts where headers are missing.

Lepton is an open-source snippet manager that synchronizes with GitHub Gists to provide developers with a desktop interface for their code snippets. When retrieving a user's complete gist collection, the application must navigate paginated results from the GitHub Gist API efficiently. The implementation in app/utilities/githubApi/index.js employs two distinct strategies to ensure complete data retrieval regardless of account configuration.

Dual-Strategy Pagination Architecture

When the GitHub API response includes a standard Link HTTP header, Lepton activates its V2 strategy. This approach parses the header to determine the total number of pages, then fetches all remaining pages in parallel.

The implementation extracts the maximum page number from the Link header using regex matching:

// https://github.com/hackjutsu/Lepton/blob/master/app/utilities/githubApi/index.js#L91-L94
const matches = res.headers.link.match(/page=[0-9]*/g)
const maxPage = matches[matches.length - 1].substring('page='.length)

After determining maxPage, the code creates an array of promises for pages 2 through maxPage and executes them concurrently using Promise.all:

// https://github.com/hackjutsu/Lepton/blob/master/app/utilities/githubApi/index.js#L95-L99
for (let i = 2; i <= maxPage; ++i) { 
  requests.push(requestGists(token, userId, i, gistList)) 
}
return Promise.all(requests).then(() => gistList.sort(...))

V1 Fallback Strategy for Legacy Accounts

For accounts where the Link header is absent—such as those with two-factor authentication or certain enterprise configurations—Lepton falls back to its V1 strategy. This method iterates sequentially through pages up to a hard-coded maximum of 100 pages (MAX_PAGE_NUMBER).

The sequential approach uses Promise.mapSeries to process pages one at a time:

// https://github.com/hackjutsu/Lepton/blob/master/app/utilities/githubApi/index.js#L124-L145
const maxPageNumber = 100
const funcs = Promise.resolve(
  makeRangeArr(1, maxPageNumber).map(
    n => makeRequestForGetAllGists(makeOptionForGetAllGists(token, userId, n))))
funcs.mapSeries(iterator)

The iteration stops when a page returns an empty body, triggering a custom EMPTY_PAGE_ERROR_MESSAGE error that the catch block interprets as the end of available data.

Core Implementation Details in app/utilities/githubApi/index.js

The pagination logic resides primarily in app/utilities/githubApi/index.js, which exports the getAllGistsV2 and getAllGistsV1 functions. The main entry point getAllGistsV2 begins by requesting page 1 and inspecting the response headers:

// https://github.com/hackjutsu/Lepton/blob/master/app/utilities/githubApi/index.js#L76-L85
if (!res.headers.link) {
  logger.debug(TAG + '[V2] The header missing link property')
  return getAllGistsV1(token, userId)
}

Individual page requests are constructed using makeOptionForGetAllGists, which builds the request configuration including the page and per_page parameters. The requestGists function then executes the request using request-promise and parses the response body:

// https://github.com/hackjutsu/Lepton/blob/master/app/utilities/githubApi/index.js#L108-L118
return ReqPromise(makeOptionForGetAllGists(token, userId, page))
  .then(res => { parseBody(res.body, gistList); return res })

The parseBody helper iterates over the response object values and appends them to the shared gistList array:

// https://github.com/hackjutsu/Lepton/blob/master/app/utilities/githubApi/index.js#L20-L22
for (const key in res) { 
  if (Object.prototype.hasOwnProperty.call(res, key)) gistList.push(res[key]) 
}

Practical Usage Examples

To fetch all gists for the authenticated user, the application calls the high-level API wrapper:

import { getGitHubApi, GET_ALL_GISTS } from '../utilities/githubApi'

// token and userLoginId are obtained after OAuth login
getGitHubApi(GET_ALL_GISTS)(token, userLoginId)
  .then(gistList => {
    console.log('All gists (sorted):', gistList)
  })
  .catch(err => console.error('Failed to sync gists:', err))

For debugging or manual pagination, you can request a specific page directly:

import { makeOptionForGetAllGists } from '../utilities/githubApi'
import ReqPromise from 'request-promise'

const options = makeOptionForGetAllGists(token, userId, 3) // page 3
ReqPromise(options).then(res => {
  console.log('Page 3 payload:', res.body)
})

Summary

  • Lepton implements dual-strategy pagination to handle paginated results from the GitHub Gist API, automatically selecting between parallel and sequential fetching based on response headers.
  • The V2 strategy parses the Link HTTP header to determine the total page count, then fetches remaining pages in parallel for optimal performance.
  • The V1 fallback iterates sequentially through up to 100 pages, stopping when an empty response signals the end of available data.
  • All pagination logic is centralized in app/utilities/githubApi/index.js, with clear separation between the modern header-based approach and the legacy sequential method.

Frequently Asked Questions

Why does Lepton use two different pagination strategies?

Lepton uses two strategies to ensure compatibility across different GitHub account configurations. The V2 strategy relies on the standard Link HTTP header for efficient parallel fetching, but some accounts—particularly those with two-factor authentication or certain enterprise setups—do not return this header. The V1 fallback ensures Lepton can still retrieve complete gist collections for these accounts by iterating sequentially until no more data is returned.

How does Lepton determine the maximum number of pages in V2 mode?

In V2 mode, Lepton extracts the maximum page number from the Link header returned by the GitHub API. The code uses a regular expression to match all page=[0-9]* occurrences in the header string, then selects the last match as the maxPage value. This value determines how many parallel requests are queued for the remaining pages.

What happens if the GitHub API returns an empty page during V1 fallback?

During the V1 fallback sequence, Lepton checks if the response body is empty after each page request. If a page returns an empty body, the code throws a custom EMPTY_PAGE_ERROR_MESSAGE error. The surrounding promise chain catches this specific error and interprets it as a signal that all available gists have been retrieved, causing the iteration to stop gracefully rather than continuing to the hard-coded limit of 100 pages.

Where is the pagination logic implemented in the Lepton codebase?

The pagination logic is implemented in app/utilities/githubApi/index.js. This file contains the getAllGistsV2 and getAllGistsV1 functions that handle the modern and fallback strategies respectively. It also exports helper functions like requestGists, makeOptionForGetAllGists, and parseBody that construct requests and process responses across both pagination modes.

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 →