Skip to content

Latest commit

 

History

History
79 lines (47 loc) · 5.92 KB

File metadata and controls

79 lines (47 loc) · 5.92 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working inside example/. The parent project at ../CLAUDE.md and its .claude/rules/*.md files load first; this file adds example-app-specific rules on top.

What this directory is

example/ is a standalone Flutter app (own pubspec.yaml, analysis_options.yaml, web/android/ios/desktop targets) that boots lib/main.dart into a navigable showcase gallery. It serves as the canonical visual reference embedded at fluttersdk.com/wind via per-page iframes.

Wind itself is consumed via pubspec.yaml: fluttersdk_wind: { path: ../ }. A code change in ../lib/ is visible here on the next hot-reload; the example app is the manual smoke test for the parent package.

The standalone JSON playground formerly hosted here (lib/play.dart, lib/playground.dart) has been migrated to the wind_playground_web package in the fluttersdk.com repository. The wind package only ships the demo gallery now.

Adding a new example page (three edits, manual)

There is NO auto-discovery. Pages are wired by hand in lib/routes.dart. To add one:

  1. Create the page file at lib/pages/<category>/<feature>_basic.dart. File name is snake_case; class name is <Feature>BasicExamplePage (PascalCase, ends in ExamplePage). Page shape (root WDiv with scrollPrimary: true, _buildHeader + _buildSection helpers, dark-mode pairs on every color token) is governed by ../.claude/rules/example-pages.md — read it before writing the page body.
  2. Add import 'pages/<category>/<feature>_basic.dart'; to the top of lib/routes.dart (alphabetically inside its category block).
  3. Add '/<category>/<feature>_basic': const <Feature>BasicExamplePage(), to the appRoutes map at the bottom of lib/routes.dart.

Verify by running flutter run -d chrome and navigating to /<category>/<feature>_basic. The route key MUST exactly match the file basename (sans .dart) — the docs website uses this URL to iframe the page.

The <x-preview> contract (docs ↔ example binding)

A doc file at ../doc/<section>/<page>.md embeds an example page via:

<x-preview path="<category>/<feature>_basic" size="md" source="example/lib/pages/<category>/<feature>_basic.dart"></x-preview>

The docs website resolves this by iframing the deployed web build at /<category>/<feature>_basic. Three things MUST hold for the iframe to render:

  • The path attribute matches a key in appRoutes exactly. Case-sensitive. Snake_case only — kebab-case caused 8 doc 404s in commit a2dee86 and was reverted globally.
  • The source attribute is the repo-root-relative path to the actual .dart file.
  • The route exists in lib/routes.dart AND the page widget compiles cleanly under flutter build web --target lib/main.dart.

If you rename, move, or delete a page, grep ../doc/ for the old path= / source= value FIRST. Update or remove every matching x-preview in the same change set. A stale x-preview is a broken doc.

Empty path="" is the documented special case for the root / route → installation_basic.dart.

The size="sm|md|lg" attribute is interpreted by the docs website's iframe wrapper CSS only; the example page itself renders to whatever viewport it gets. Do not branch on size inside Dart.

Iframe rendering invariants

The docs website iframes a deployed web build of lib/main.dart and navigates to /<route> per <x-preview>. Pages must work inside an iframe with unpredictable height:

  • Root widget of every page is WDiv(className: 'w-full h-full overflow-y-auto p-4', scrollPrimary: true, child: ...). Skipping scrollPrimary: true breaks iOS Safari tap-to-top inside the iframe.
  • No hard-coded width or height that exceeds typical iframe dimensions (1024 wide is safe; > 1280 risks horizontal scroll in narrow embed contexts).
  • No Navigator.of(context).pop(), SystemNavigator.pop(), dart:js window manipulation, or anything that escapes the iframe sandbox.
  • No real network calls (HTTP 400 in the test binding, hang in the production iframe). Use static fixtures.

Theme setup

lib/main.dart wraps the gallery in WindTheme(data: windTheme, builder: (ctx, controller) => MaterialApp(theme: controller.toThemeData(), routes: appRoutes.map(...), ...)). The floating theme-toggle FAB in AppLayout calls context.windTheme.toggleTheme().

Dependencies

  • fluttersdk_wind: { path: ../ } — local path to the parent. Do not bump to a pub.dev version; the example tests pre-release parent code.
  • google_fonts: ^6.1.0 — pulled by some pages for non-system font demos.

pubspec.lock is committed (this is an application, not a library). Do not delete it.

Off-limits

  • lib/routes.dart route keys — renaming a route silently breaks every doc page that links to it. Run a grep across ../doc/ BEFORE renaming.
  • web/index.html, web/manifest.json — standard Flutter web scaffolding. Editing them changes the iframe-host page chrome; coordinate with the docs site before touching.

Coverage

The 90% coverage gate enforced by ../tool/coverage.sh 90 measures the PARENT package only (../lib/src/). The example app contributes nothing to coverage. Tests for new parent features go to ../test/.

Related rules (loaded automatically by the parent project)

  • ../CLAUDE.md — Wind-wide stack, commands, post-change sync discipline (which lists example/lib/pages/ as one of the 5 surfaces every code change updates), coverage policy.
  • ../.claude/rules/example-pages.md (paths: example/lib/pages/**) — per-page file shape, helpers (_buildHeader, _buildSection), dark-mode pair rule, naming convention.
  • ../.claude/rules/docs.md (paths: doc/**) — the doc-side half of the <x-preview> contract.
  • ../.claude/rules/dynamic.md (paths: {lib/src/dynamic,test/dynamic}/**) — WDynamic schema and security model.