# How to Build a Workout Generator Using the Exercises Dataset

> Create a workout generator using the exercises dataset. Learn to filter exercises, select random workouts, and assemble them with multilingual instructions and media assets.

- Repository: [Hasan Emir Yıldırım/exercises-dataset](https://github.com/hasaneyldrm/exercises-dataset)
- Tags: tutorial
- Published: 2026-07-30

---

**Build a workout generator by loading the [`exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/exercises.json) file, filtering exercises by category, equipment, and target muscles, randomly selecting a subset, and assembling them into a structured workout with multilingual instructions and media assets.**

The `hasaneyldrm/exercises-dataset` repository provides a ready-to-use collection of **1,324 exercises** stored as a plain JSON array, making it accessible to any programming language that can parse JSON. Each exercise record contains comprehensive metadata including equipment requirements, targeted muscle groups, multilingual instructions, and URLs to thumbnail images and animated GIFs. This structure allows you to build a workout generator using the dataset by implementing a simple pipeline: ingestion, filtering, selection, and assembly.


## Understanding the Dataset Structure

The core data resides in [[`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json)](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json), which contains an array of exercise objects. Each object follows the schema defined in [[`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json)](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) (Draft 2020-12), ensuring predictable structure for validation.

Key fields available for filtering and display include:

- **`category`** – Body region classification (e.g., "chest", "upper legs", "back")
- **`equipment`** – Required gear (e.g., "dumbbell", "barbell", "body weight")
- **`target`** – Primary muscle group targeted (e.g., "biceps", "glutes", "abs")
- **`instructions`** – Multilingual object with keys like `"en"`, `"es"`, `"fr"`
- **`image`** – URL to the exercise thumbnail
- **`gif_url`** – URL to the animated demonstration


## Step-by-Step Implementation Architecture

When you build a workout generator using the dataset, implement these four logical layers:

### Data Ingestion and Validation

Load the JSON file into memory at application startup. For production systems, validate against [[`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json)](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) to ensure schema compliance before processing.

### Filtering by User Criteria

Construct predicate functions that accept parameters such as `category`, `equipment`, and `target`. Apply these filters sequentially to narrow the pool of available exercises based on user constraints or equipment availability.

### Selection and Diversity Logic

From the filtered subset, implement selection strategies. Use **random sampling** for variety, or apply **weighted probability** and **difficulty-based ordering** for progressive overload. Enforce diversity rules—such as limiting exercises per muscle group—to ensure balanced workouts.

### Workout Assembly and Export

Map the selected exercise objects into a client-ready format including `id`, `name`, `category`, `equipment`, `target`, localized `instructions`, and media URLs. Serialize as JSON for API responses or direct browser consumption.


## Code Implementation Examples

### Python Workout Generator

This implementation loads the dataset once, provides flexible filtering, and returns workout objects ready for API serialization:

```python
import json
import random
import pathlib

DATA_PATH = pathlib.Path(__file__).parent / "data" / "exercises.json"

with DATA_PATH.open(encoding="utf-8") as f:
    EXERCISES = json.load(f)

def filter_exercises(category=None, equipment=None, target=None):
    result = EXERCISES
    if category:
        result = [e for e in result if e["category"] == category]
    if equipment:
        result = [e for e in result if e["equipment"] == equipment]
    if target:
        result = [e for e in result if e["target"] == target]
    return result

def generate_workout(count=6, **filters):
    pool = filter_exercises(**filters)
    chosen = random.sample(pool, min(count, len(pool)))
    return [
        {
            "id": ex["id"],
            "name": ex["name"],
            "category": ex["category"],
            "equipment": ex["equipment"],
            "target": ex["target"],
            "instruction": ex["instructions"]["en"],
            "image": ex["image"],
            "gif": ex["gif_url"],
        }
        for ex in chosen
    ]

# Generate 6 body-weight chest exercises

workout = generate_workout(count=6, equipment="body weight", category="chest")
print(json.dumps(workout, indent=2))

```

### Node.js REST API Endpoint

Use this pattern for an Express-based backend that serves filtered workouts via HTTP:

```javascript
const path = require("path");
const fs = require("fs");

const EXERCISES = JSON.parse(
  fs.readFileSync(path.join(__dirname, "data", "exercises.json"), "utf-8")
);

function filterExercises({ category, equipment, target } = {}) {
  return EXERCISES.filter((e) => {
    return (
      (!category || e.category === category) &&
      (!equipment || e.equipment === equipment) &&
      (!target || e.target === target)
    );
  });
}

function generateWorkout({ count = 6, language = "en", ...filters } = {}) {
  const pool = filterExercises(filters);
  const shuffled = pool.sort(() => 0.5 - Math.random());
  const chosen = shuffled.slice(0, Math.min(count, pool.length));
  return chosen.map((ex) => ({
    id: ex.id,
    name: ex.name,
    category: ex.category,
    equipment: ex.equipment,
    target: ex.target,
    instruction: ex.instructions[language],
    image: ex.image,
    gif: ex.gif_url,
  }));
}

// Example Express route implementation:
// app.get("/api/workout", (req, res) => {
//   const { count, lang, category, equipment, target } = req.query;
//   const workout = generateWorkout({
//     count: Number(count) || 6,
//     language: lang || "en",
//     category,
//     equipment,
//     target,
//   });
//   res.json(workout);
// });

```

### Browser-Based Generator

You can also build a **pure-client generator** without a backend. The repository includes [[`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html)](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html) demonstrating live search and filtering. Load the JSON via import and run the selection logic directly:

```html
<script type="module">
import exercises from "./data/exercises.json";

function randomWorkout({ count = 6, language = "en", filters = {} } = {}) {
  const pool = Object.values(exercises).filter((ex) => {
    return Object.entries(filters).every(
      ([k, v]) => v === undefined || ex[k] === v
    );
  });
  const chosen = [];
  while (chosen.length < count && pool.length) {
    const idx = Math.floor(Math.random() * pool.length);
    chosen.push(pool.splice(idx, 1)[0]);
  }
  return chosen.map((ex) => ({
    name: ex.name,
    instruction: ex.instructions[language],
    gif: ex.gif_url,
    img: ex.image,
  }));
}

// Generate 4 barbell upper-leg exercises
const workout = randomWorkout({
  count: 4,
  language: "en",
  filters: { equipment: "barbell", category: "upper legs" },
});
console.table(workout);
</script>

```

For additional setup guidance, reference [[`setup.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/setup.html)](https://github.com/hasaneyldrm/exercises-dataset/blob/main/setup.html) in the repository, which provides database import instructions and LLM-generated backend templates.


## Summary

- The **exercises dataset** contains 1,324 structured records with multilingual instructions and media assets located in [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json).
- **Validation** against [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) ensures data integrity before processing.
- Build filtering logic around **category**, **equipment**, and **target** fields to match user constraints.
- Implement **random sampling** or weighted selection from filtered pools to generate varied workouts.
- Assemble final output with `instructions`, `image`, and `gif_url` for complete UI rendering.
- Deploy as Python scripts, Node.js APIs, or **browser-only solutions** using the provided [`index.html`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/index.html) reference.


## Frequently Asked Questions

### What data structure does the exercises dataset use?

The dataset uses a flat JSON array where each element is an exercise object containing string fields for `name`, `category`, `equipment`, and `target`, plus nested objects for multilingual `instructions` and URLs for media assets. This structure is formally defined in [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) using JSON Schema Draft 2020-12.

### How do I validate the exercises.json file before processing?

Validate the file against the provided schema using any JSON Schema validator library. In Python, use `jsonschema.validate()` against [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json). In JavaScript, use `ajv` (Another JSON Schema Validator) to check compliance before loading the data into your application memory.

### Can I filter exercises by multiple criteria simultaneously?

Yes. Apply filters sequentially or combine them with logical AND operations. For example, filter first by `equipment: "dumbbell"`, then by `category: "chest"` to return only dumbbell chest exercises. The filtered subset can then be sampled to create equipment-specific workout splits.

### How do I access the exercise animations and images?

Each exercise record includes `image` (thumbnail URL) and `gif_url` (animation URL) fields. These assets are publicly accessible and can be rendered directly in web UIs or mobile applications. Check [`NOTICE.md`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/NOTICE.md) in the repository for attribution requirements and usage terms regarding the media files.