How to Use the Exercises Dataset with TypeScript: A Complete Integration Guide

The exercises dataset from hasaneyldrm/exercises-dataset provides 1,324 fitness records as a static JSON file you can consume in TypeScript by importing data/exercises.json directly and generating compile-time types from data/exercises.schema.json.

The hasaneyldrm/exercises-dataset repository offers a production-ready collection of fitness exercise metadata designed for immediate consumption in modern TypeScript applications. Because the dataset is entirely static—consisting of a single JSON file and associated media assets—you can integrate it into Node.js servers, Deno runtimes, or front-end bundles without managing external APIs or database connections.

Understanding the Dataset Architecture

The Data Layer

The core dataset resides in data/exercises.json [source] and contains an array of 1,324 exercise objects. Each record includes multilingual step-by-step instructions, equipment requirements, target muscle groups, and relative paths to associated media files.

The Schema Layer

The repository includes data/exercises.schema.json [source], a JSON Schema (Draft 2020-12) that defines type constraints and validation rules for every field. This schema enables automatic TypeScript interface generation, ensuring compile-time safety when accessing nested properties like instructions.en or secondary_muscles.

Media Assets

Static assets are organized in images/ (thumbnails) and videos/ (animation GIFs), referenced by relative paths in each record's image and gif_url properties.

Generating TypeScript Types from JSON Schema

To achieve full type safety and IDE autocompletion, generate interfaces from the provided schema using json-schema-to-typescript.

First, install the development dependency:

npm i -D json-schema-to-typescript

Generate the type definitions:

npx json2ts -i data/exercises.schema.json -o src/types/exercise.d.ts

The generated src/types/exercise.d.ts file contains a comprehensive interface matching the JSON structure:

export interface Exercise {
  id: string;
  name: string;
  category: string;
  body_part: string;
  equipment: string;
  instructions: {
    en: string;
    es: string;
    it: string;
    tr: string;
    ru: string;
    zh: string;
    hi: string;
    pl: string;
    ko: string;
    fr: string;
  };
  instruction_steps: Record<string, string[]>;
  muscle_group: string;
  secondary_muscles: string[];
  target: string;
  media_id: string;
  image: string;
  gif_url: string;
  attribution: string;
}

Loading the Dataset in TypeScript

Node.js with ES Module Import Assertions

For Node.js 17+ using ES modules, import the JSON file directly with type assertions. This approach bundles the data at compile time, eliminating runtime fetch overhead.

// src/data.ts
import type { Exercise } from './types/exercise';
import exercisesRaw from '../data/exercises.json' assert { type: 'json' };

export const exercises: Exercise[] = exercisesRaw as Exercise[];

Browser and Fetch API

When serving the file from a static CDN or local development server, use the Fetch API with explicit type casting to populate your application state.

export async function loadExercises(): Promise<Exercise[]> {
  const res = await fetch('/data/exercises.json');
  if (!res.ok) throw new Error('Failed to fetch exercises');
  const data = (await res.json()) as Exercise[];
  return data;
}

// Usage in a front-end component
loadExercises().then(exs => console.log(`Loaded ${exs.length} exercises`));

Querying and Filtering Exercises

Once loaded into a typed array, you can leverage standard JavaScript array methods to search and filter the dataset efficiently.

Searching by Name

Implement case-insensitive search to find specific movements:

import { exercises } from './data';

export function searchByName(query: string): Exercise[] {
  const lowered = query.toLowerCase();
  return exercises.filter(e => e.name.toLowerCase().includes(lowered));
}

// Usage
const benchPresses = searchByName('bench press');
console.log(`Found ${benchPresses.length} bench-press variations`);

Filtering by Equipment

Filter the dataset by equipment type to build targeted workout generators:

export function filterByEquipment(equipment: string): Exercise[] {
  const lowered = equipment.toLowerCase();
  return exercises.filter(e => e.equipment.toLowerCase() === lowered);
}

// Example: Get all dumbbell exercises
const dumbbellExercises = filterByEquipment('dumbbell');
console.log(dumbbellExercises.slice(0, 3)); // first three results

Bulk Inserting into SQLite

For persistent storage or complex querying, bulk-insert records into SQLite using prepared statements and transactions:

import Database from 'better-sqlite3';
import { exercises } from './data';

const db = new Database('exercises.db');

db.exec(`
  CREATE TABLE IF NOT EXISTS exercises (
    id TEXT PRIMARY KEY,
    name TEXT,
    category TEXT,
    body_part TEXT,
    equipment TEXT,
    instructions TEXT,
    muscle_group TEXT,
    target TEXT,
    image TEXT,
    gif_url TEXT,
    attribution TEXT
  );
`);

const insert = db.prepare(`
  INSERT OR REPLACE INTO exercises
  (id, name, category, body_part, equipment, instructions, muscle_group, target, image, gif_url, attribution)
  VALUES (@id, @name, @category, @body_part, @equipment, @instructions, @muscle_group, @target, @image, @gif_url, @attribution);
`);

const insertMany = db.transaction((list: Exercise[]) => {
  for (const e of list) {
    insert.run({
      id: e.id,
      name: e.name,
      category: e.category,
      body_part: e.body_part,
      equipment: e.equipment,
      instructions: JSON.stringify(e.instructions),
      muscle_group: e.muscle_group,
      target: e.target,
      image: e.image,
      gif_url: e.gif_url,
      attribution: e.attribution,
    });
  }
});

insertMany(exercises);
console.log('All exercises inserted into SQLite');

Summary

  • The exercises dataset from hasaneyldrm/exercises-dataset contains 1,324 records in data/exercises.json with comprehensive metadata and multilingual instructions.
  • Generate TypeScript interfaces automatically from data/exercises.schema.json using json-schema-to-typescript for compile-time safety and IDE autocompletion.
  • Import the data directly using ES module JSON assertions (Node.js 17+) or the Fetch API for browser environments.
  • Query records efficiently using standard array methods like filter() and find() on the typed Exercise[] array.
  • Persist data to SQLite, PostgreSQL, or other databases using bulk-insert transactions for production performance.

Frequently Asked Questions

Can I use the exercises dataset with TypeScript without generating types?

Yes, you can import the JSON file directly and cast it using as Exercise[] or any, but generating types from data/exercises.schema.json provides compile-time checking and IDE autocomplete that prevents runtime errors when accessing nested properties like instruction_steps.en.

How do I handle the image and GIF assets in a TypeScript application?

Each exercise record stores relative paths in the image and gif_url fields pointing to the images/ and videos/ directories. Resolve these by either copying the media folders to your public static directory (for Next.js, Vite, or similar) or prepending a CDN base URL to the path strings before rendering.

Is the exercises dataset compatible with Deno?

Yes. Because the dataset is pure JSON, Deno can import it directly using import exercises from './data/exercises.json' with { type: 'json' } (note that Deno uses the with keyword for import attributes rather than Node.js's assert keyword). The same TypeScript interfaces generated from the schema work identically in Deno.

What is the performance impact of loading all 1,324 exercises into memory?

The uncompressed JSON file is approximately a few hundred kilobytes, making it suitable for in-memory operations in most TypeScript environments. For high-frequency serverless functions or large-scale applications, consider loading the data once at startup, or bulk-inserting into a database as demonstrated in the SQLite example above to leverage SQL indexing for complex queries.

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 →