How to Use index.html for Exercise Browsing: A Complete Guide to the Self-Contained Fitness Catalog

The index.html file in hasaneyldrm/exercises-dataset is a self-contained client-side web application that lets you browse 1,324 fitness exercises directly in your browser without any server setup or external dependencies.

The hasaneyldrm/exercises-dataset repository provides a fully functional exercise library as a single HTML file. When you use index.html for exercise browsing, you get a reactive interface with real-time search, multi-dimensional filtering, and detailed exercise modals—all powered by vanilla JavaScript and embedded data that requires no backend infrastructure.

Architecture of the Self-Contained Browser

Unlike traditional web apps that rely on API calls, the exercise browser ships with all data and logic bundled into one file. The EXERCISES array embedded at lines 71-73 contains the complete catalog of 1,324 fitness records, while the state object (lines 1175-1200) manages the reactive application state.

The App Shell and Layout Structure

The interface uses a CSS grid layout defined in the App Shell at lines 28-30, splitting the viewport into two primary regions:

  • Sidebar (lines 30-73): Houses the search input and three filter sections (Category, Equipment, Target Muscle)
  • Main Content (lines 75-87): Contains the results bar, exercise grid, and infinite-scroll sentinel

This static layout immediately renders upon opening the file, providing instant interactivity without waiting for network requests.

Client-Side State Management

The application tracks user interactions through a plain JavaScript state object:

const state = {
  exercises: [],      // Full dataset copied from EXERCISES
  filtered: [],       // Current subset based on active filters
  search: '',         // Current search string
  filters: {          // Active filter selections
    category: new Set(),
    equipment: new Set(),
    target: new Set()
  }
};

The applyFilters() function recomputes state.filtered whenever users type or toggle chips, triggering a reactive re-render of the exercise grid (lines 1248-1296).

The browser provides five primary interaction patterns for exploring the dataset.

Real-Time Search and Filtering

Type any term into the search box at the top of the sidebar to filter across exercise names, categories, body parts, equipment, and muscle groups. The input uses a 250ms debounce to optimize performance. Results update automatically through the wireEvents() listener registration (lines 1289-1340).

Filter chips under Category, Equipment, and Target Muscle allow toggling specific values. Active chips receive the .active class (orange styling), and selected filters appear as removable badges in the results bar. Click Clear all to invoke clearAllFilters() and reset the view.

Infinite Scroll Pagination

Rather than traditional pagination, the browser implements lazy loading via an IntersectionObserver watching the #load-sentinel element at the bottom of the grid. When this sentinel enters the viewport, appendNextPage() loads the next batch of 60 exercises from state.filtered, ensuring smooth scrolling through large result sets.

Exercise Detail Modals

Click any exercise card to trigger openModal(id), which overlays a detailed view (lines 155-165). The modal displays:

  • Full-size animated GIF preview
  • Meta information chips (category, equipment, difficulty)
  • Primary and secondary muscle groups
  • Multilingual step-by-step instructions

Close the modal to return to the filtered list without losing your scroll position or filter state.

Programmatic Control and Customization

You can interact with the browser's state and UI programmatically using the global functions and elements exposed in the script.

Triggering Searches via JavaScript

Simulate user input to filter results programmatically:

const searchEl = document.getElementById('search');
searchEl.value = 'bench press';
searchEl.dispatchEvent(new Event('input')); // Triggers debounced filter

Adding Custom Filter Chips

Extend the filter interface with new categories or values:

function addCustomChip(label, key) {
  const container = document.getElementById(`${key}-chips`);
  const chip = document.createElement('button');
  chip.className = 'chip';
  chip.textContent = label;
  chip.dataset.filter = key;
  chip.dataset.value = label;
  container.appendChild(chip);
}

// Add a "Yoga" category filter
addCustomChip('Yoga', 'category');

Manual Modal Control and State Reset

Access exercise details or reset the application state directly:

// Open specific exercise by ID
openModal('0010');

// Reset all filters and search (mirrors the "Clear all" button)
clearAllFilters();

Hooking into the Infinite Scroll Observer

Monitor pagination events for custom analytics or UI updates:

const observer = new IntersectionObserver(entries => {
  if (entries[0].isIntersecting) {
    console.log('Loading next page of exercises...');
  }
});
observer.observe(document.getElementById('load-sentinel'));

Supporting Files and Data Sources

While index.html operates independently, the repository includes complementary files for advanced use cases:

  • setup.html: Provides SQL scripts and API snippets for importing the dataset into a backend database if you later require server-side processing
  • data/exercises.json: The raw JSON source (1,324 records) used to generate the embedded EXERCISES array in the HTML file
  • data/exercises.schema.json: JSON Schema definition for the exercise objects, useful for validation or external tooling integration

Summary

  • index.html is a zero-dependency, single-file application containing 1,324 exercises with embedded data at lines 71-73
  • The state object (lines 1175-1200) and applyFilters() function drive reactive updates without frameworks
  • Browse via debounced search, multi-select chips, and infinite scroll (60 items per page) watched by an IntersectionObserver on #load-sentinel
  • View details through the modal system using openModal(id) (lines 155-165)
  • Extend functionality programmatically using exposed global functions like clearAllFilters() and custom chip injection

Frequently Asked Questions

Do I need a web server to run the exercise browser?

No. Because index.html embeds the entire EXERCISES dataset and all JavaScript logic internally, you can open the file directly in any modern browser using the file:// protocol. No Node.js, Python server, or database is required, as all processing happens client-side.

How many exercises are available in the dataset?

The browser ships with 1,324 fitness exercises covering strength training, cardio, stretching, and equipment-based movements. The full dataset is stored in the EXERCISES constant (lines 71-73) and loads instantly upon initialization without network requests.

Can I add custom filters or categories to the interface?

Yes. The filter system is dynamic—you can inject new chips using the addCustomChip() pattern shown above, provided the underlying data in EXERCISES contains matching values for the category, equipment, or target keys.

Is the exercise data fetched from an external API?

No. All data is embedded directly within index.html at lines 71-73. This design ensures the browser works offline and eliminates API latency, though it means any updates to the dataset require regenerating or editing the HTML file itself.

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 →