workout_flutter_guide 0.1.1 copy "workout_flutter_guide: ^0.1.1" to clipboard
workout_flutter_guide: ^0.1.1 copied to clipboard

302 exercises with 906 offline SVG frames, a typed catalog with search and filters, and ready-to-use Flutter widgets. Community port of @bryllim/workout-guide.

workout_flutter_guide #

302 exercises, 906 illustration frames, and a typed catalog to query them — all offline, all in your app bundle.

A Flutter port of @bryllim/workout-guide by Bryl Lim. Unaffiliated community port.

final pushUp = WorkoutGuide.getExercise('push-up')!;
final chest = WorkoutGuide.search('chest', equipment: Equipment.bodyweight);

ExerciseAnimation(exercise: pushUp, size: 200, color: Colors.black87);

⚖️ Licensing — read this before you ship #

This package is dual-licensed, and the artwork is the strict half.

What License
The Dart code MIT
The 906 SVG frames and their metadata CC BY-SA 4.0

CC BY-SA 4.0 means your app must display the attribution. Put it on an About or Licenses screen — that is the whole obligation, and it takes one widget:

const WorkoutGuideAttribution();

or, if your app already has a licenses page:

void main() {
  WorkoutGuide.registerLicenses(); // shows up in showLicensePage()
  runApp(const MyApp());
}

The plain-text version, ready to paste:

Exercise illustrations by Bryl Lim (https://bryllim.com), based on artwork by Everkinetic (https://github.com/everkinetic/data), licensed under CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0/).

ShareAlike also means: if you modify the SVG files, your modified files stay CC BY-SA 4.0 and you must say what you changed. Tinting them at render time (the color argument below) is not a modification — it does not touch the files. See LICENSES.md and ATTRIBUTION.md.


Install #

dependencies:
  workout_flutter_guide: ^0.1.0

No setup, no initialization, no asset declarations of your own. The catalog is compiled in as Dart constants, so it is there synchronously on the first frame.

The catalog #

import 'package:workout_flutter_guide/workout_flutter_guide.dart';

WorkoutGuide.exercises;                       // all 302, unmodifiable
WorkoutGuide.getExercise('push-up');          // by slug
WorkoutGuide.getExercise('exercise-push-up'); // or by id -- null if unknown
WorkoutGuide.stretches;                       // the 14 stretches

Every token of the query must appear somewhere in the exercise's name, equipment, primary muscle or secondary muscles. Matching ignores case, punctuation and accents.

WorkoutGuide.search('incline dumbbell');
WorkoutGuide.search('press', equipment: Equipment.dumbbell);
WorkoutGuide.search('', primaryMuscle: [Muscle.lats, Muscle.upperBack]);
WorkoutGuide.search('', isStretch: true);

// String labels work too, so upstream JavaScript examples port as-is:
WorkoutGuide.search('press', equipment: 'Dumbbell', primaryMuscle: 'Shoulders');

Values inside one filter are ORed; different filters are ANDed. Results keep catalog order. Shorthands: byEquipment, byPrimaryMuscle, byExerciseType.

An exercise #

final e = WorkoutGuide.getExercise('bench-press')!;

e.name;              // 'Bench Press'
e.equipment;         // Equipment.barbell      -> .label == 'Barbell'
e.primaryMuscle;     // Muscle.chest
e.secondaryMuscles;  // [Muscle.triceps, Muscle.shoulders]
e.exerciseType;      // ExerciseType.weightReps -> .label == 'weight_reps'
e.isStretch;         // false
e.frames;            // 3 frames: start, mid, end
e.assetPath(1);      // packages/workout_flutter_guide/assets/.../frame-1.svg

The enums keep the upstream strings in .label, and Equipment.fromLabel, Muscle.fromLabel and ExerciseType.fromLabel read them back.

The widgets #

// One pose.
ExerciseFrameImage(exercise: e, frame: 1, size: 160, color: Colors.black87);

// The movement, cycling 1 -> 2 -> 3.
ExerciseAnimation(
  exercise: e,
  frameDuration: const Duration(milliseconds: 400),
  size: 200,
  color: Colors.black87,
);

// The credit block you owe the artists.
WorkoutGuideAttribution(onLinkTap: (url) => launchUrlString(url));

About color: the artwork is drawn in white on a transparent background, because upstream targets dark surfaces. On a light background it is invisible unless you pass a colour — Theme.of(context).colorScheme.onSurface is usually the right one. The widgets will not pick one for you, because a widget that silently recolours artwork is a surprise you would rather not debug.

ExerciseAnimation mounts all three frames up front (no flicker on the first loop), cancels its timer when it leaves the tree, and holds a still frame when the platform asks for reduced motion.

Serving the artwork from a CDN #

The bundled assets are the offline default, but the upstream jsDelivr URLs are one call away — a pure string builder, no network access from this package:

WorkoutGuide.assetCdnUrl('push-up', 2);
// https://cdn.jsdelivr.net/npm/@bryllim/workout-guide@1.0.0/assets/push-up/frame-2.svg

Be aware of the trade-off: the SVGs are declared in this package's pubspec.yaml, so they ship with your app whether or not you use the CDN. Flutter gives a consumer no way to opt out of a dependency's assets. Use the CDN when you want the artwork cached and shared across clients, not to shrink your bundle.

Attribution metadata is queryable #

The per-frame provenance survives the port, because CC BY-SA requires it to:

final source = e.frames.first.attribution.source;
source?.name;    // 'Everkinetic'
source?.url;     // the exact upstream file
source?.changes; // what was changed, in words

76 of the 906 frames are vector-traced adaptations of Everkinetic drawings and carry a source; the other 830 were drawn from scratch by Bryl Lim.

Parity with upstream #

The upstream test suite is ported 1:1, and the generated catalog is compared entry-by-entry against manifest.json in both directions. Search normalization matches the JavaScript exactly — including its rough edges, verified against 524 golden cases generated by running the original code.

Upstream Here
exercises WorkoutGuide.exercises
getExercise(idOrSlug) WorkoutGuide.getExercise(idOrSlug)
searchExercises(query, filters) WorkoutGuide.search(query, ...)
normalizeSearchText(value) normalizeSearchText(value)
getAssetUrl(id, frame, opts) WorkoutGuide.assetCdnUrl(id, frame, ...)
WorkoutGuide.assetPath(id, frame) (local asset)

Example #

example/ is a runnable gallery: searchable grid, equipment and muscle filters, a detail page with the animation, and an About screen showing the attribution done properly.

cd example && flutter run

Credits #

Artwork by Everkinetic and Bryl Lim, CC BY-SA 4.0. Catalog from @bryllim/workout-guide v1.0.0. Flutter port by Jonathan KABLAN.

1
likes
160
points
--
downloads

Documentation

API reference

Publisher

verified publisheragent-neo.cloud

Weekly Downloads

302 exercises with 906 offline SVG frames, a typed catalog with search and filters, and ready-to-use Flutter widgets. Community port of @bryllim/workout-guide.

Repository (GitHub)
View/report issues

Topics

#fitness #exercise #workout #svg #illustrations

License

MIT (license)

Dependencies

flutter, flutter_svg

More

Packages that depend on workout_flutter_guide