mokr 0.1.0 copy "mokr: ^0.1.0" to clipboard
mokr: ^0.1.0 copied to clipboard

Realistic mock data and images for Flutter UI development. Stable users, posts, feeds, and images with deterministic seeding. For development and prototyping only.

mokr #

Realistic mock data and images for Flutter UI development.

Drop one line anywhere in your widget tree. Get a realistic user, post, or image — stable across hot reloads, restarts, and team members' machines. No backend. No setup beyond await Mokr.init().


⚠️ Development and prototyping only. mokr asserts and refuses to run in release builds. Do not ship it to end users or include it in production app bundles.


The Problem #

Building UI in Flutter means staring at placeholder boxes and Lorem Ipsum until your backend is ready. Once you wire up real data, everything shifts — layouts break, names are too long or too short, images never match the category you designed for.

mokr gives you realistic, deterministic mock data that behaves exactly like real data, immediately. A user always has the same name. A post always has the same caption. An image always comes from the right category. Your UI looks finished before your backend exists.


Quick Start #

# pubspec.yaml
dependencies:
  mokr: ^0.1.0
// main.dart
void main() async {
  await Mokr.init();
  runApp(MyApp());
}
// Anywhere in your widget tree — no await, no FutureBuilder
MokrAvatar(seed: 'user_42', size: 48)
MokrImage(seed: 'post_1', category: MokrCategory.nature)
MokrPostCard(seed: 'feed_0')

// Or use the data directly in your own widgets
final user = Mokr.user('user_42');
Text(user.name)
Text('@${user.username}')

// URL strings for NetworkImage, CachedNetworkImage, etc.
Image.network(Mokr.avatarUrl('user_42', size: 80))
Image.network(Mokr.imageUrl('post_1', category: MokrCategory.travel))

The Four Modes #

mokr has four ways to generate data. They form a spectrum from throwaway to permanent.

// 1 — Fresh random
//     Different every call. Nothing stored. Use for quick browsing.
Mokr.randomUser()

// 2 — Slot (stable random)
//     Random once, then frozen. Stable across hot reloads and restarts.
//     Clear it when you want a new result.
Mokr.randomUser(slot: 'card_1')

// 3 — Pinned slot
//     Same as slot, but protected from Mokr.clearAll().
//     Only clears when you explicitly call Mokr.clearPin('hero').
Mokr.randomUser(slot: 'hero', pin: true)

// 4 — Deterministic
//     Seed baked into code. Same result everywhere, forever.
//     No disk, no init() dependency, no runtime state.
Mokr.user('user_42')

The same four modes work for posts and all widgets:

Mokr.randomPost()
Mokr.randomPost(slot: 'feed_hero', pin: true)
Mokr.post('post_seed')

MokrAvatar()                             // fresh random
MokrAvatar(slot: 'card_1')               // slot
MokrAvatar(slot: 'hero', pin: true)      // pinned slot
MokrAvatar(seed: 'user_42')              // deterministic

The Graduation Flow #

Start with randomUser() and browse. When you see a result you like, make it permanent.

Step 1 — write this, iterate fast:
  Mokr.randomUser()

Step 2 — see a user you like. Console shows:
  [mokr] 🎲 fresh → seed: 'mokr_a7Be'

Step 3 — copy the seed, freeze it forever:
  Mokr.user('mokr_a7Be')

Or skip step 3 and use a slot — the result stays stable without baking a seed into code:

Mokr.randomUser(slot: 'profile_card')  // frozen until you clear it

Widgets #

All mokr widgets are standard Flutter widgets. They work anywhere — inside Card, ListView.builder, Stack, Expanded, or as child: of any widget.

MokrAvatar #

// Circle (default), rounded, or square
MokrAvatar(seed: 'user_42', size: 48)
MokrAvatar(seed: 'user_42', size: 48, shape: MokrShape.rounded)
MokrAvatar(seed: 'user_42', size: 48, shape: MokrShape.square)

// With border
MokrAvatar(seed: 'user_42', size: 48, border: Border.all(width: 2))

// Custom loading / error states
MokrAvatar(
  seed: 'user_42',
  size: 48,
  loadingBuilder: (context) => MyShimmer(),
  errorBuilder: (context) => MyFallback(),
)

// Slot and fresh random work too
MokrAvatar(slot: 'sidebar_user', size: 40)
MokrAvatar(size: 40)  // fresh random

MokrImage #

// Fixed size
MokrImage(
  seed: 'post_1',
  category: MokrCategory.nature,
  width: 400,
  height: 300,
)

// Fill parent (inside Expanded, AspectRatio, SizedBox.expand, etc.)
MokrImage(
  seed: 'banner',
  category: MokrCategory.architecture,
  width: double.infinity,
  height: 200,
)

// With border radius
MokrImage(
  seed: 'card_image',
  category: MokrCategory.food,
  width: 300,
  height: 200,
  borderRadius: BorderRadius.circular(12),
)

MokrPostCard #

// Full post card — avatar, image, caption, like/comment/share counts
MokrPostCard(seed: 'feed_0')
MokrPostCard(slot: 'featured')
MokrPostCard(slot: 'featured', pin: true)
MokrPostCard()  // fresh random

MokrUserTile #

// User list tile — avatar, name, username, optional trailing widget
MokrUserTile(seed: 'user_42')
MokrUserTile(
  seed: 'user_42',
  trailing: FilledButton(onPressed: () {}, child: const Text('Follow')),
)
MokrUserTile(slot: 'suggestion_1')

Data API #

Use the data API when you want to feed mock data into your own widgets.

Users #

final user = Mokr.user('user_42');

user.name           // 'Jordan Rivera'
user.username       // 'jordanrivera'
user.bio            // 'Outdoor photographer and trail runner.'
user.seed           // 'user_42'
user.followerCount  // 4_821
user.followingCount // 312
user.postCount      // 87
user.initials       // 'JR'

Posts #

final post = Mokr.post('post_1');

post.caption        // 'Golden hour at the summit. Worth every step. 🌄'
post.likeCount      // 1_203
post.commentCount   // 48
post.shareCount     // 19
post.formattedLikes // '1.2K'
post.hasImage       // true
post.imageUrl       // category-aware URL string
post.author         // MockUser
post.createdAt      // DateTime (recent, realistic)
post.relativeTime   // '3h ago'

Feeds #

// Same seed + same page → same posts, always
final page0 = Mokr.feedPage('home_feed', page: 0, pageSize: 20);
final page1 = Mokr.feedPage('home_feed', page: 1, pageSize: 20);

// Infinite scroll example:
ListView.builder(
  itemCount: posts.length,
  itemBuilder: (context, i) => PostCard(post: posts[i]),
)

String extensions #

'user_42'.asMockUser   // same as Mokr.user('user_42')
'post_0'.asMockPost    // same as Mokr.post('post_0')
'user_42'.asAvatarUrl  // same as Mokr.avatarUrl('user_42')

Image Categories #

15 categories for every part of your UI:

Category Use for
MokrCategory.face Avatars, profile photos
MokrCategory.nature Landscape posts, banners
MokrCategory.travel Destination cards, explore grids
MokrCategory.food Restaurant apps, recipe cards
MokrCategory.fashion Product listings, lookbooks
MokrCategory.fitness Workout apps, progress cards
MokrCategory.art Creative platforms, galleries
MokrCategory.technology Tech blogs, device mockups
MokrCategory.office B2B dashboards, productivity apps
MokrCategory.abstract_ Backgrounds, decorative images
MokrCategory.product E-commerce, lifestyle photography
MokrCategory.interior Real estate, home decor
MokrCategory.architecture Property apps, city guides
MokrCategory.automotive Car listings, transport apps
MokrCategory.pets Pet apps, community feeds

Note: abstract_ has a trailing underscore because abstract is a Dart keyword.


Slot Management #

// Clear a single unpinned slot — re-randomises on next call
await Mokr.clearSlot('card_1');

// Clear a pinned slot — requires explicit intent
await Mokr.clearPin('hero');

// Clear all unpinned slots — pinned slots survive
await Mokr.clearAll();

A common pattern for pull-to-refresh:

Future<void> onRefresh() async {
  await Mokr.clearAll();  // wipe unpinned slots — fresh randoms next build
  setState(() => _session++);  // new seed → feedPage returns new posts
}

Unsplash Images (opt-in) #

By default, mokr uses Picsum — no API key required.

To get real, category-filtered images from Unsplash:

// At startup:
await Mokr.init(unsplashKey: 'your_access_key');

// Or switch at runtime (e.g. from a dev settings screen):
final count = await Mokr.useUnsplash('your_access_key');
// count == 0  → key invalid or network unavailable
// count 1–15  → categories loaded successfully (rest fall back to Picsum)

// Switch back to Picsum:
Mokr.usePicsum();

Use the Access Key from your Unsplash app dashboard — not the Secret Key or Application ID.

mokr pre-warms a URL cache at startup (2 requests × 15 categories = 30 total). After warm-up, all imageUrl, avatarUrl, and bannerUrl calls are instant and synchronous. Categories that fail to warm fall back to Picsum transparently.


Custom Image Provider #

Plug in any image source by implementing MokrImageProvider:

class MyImageProvider extends MokrImageProvider {
  @override
  String avatarUrl(String seed, MokrCategory category, {int size = 80}) {
    return 'https://my-cdn.com/avatars/$seed?size=$size';
  }

  @override
  String imageUrl(String seed, MokrCategory category,
      {int width = 400, int height = 300}) {
    return 'https://my-cdn.com/images/${category.keyword}/$seed'
        '?w=$width&h=$height';
  }

  @override
  String bannerUrl(String seed, MokrCategory category,
      {int width = 800, int height = 300}) {
    return 'https://my-cdn.com/banners/$seed?w=$width&h=$height';
  }
}

// Activate:
await Mokr.init(imageProvider: MyImageProvider());

License #

MIT — see LICENSE.

Images are sourced from Picsum Photos (default) and Unsplash (opt-in). Refer to their respective terms when using Unsplash images. mokr is a development tool — do not use it to serve images to end users.

1
likes
160
points
185
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Realistic mock data and images for Flutter UI development. Stable users, posts, feeds, and images with deterministic seeding. For development and prototyping only.

Repository (GitHub)
View/report issues
Contributing

Topics

#mock #ui #flutter #fake-data #testing

License

MIT (license)

Dependencies

flutter, http, shared_preferences

More

Packages that depend on mokr