# How to Handle Media File Paths for Exercise Assets in the Exercises Dataset

> Learn how to handle media file paths for exercise assets in the exercises dataset. Construct full URLs by prepending a base URL to relative paths for images and GIFs.

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

---

**Each exercise record in `hasaneyldrm/exercises-dataset` stores relative paths in the `image` and `gif_url` fields, requiring consumers to prepend a base URL to construct fully-qualified URLs for thumbnails and GIF animations.**

The `hasaneyldrm/exercises-dataset` repository organizes fitness exercise data as a lightweight JSON catalog where every record references visual assets through relative file paths. To display the 180×180 thumbnails and animation GIFs correctly, you must resolve these relative paths against a base URL while respecting the JSON Schema constraints defined in [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json).

## Understanding the Media Path Structure

The dataset stores asset locations in two specific fields within [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json). Both fields contain **relative file paths** rather than absolute URLs, keeping the JSON payload portable across local development, CDN, and server-side environments.

### The image Field for Thumbnails

The `image` field contains a string pointing to a 180×180 JPEG or PNG thumbnail stored in the `images/` directory. According to the JSON Schema in [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) (lines 18–22), this field must match the pattern `^images/.+\.(jpg|jpeg|png)$`. A typical value follows the format `"images/0001-2gPfomN.jpg"`.

### The gif_url Field for Animations

The `gif_url` field references 180×180 animated GIFs located in the `videos/` folder. The schema enforces the pattern `^videos/.+\.gif$` for this field (lines 24–27 in [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json)), with values like `"videos/0001-2gPfomN.gif"` linking to the corresponding animation file.

### JSON Schema Validation

Before processing media paths, validate records against [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json). The schema strictly defines the regex patterns for both fields, ensuring every entry contains properly formatted relative paths before you attempt URL resolution.

## Resolving Relative Paths to Full URLs

Because the dataset uses relative paths, you must prepend a **base URL** (such as a CDN or local static server) to construct accessible URLs. This design allows the same dataset to function across staging and production environments without modifying the JSON files.

### JavaScript URL Construction

Use the built-in `URL` constructor to safely resolve relative paths against your base domain:

```javascript
const exercises = require('./data/exercises.json');
const baseUrl = 'https://mycdn.example.com/';

exercises.forEach(ex => {
  const imageUrl = new URL(ex.image, baseUrl).href;
  const gifUrl = new URL(ex.gif_url, baseUrl).href;
  console.log(`${ex.name}: thumbnail → ${imageUrl}, animation → ${gifUrl}`);
});

```

### Python Flask Integration

When serving assets directly from the repository, use `send_from_directory` to safely expose the `images/` and `videos/` directories:

```python
import json, os
from flask import Flask, send_from_directory, abort

app = Flask(__name__)
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
DATA = json.load(open(os.path.join(BASE_DIR, 'data', 'exercises.json')))

@app.route('/assets/<path:filename>')
def serve_asset(filename):
    if not (filename.startswith('images/') or filename.startswith('videos/')):
        abort(404)
    return send_from_directory(BASE_DIR, filename)

@app.route('/exercise/<ex_id>')
def exercise_detail(ex_id):
    ex = next((e for e in DATA if e['id'] == ex_id), None)
    if not ex:
        abort(404)
    return {
        "name": ex["name"],
        "image": f"/assets/{ex['image']}",
        "gif_url": f"/assets/{ex['gif_url']}",
        "attribution": ex["attribution"]
    }

```

### TypeScript Type-Safe Access

For type-safe path handling, define an interface matching the schema and resolve URLs with strict typing:

```typescript
import exercises from './data/exercises.json';

interface Exercise {
  id: string;
  name: string;
  image: string;
  gif_url: string;
  attribution: string;
}

const base = 'https://static.example.com/';
const fullUrl = (relPath: string) => new URL(relPath, base).toString();

exercises.forEach((ex: Exercise) => {
  console.log(`${ex.name}: ${fullUrl(ex.image)} | ${fullUrl(ex.gif_url)}`);
});

```

## Serving Assets and Compliance

When deploying the dataset in production, serve the `images/` and `videos/` directories as static files. Ensure your server configuration maintains the directory structure as organized in the repository, with 1,324 thumbnail files in `images/` and 1,324 animation files in `videos/`.

Additionally, every record contains an **attribution** field (e.g., `"© Gym visual — https://gymvisual.com/"`). You must display this attribution alongside any rendered media to comply with the licensing requirements specified in the repository's [`README.md`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/README.md) (lines 75–76).

## Summary

- The `hasaneyldrm/exercises-dataset` stores **relative paths** in `image` and `gif_url` fields, validated by patterns `^images/.+\.(jpg|jpeg|png)$` and `^videos/.+\.gif$` in [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json).
- Construct full URLs by prepending a base URL to the relative paths found in [`data/exercises.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.json) using standard URL resolution methods.
- Serve assets from the `images/` and `videos/` directories using static file hosting or frameworks like Flask with `send_from_directory`.
- Always display the `attribution` field alongside media to meet licensing obligations defined in the repository documentation.

## Frequently Asked Questions

### What is the format of media paths in exercises.json?

Each record contains relative paths: the `image` field points to `images/*.jpg` (or .jpeg/.png) and `gif_url` points to `videos/*.gif`. Both follow strict regex patterns defined in [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) to ensure consistency across all 1,324 exercise entries.

### How do I validate media file paths before processing?

Use the provided [`data/exercises.schema.json`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/data/exercises.schema.json) with any standard JSON Schema validator. The schema enforces the specific patterns for thumbnails and animations, rejecting records with malformed paths or absolute URLs that would break the relative path resolution logic.

### Can I use absolute URLs instead of relative paths in the dataset?

No. The dataset design intentionally uses relative paths to keep the JSON lightweight and environment-agnostic. If your application requires absolute URLs, transform the data during ingestion by prepending your base URL programmatically, but do not modify the source files in the repository.

### What are the licensing requirements for exercise media?

Each exercise includes an `attribution` field that must be displayed alongside the visual assets. According to the [`README.md`](https://github.com/hasaneyldrm/exercises-dataset/blob/main/README.md), this typically credits the original source (e.g., Gym Visual) and ensures compliance with the dataset's licensing terms when displaying the thumbnails and GIF animations.