<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: charlieww</title>
    <description>The latest articles on DEV Community by charlieww (@charlieww).</description>
    <link>https://dev.to/charlieww</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3771525%2F31060fcd-ff49-44af-b45c-c550ef31b76d.jpg</url>
      <title>DEV Community: charlieww</title>
      <link>https://dev.to/charlieww</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/charlieww"/>
    <language>en</language>
    <item>
      <title>We Built a Full-Stack Flutter Short Video + Live Streaming App in 90 Days — Here's What We Shipped</title>
      <dc:creator>charlieww</dc:creator>
      <pubDate>Tue, 15 Sep 2026 15:12:13 +0000</pubDate>
      <link>https://dev.to/charlieww/we-built-a-full-stack-flutter-short-video-live-streaming-app-in-90-days-heres-what-we-shipped-47nb</link>
      <guid>https://dev.to/charlieww/we-built-a-full-stack-flutter-short-video-live-streaming-app-in-90-days-heres-what-we-shipped-47nb</guid>
      <description>&lt;p&gt;90 days. One team. A complete TikTok-style app — from bare repo to App Store submission.&lt;/p&gt;

&lt;p&gt;Here's the full breakdown of what we shipped with &lt;strong&gt;DTok&lt;/strong&gt;, our open-source Flutter short video + live streaming platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What Is DTok?
&lt;/h2&gt;

&lt;p&gt;DTok is a production-grade short video and live streaming app built entirely in Flutter. Think TikTok + Twitch — but open source, self-hostable, and developer-friendly.&lt;/p&gt;

&lt;p&gt;We wanted to prove that a small team could ship a full-featured social video app in a single quarter. This post documents what we built, the architectural decisions that made it possible, and everything we learned along the way.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Core Features Shipped
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Short Video Feed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Infinite vertical swipe feed (like TikTok)&lt;/li&gt;
&lt;li&gt;Auto-play with smart prefetching&lt;/li&gt;
&lt;li&gt;Hardware-accelerated video player built on &lt;code&gt;video_player&lt;/code&gt; + custom controller&lt;/li&gt;
&lt;li&gt;Like, comment, share, and save actions — all optimistically updated&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Live Streaming
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Real-time RTMP broadcast from phone camera&lt;/li&gt;
&lt;li&gt;Low-latency playback via HLS adaptive bitrate&lt;/li&gt;
&lt;li&gt;Live chat with WebSocket-based message sync&lt;/li&gt;
&lt;li&gt;Virtual gift sending system with coin economy&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creator Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;In-app video recording with filters and speed control&lt;/li&gt;
&lt;li&gt;Multi-clip editing timeline&lt;/li&gt;
&lt;li&gt;Caption + music overlay&lt;/li&gt;
&lt;li&gt;One-tap publish flow with thumbnail auto-generation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Social Graph
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Follow / following system with real-time feed updates&lt;/li&gt;
&lt;li&gt;User profiles with video, liked, and saved tabs&lt;/li&gt;
&lt;li&gt;Push notifications (FCM) for new followers and interactions&lt;/li&gt;
&lt;li&gt;Algorithmic "For You" page using engagement signals&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Monetization Layer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Coin purchase via in-app purchase (IAP)&lt;/li&gt;
&lt;li&gt;Gift sending to live streamers&lt;/li&gt;
&lt;li&gt;Streamer payout dashboard&lt;/li&gt;
&lt;li&gt;Stripe Connect integration for creator withdrawals&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠 Tech Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mobile&lt;/td&gt;
&lt;td&gt;Flutter 3.x (Dart)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State management&lt;/td&gt;
&lt;td&gt;Riverpod + AsyncNotifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video player&lt;/td&gt;
&lt;td&gt;video_player + custom buffering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live streaming&lt;/td&gt;
&lt;td&gt;RTMP push, HLS pull&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Go (Gin) + gRPC microservices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time&lt;/td&gt;
&lt;td&gt;WebSocket (live chat), Firebase (notifications)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;MinIO (video), PostgreSQL (metadata)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CDN&lt;/td&gt;
&lt;td&gt;Cloudflare R2 + Stream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD&lt;/td&gt;
&lt;td&gt;GitHub Actions + Fastlane&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📐 Architecture Decisions That Saved Us
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Riverpod over Bloc
&lt;/h3&gt;

&lt;p&gt;We switched from BLoC mid-project. The &lt;code&gt;AsyncNotifier&lt;/code&gt; pattern reduced boilerplate by ~40% for async data operations. Provider-scoped state also made widget tests dramatically simpler.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Separate Video Controller per Page
&lt;/h3&gt;

&lt;p&gt;Instead of a global video player, each feed item owns its controller lifecycle. This enabled proper pause/resume during scroll and eliminated the "ghost audio" bug that haunts most video feed implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Optimistic UI everywhere
&lt;/h3&gt;

&lt;p&gt;Every like, follow, and comment triggers an immediate local state update before the server confirms. We built a simple rollback queue — if the server returns an error, the UI reverts. Users never wait.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Feature Flags from day 1
&lt;/h3&gt;

&lt;p&gt;We integrated a lightweight flag service on day 3. This let us ship unfinished features behind flags and do gradual rollouts. Saved us twice when a live streaming feature broke on specific Android OEMs.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 What the Numbers Look Like
&lt;/h2&gt;

&lt;p&gt;After 90 days we shipped:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;47 screens&lt;/strong&gt; across the app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;12 microservices&lt;/strong&gt; on the backend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3,200+ commits&lt;/strong&gt; across all repos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~0 crashes&lt;/strong&gt; in beta (Crashlytics-verified)&lt;/li&gt;
&lt;li&gt;Cold start time: &lt;strong&gt;&amp;lt; 1.8 seconds&lt;/strong&gt; on mid-range Android&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Biggest Lessons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Video is hard. Live video is harder.&lt;/strong&gt; The gap between "plays a video" and "plays a video reliably across 200+ Android device models" is enormous. Budget 2x your estimate for video features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-time sync is where complexity hides.&lt;/strong&gt; Live chat looks simple until you handle reconnection, message ordering under packet loss, and gift animations that need to land in sync.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flutter is genuinely ready for production video apps.&lt;/strong&gt; The ecosystem has matured. We hit zero framework-level bugs. The bottleneck was always our own code.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔓 Open Source
&lt;/h2&gt;

&lt;p&gt;DTok is open source. You can explore the codebase, star the repo, or build your own version on top of it.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;GitHub&lt;/strong&gt;: github.com/dtokapp/dtok&lt;br&gt;&lt;br&gt;
👉 &lt;strong&gt;Live Demo&lt;/strong&gt;: dtok.app&lt;br&gt;&lt;br&gt;
👉 &lt;strong&gt;Discord&lt;/strong&gt;: Join our builder community&lt;/p&gt;




&lt;p&gt;If you're building in the video space or curious how the architecture handles scale, drop a comment — happy to go deeper on any layer.&lt;/p&gt;

&lt;h1&gt;
  
  
  flutter #dart #livestreaming #videoapp #opensource #mobiledev #webdev
&lt;/h1&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>mobile</category>
      <category>opensource</category>
    </item>
    <item>
      <title>We Built a Full-Stack Flutter Short Video + Live Streaming App in 90 Days — Here's What We Shipped</title>
      <dc:creator>charlieww</dc:creator>
      <pubDate>Tue, 15 Sep 2026 13:54:04 +0000</pubDate>
      <link>https://dev.to/charlieww/we-built-a-full-stack-flutter-short-video-live-streaming-app-in-90-days-heres-what-we-shipped-12fl</link>
      <guid>https://dev.to/charlieww/we-built-a-full-stack-flutter-short-video-live-streaming-app-in-90-days-heres-what-we-shipped-12fl</guid>
      <description>&lt;p&gt;Let me be straight about what this is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DTok&lt;/strong&gt; — a full-stack Flutter source code package for short video + live streaming. Runs on Android, iOS, Web, and Desktop (6 platforms total). One-time purchase, no recurring fees.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's included
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;12 complete feature modules&lt;/strong&gt; — not a demo, not a prototype&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;6 business scenarios:&lt;/strong&gt; short dramas, live commerce, online education, content e-commerce, enterprise internal tools, vertical communities&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Private deployment&lt;/strong&gt; — your servers, your data, full deployment guide included&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;3-person team. 90 days to ship. First month revenue: $11,200 (¥82,000).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Flutter?
&lt;/h2&gt;

&lt;p&gt;One codebase, six platforms. The rendering is consistent, performance is solid, and the ecosystem has matured enough that we hit production-quality on all targets without platform-specific rewrites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Teams that want to launch a short video or live streaming product without building from scratch&lt;/li&gt;
&lt;li&gt;Agencies building for clients in these verticals&lt;/li&gt;
&lt;li&gt;Developers who want to study a real production Flutter codebase at scale&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  flutter #livestreaming #shortvideo #mobile #opensource
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>I tested my app across 8 platforms with zero test code — here's how</title>
      <dc:creator>charlieww</dc:creator>
      <pubDate>Tue, 24 Feb 2026 18:13:35 +0000</pubDate>
      <link>https://dev.to/charlieww/i-tested-my-app-across-8-platforms-with-zero-test-code-heres-how-37gd</link>
      <guid>https://dev.to/charlieww/i-tested-my-app-across-8-platforms-with-zero-test-code-heres-how-37gd</guid>
      <description>&lt;p&gt;Last week I shipped a cross-platform app and needed to test it on Flutter, React Native, iOS, Android, Electron, Tauri, and web. Writing separate test suites for each platform? No thanks.&lt;/p&gt;

&lt;p&gt;Instead, I used an AI agent that could see my app and interact with it. Here is what the workflow looked like:&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;I used &lt;a href="https://github.com/ai-dashboad/flutter-skill" rel="noopener noreferrer"&gt;flutter-skill&lt;/a&gt;, an open-source MCP server that gives AI agents eyes and hands inside running apps. It connects to your app via a lightweight bridge and exposes 253 tools the AI can use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; flutter-skill
flutter-skill init ./my-app
flutter-skill launch ./my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing with Natural Language
&lt;/h2&gt;

&lt;p&gt;Instead of writing test code, I just described what to test:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Test the login flow - enter &lt;a href="mailto:test@example.com"&gt;test@example.com&lt;/a&gt; and password123, tap Login, verify the Dashboard appears&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI agent automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Takes a screenshot to see the current state&lt;/li&gt;
&lt;li&gt;Discovers all interactive elements with semantic refs&lt;/li&gt;
&lt;li&gt;Taps, types, scrolls - just like a human&lt;/li&gt;
&lt;li&gt;Verifies the expected outcome&lt;/li&gt;
&lt;li&gt;Screenshots each step for evidence&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;Across 8 platforms, the AI agent completed &lt;strong&gt;562 out of 567 test scenarios&lt;/strong&gt; (99.1% pass rate). The failures were all legitimate bugs it discovered.&lt;/p&gt;

&lt;p&gt;What surprised me most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero test code written&lt;/strong&gt; - everything was natural language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform for free&lt;/strong&gt; - same test descriptions worked on iOS, Android, web, desktop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Found real bugs&lt;/strong&gt; - the AI explored edge cases I would not have thought of&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshot is 99% more token-efficient than screenshots&lt;/strong&gt; - the accessibility tree gives the AI structured data instead of pixels&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to Use This vs Traditional Automation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use AI testing when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to test across multiple platforms quickly&lt;/li&gt;
&lt;li&gt;You want to explore edge cases without writing explicit tests&lt;/li&gt;
&lt;li&gt;Your team does not have dedicated SDET resources&lt;/li&gt;
&lt;li&gt;You need fast smoke tests during development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stick with traditional automation when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need deterministic, repeatable CI/CD tests&lt;/li&gt;
&lt;li&gt;Performance benchmarking&lt;/li&gt;
&lt;li&gt;Testing specific race conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;flutter-skill is open source and free: &lt;a href="https://github.com/ai-dashboad/flutter-skill" rel="noopener noreferrer"&gt;github.com/ai-dashboad/flutter-skill&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Works with Claude, GPT, Gemini, Cursor, Windsurf, and any MCP-compatible agent.&lt;/p&gt;

&lt;p&gt;Would love to hear if anyone else is using AI agents for testing - what is working for you?&lt;/p&gt;

</description>
      <category>testingaiflutterwebdev</category>
    </item>
    <item>
      <title>How AI Semantic Snapshots Replace Screenshots for E2E Testing</title>
      <dc:creator>charlieww</dc:creator>
      <pubDate>Mon, 23 Feb 2026 22:45:30 +0000</pubDate>
      <link>https://dev.to/charlieww/how-ai-semantic-snapshots-replace-screenshots-for-e2e-testing-2pjn</link>
      <guid>https://dev.to/charlieww/how-ai-semantic-snapshots-replace-screenshots-for-e2e-testing-2pjn</guid>
      <description>&lt;h2&gt;
  
  
  The Problem with Screenshots
&lt;/h2&gt;

&lt;p&gt;Every AI-powered testing tool I've seen sends screenshots to the AI model. It works, but it's expensive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100KB+ per screenshot&lt;/li&gt;
&lt;li&gt;Thousands of tokens to process&lt;/li&gt;
&lt;li&gt;Visual recognition needed to find elements&lt;/li&gt;
&lt;li&gt;500ms-2s latency per analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Semantic Snapshots: A Better Way
&lt;/h2&gt;

&lt;p&gt;What if instead of a screenshot, you sent the AI a structured description of every interactive element — its position, label, type, and state?&lt;/p&gt;

&lt;p&gt;That's what semantic snapshots do. In &lt;strong&gt;1ms&lt;/strong&gt;, they extract the complete UI structure. The AI gets a machine-readable picture for a fraction of the token cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  New: Form Validation Detection
&lt;/h2&gt;

&lt;p&gt;The latest feature detects form validation rules automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Editor type&lt;/strong&gt;: CodeMirror, Draft.js, Tiptap, ProseMirror, Quill&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Required empty fields&lt;/strong&gt;: Which fields need to be filled&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why buttons are disabled&lt;/strong&gt;: Infers missing required fields&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best input method&lt;/strong&gt;: Recommends how to input text per framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means AI agents can fill and submit forms on the &lt;strong&gt;first try&lt;/strong&gt; — no trial and error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx flutter-skill@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;253 MCP tools, 10 platforms, 1ms latency.&lt;/p&gt;

&lt;p&gt;Open source: &lt;a href="https://github.com/ai-dashboad/flutter-skill" rel="noopener noreferrer"&gt;github.com/ai-dashboad/flutter-skill&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>ai</category>
      <category>webdev</category>
      <category>mcp</category>
    </item>
    <item>
      <title>How I Stopped Writing Fragile E2E Tests and Let AI Handle It</title>
      <dc:creator>charlieww</dc:creator>
      <pubDate>Mon, 23 Feb 2026 19:25:11 +0000</pubDate>
      <link>https://dev.to/charlieww/how-i-stopped-writing-fragile-e2e-tests-and-let-ai-handle-it-1hm3</link>
      <guid>https://dev.to/charlieww/how-i-stopped-writing-fragile-e2e-tests-and-let-ai-handle-it-1hm3</guid>
      <description>&lt;p&gt;Last month I spent 4 hours debugging a Playwright test that broke because someone renamed a CSS class. Sound familiar?&lt;/p&gt;

&lt;p&gt;I decided to try a different approach: what if the test framework could &lt;em&gt;see&lt;/em&gt; the app like a human does, instead of relying on brittle selectors?&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;An MCP (Model Context Protocol) server that gives AI agents — Claude, GPT, Cursor, Copilot — direct access to running applications. The AI can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch and connect to apps via CDP&lt;/li&gt;
&lt;li&gt;Tap elements, fill forms, scroll, navigate&lt;/li&gt;
&lt;li&gt;Take screenshots and analyze UI snapshots&lt;/li&gt;
&lt;li&gt;Run assertions in natural language&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Key Trick: Semantic Snapshots
&lt;/h2&gt;

&lt;p&gt;Instead of sending full screenshots (expensive in tokens), I built a snapshot system that extracts the UI's semantic structure — interactive elements, their positions, labels, states. The AI gets a complete picture of the UI in ~2ms and a few hundred tokens.&lt;/p&gt;

&lt;p&gt;Compare that to a screenshot: ~100KB of base64, thousands of tokens, and the AI still has to "guess" where buttons are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Traditional&lt;/th&gt;
&lt;th&gt;AI-Driven&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tap latency&lt;/td&gt;
&lt;td&gt;50-200ms&lt;/td&gt;
&lt;td&gt;1ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI analysis&lt;/td&gt;
&lt;td&gt;500ms-2s (screenshot)&lt;/td&gt;
&lt;td&gt;2ms (snapshot)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test brittleness&lt;/td&gt;
&lt;td&gt;High (selector-dependent)&lt;/td&gt;
&lt;td&gt;Low (semantic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Platforms supported&lt;/td&gt;
&lt;td&gt;Usually 1-2&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Supported Platforms
&lt;/h2&gt;

&lt;p&gt;Flutter, React Native, iOS, Android, Web (Chrome/Firefox/Safari), Electron, Tauri, KMP, .NET MAUI.&lt;/p&gt;

&lt;p&gt;253 MCP tools total. Video recording, API testing, mock responses, parallel multi-device — it's all there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;\&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
npx flutter-skill@latest&lt;br&gt;
\&lt;/code&gt;&lt;code&gt;\&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add to your MCP config and your AI assistant can start testing immediately.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/ai-dashboad/flutter-skill" rel="noopener noreferrer"&gt;ai-dashboad/flutter-skill&lt;/a&gt;&lt;br&gt;
npm: &lt;a href="https://www.npmjs.com/package/flutter-skill" rel="noopener noreferrer"&gt;flutter-skill&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love to hear from anyone doing E2E testing — what's the most annoying part of your current setup?&lt;/p&gt;

</description>
      <category>testing</category>
      <category>mcp</category>
      <category>webdev</category>
      <category>aitesting</category>
    </item>
    <item>
      <title>I Replaced 500 Lines of E2E Tests with One AI Prompt</title>
      <dc:creator>charlieww</dc:creator>
      <pubDate>Mon, 23 Feb 2026 09:44:31 +0000</pubDate>
      <link>https://dev.to/charlieww/i-replaced-500-lines-of-e2e-tests-with-one-ai-prompt-40am</link>
      <guid>https://dev.to/charlieww/i-replaced-500-lines-of-e2e-tests-with-one-ai-prompt-40am</guid>
      <description>&lt;h2&gt;
  
  
  The Breaking Point
&lt;/h2&gt;

&lt;p&gt;I had 500+ lines of E2E test code across three platforms. Every UI change broke dozens of selectors. Every framework migration meant rewriting test suites.&lt;/p&gt;

&lt;p&gt;Then I tried something different: &lt;strong&gt;let AI control the app directly.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is flutter-skill?
&lt;/h2&gt;

&lt;p&gt;An MCP server with &lt;strong&gt;253 tools&lt;/strong&gt; that lets Claude, Cursor, or any MCP client:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;See&lt;/strong&gt; your app through screenshots (31ms capture)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interact&lt;/strong&gt; like a human — tap, scroll, type (1ms latency)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test across 10 platforms&lt;/strong&gt; with natural language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-adapt&lt;/strong&gt; when UI changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Before vs After
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Traditional (Playwright — 50+ lines)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://app.example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#register-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#register-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[name=email]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ... 50 more lines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  AI-Driven (1 line)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter-skill &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"Open registration, fill email and password, accept terms, submit, verify welcome page"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;99.8% less code. Zero maintenance.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it Compares
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;MCP Tools&lt;/th&gt;
&lt;th&gt;Platforms&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;flutter-skill&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;253&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;10&lt;/strong&gt; (Flutter, RN, iOS, Android, Web, Electron, Tauri, KMP, .NET MAUI, CDP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playwright MCP&lt;/td&gt;
&lt;td&gt;~33&lt;/td&gt;
&lt;td&gt;1 (Web only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Appium&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;2 (iOS + Android)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tap latency: &lt;strong&gt;1ms&lt;/strong&gt; (near hardware limit)&lt;/li&gt;
&lt;li&gt;Screenshot: &lt;strong&gt;31ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;UI analysis: &lt;strong&gt;2ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Compare: Selenium 100-500ms, Appium 200-1000ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;181 test scenarios across 8 platforms: &lt;strong&gt;99% pass rate&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; flutter-skill
flutter-skill init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; flutter-skill demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/ai-dashboad/flutter-skill" rel="noopener noreferrer"&gt;github.com/ai-dashboad/flutter-skill&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open source, MIT licensed. Happy to answer questions!&lt;/p&gt;

</description>
      <category>testing</category>
    </item>
    <item>
      <title>Zero-code E2E testing for any app with OpenClaw + flutter-skill</title>
      <dc:creator>charlieww</dc:creator>
      <pubDate>Sat, 14 Feb 2026 13:41:24 +0000</pubDate>
      <link>https://dev.to/charlieww/zero-code-e2e-testing-for-any-app-with-openclaw-flutter-skill-f00</link>
      <guid>https://dev.to/charlieww/zero-code-e2e-testing-for-any-app-with-openclaw-flutter-skill-f00</guid>
      <description>&lt;p&gt;What if your AI agent could actually &lt;em&gt;use&lt;/em&gt; your app?&lt;/p&gt;

&lt;p&gt;Not review your test code. Actually tap buttons, enter text, scroll through lists, take screenshots, and verify everything works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;flutter-skill&lt;/strong&gt; makes this real. It's an MCP server that gives AI agents eyes and hands inside any running app.&lt;/p&gt;

&lt;p&gt;Now available as a skill for Claude Code, Cursor, OpenClaw, and 20+ other agents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add ai-dashboad/flutter-skill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Initialize your app (one-time):
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter-skill init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Tell the agent what to test:&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;"Test the login flow — enter admin and password123, tap Login, verify Dashboard appears"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent screenshots the screen, finds UI elements, interacts with them, and verifies results. No test code. No selectors. Just natural language.&lt;/p&gt;
&lt;h2&gt;
  
  
  8 platforms, 99% pass rate
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;SDK&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Flutter iOS/Android/Web&lt;/td&gt;
&lt;td&gt;Dart&lt;/td&gt;
&lt;td&gt;21/21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Native&lt;/td&gt;
&lt;td&gt;JS&lt;/td&gt;
&lt;td&gt;24/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Electron&lt;/td&gt;
&lt;td&gt;JS&lt;/td&gt;
&lt;td&gt;24/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android Native&lt;/td&gt;
&lt;td&gt;Kotlin&lt;/td&gt;
&lt;td&gt;24/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tauri&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;23/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET MAUI&lt;/td&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;23/24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KMP Desktop&lt;/td&gt;
&lt;td&gt;Kotlin&lt;/td&gt;
&lt;td&gt;22/22&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Total: 181/183 tests passing&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why use a skill?
&lt;/h2&gt;

&lt;p&gt;Skills are reusable capabilities for AI agents. Install once, use forever:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One-command install via &lt;code&gt;npx skills&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Works with Claude Code, Cursor, Windsurf, Codex, Cline, and 20+ agents&lt;/li&gt;
&lt;li&gt;Schedule tests with cron for continuous testing&lt;/li&gt;
&lt;li&gt;AI-native: understands natural language prompts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;AI testing a TikTok-level app (10 feature modules), fully autonomous:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://github-production-user-asset-6210df.s3.amazonaws.com/6106454/549827272-d4617c73-043f-424c-9a9a-1a61d4c2d3c6.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20260327%2Fus-east-1%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20260327T201607Z&amp;amp;X-Amz-Expires=300&amp;amp;X-Amz-Signature=60a19a6fdd36600af3f0c06e87583ac2b852c4e4b8fac8ddb408a76f98d1bfdc&amp;amp;X-Amz-SignedHeaders=host" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;github-production-user-asset-6210df.s3.amazonaws.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  Get started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install as agent skill (Claude Code, Cursor, OpenClaw, etc.)&lt;/span&gt;
npx skills add ai-dashboad/flutter-skill

&lt;span class="c"&gt;# Or install CLI globally&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; flutter-skill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⭐ &lt;a href="https://github.com/ai-dashboad/flutter-skill" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;What platform would you test first? Drop a comment!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>flutter</category>
      <category>mcp</category>
      <category>testing</category>
    </item>
    <item>
      <title>How to Test Any App with AI in 30 Seconds — Flutter, React Native, iOS, Android &amp; More</title>
      <dc:creator>charlieww</dc:creator>
      <pubDate>Fri, 13 Feb 2026 18:36:47 +0000</pubDate>
      <link>https://dev.to/charlieww/how-to-test-any-app-with-ai-in-30-seconds-flutter-react-native-ios-android-more-j6c</link>
      <guid>https://dev.to/charlieww/how-to-test-any-app-with-ai-in-30-seconds-flutter-react-native-ios-android-more-j6c</guid>
      <description>&lt;h1&gt;
  
  
  How to Test Any App with AI in 30 Seconds
&lt;/h1&gt;

&lt;p&gt;What if testing your app required zero test code?&lt;/p&gt;

&lt;p&gt;Not "low-code testing." Not "AI-assisted test generation." Literally zero lines of test code — you describe what should happen, and AI does it.&lt;/p&gt;

&lt;p&gt;That's what we built with &lt;a href="https://github.com/ai-dashboad/flutter-skill" rel="noopener noreferrer"&gt;flutter-skill&lt;/a&gt;: an open-source MCP server that gives AI agents eyes and hands inside any running app.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;E2E testing is universally hated for a reason:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// This breaks every time someone moves a button
final loginButton = find.byKey(Key('loginBtn'));
await tester.tap(loginButton);
await tester.pumpAndSettle();
final emailField = find.byKey(Key('emailField'));
await tester.enterText(emailField, 'test@example.com');
// ... 50 more lines of brittle selectors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're not testing your app. You're maintaining a second codebase that mirrors your UI. Every refactor breaks it. Every design change means rewriting tests.&lt;/p&gt;

&lt;p&gt;And it gets worse: &lt;strong&gt;every platform has its own testing framework.&lt;/strong&gt; Flutter has &lt;code&gt;integration_test&lt;/code&gt;. iOS has XCUITest. Android has Espresso. React Native has Detox. Web has Playwright. Each with its own API, its own quirks, its own debug cycle.&lt;/p&gt;

&lt;p&gt;What if there was one tool for all of them?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea: Let AI Be the User
&lt;/h2&gt;

&lt;p&gt;Instead of writing robot instructions, what if we just... talked to the robot?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Tap the login button, enter test@email.com as the email,
enter password123 as the password, tap submit,
and verify the dashboard loads."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a complete E2E test. No selectors. No framework-specific code. No maintenance when the UI changes — because AI understands what a "login button" looks like, regardless of its internal key.&lt;/p&gt;

&lt;p&gt;This is what MCP (Model Context Protocol) makes possible. MCP lets AI tools like Claude, Cursor, and Windsurf connect to external services. flutter-skill is one of those services — it bridges AI to your running app's UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The architecture is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────┐     MCP      ┌────────────────┐   WebSocket   ┌─────────────┐
│  AI Client   │ ◄──────────► │  flutter-skill  │ ◄────────────► │  Your App    │
│ (Claude,     │   JSON-RPC   │  (MCP Server)   │   JSON-RPC    │  (any        │
│  Cursor,     │              │                 │   on :18118   │   platform)  │
│  Windsurf)   │              └────────────────┘               └─────────────┘
└─────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Your app&lt;/strong&gt; includes a lightweight SDK (a few lines of code) that connects via WebSocket&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;flutter-skill&lt;/strong&gt; runs as an MCP server, translating AI commands into app interactions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your AI tool&lt;/strong&gt; sends natural language instructions, which flutter-skill converts to precise UI operations&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The SDK exposes your app's accessibility tree — every button, text field, label, and container — so the AI can see exactly what's on screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup: Actually 30 Seconds
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Install (5 seconds)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; flutter-skill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Initialize your project (10 seconds)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;your-app
flutter-skill init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This auto-detects your project type and patches your entry point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pubspec.yaml&lt;/code&gt; → Flutter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Package.swift&lt;/code&gt; → iOS native&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build.gradle.kts&lt;/code&gt; + &lt;code&gt;AndroidManifest.xml&lt;/code&gt; → Android native&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt; + &lt;code&gt;react-native&lt;/code&gt; → React Native&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;index.html&lt;/code&gt; → Web&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt; + &lt;code&gt;electron&lt;/code&gt; → Electron&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cargo.toml&lt;/code&gt; + &lt;code&gt;tauri&lt;/code&gt; → Tauri&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build.gradle.kts&lt;/code&gt; + &lt;code&gt;kotlin&lt;/code&gt; → KMP&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.csproj&lt;/code&gt; + &lt;code&gt;Maui&lt;/code&gt; → .NET MAUI&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 3: Add to your AI tool (15 seconds)
&lt;/h3&gt;

&lt;p&gt;Add to your MCP config (e.g., Claude Desktop &lt;code&gt;claude_desktop_config.json&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"flutter-skill"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"flutter-skill"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Your AI can now see and interact with your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI Can Do
&lt;/h2&gt;

&lt;p&gt;Once connected, your AI has access to 40+ tools:&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;inspect&lt;/code&gt;&lt;/strong&gt; — See the full UI element tree (accessibility labels, types, positions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;get_element_details&lt;/code&gt;&lt;/strong&gt; — Deep-dive into any specific element&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Interaction
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tap&lt;/code&gt;&lt;/strong&gt; — Tap any element by description or index&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;enter_text&lt;/code&gt;&lt;/strong&gt; — Type into text fields&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;scroll&lt;/code&gt;&lt;/strong&gt; — Scroll in any direction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;swipe&lt;/code&gt;&lt;/strong&gt; — Swipe gestures (e.g., dismiss, navigate)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;long_press&lt;/code&gt;&lt;/strong&gt; — Long press for context menus&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Verification
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;screenshot&lt;/code&gt;&lt;/strong&gt; — Capture what the app looks like right now&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;assert_exists&lt;/code&gt;&lt;/strong&gt; — Verify an element is on screen&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;get_text&lt;/code&gt;&lt;/strong&gt; — Read text content from any element&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Navigation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;go_back&lt;/code&gt;&lt;/strong&gt; — Navigate back&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;open_url&lt;/code&gt;&lt;/strong&gt; — Deep link to any route&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advanced
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;eval&lt;/code&gt;&lt;/strong&gt; — Execute platform-native code (Dart, JS, Swift, Kotlin)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;get_logs&lt;/code&gt;&lt;/strong&gt; — Read app console output&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real Example: Testing a Login Flow
&lt;/h2&gt;

&lt;p&gt;Here's what happens when you tell Claude: &lt;em&gt;"Test the login flow with invalid credentials and verify the error message."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Claude (via flutter-skill):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. inspect() → sees the login screen with email field, password field, submit button
2. tap(element: "Email field")
3. enter_text(text: "bad@email.com")
4. tap(element: "Password field")
5. enter_text(text: "wrongpassword")
6. tap(element: "Submit")
7. screenshot() → captures the error state
8. assert_exists(element: "Invalid credentials") → ✅ verified
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No test file created. No selectors maintained. If the UI changes tomorrow, the AI adapts — it looks for "Submit" by understanding the UI, not by memorizing a widget key.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;p&gt;We tested flutter-skill across 8 platforms with a comprehensive E2E test suite:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Tests&lt;/th&gt;
&lt;th&gt;Passing&lt;/th&gt;
&lt;th&gt;Rate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Flutter iOS&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flutter Web&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Electron&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android Native&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KMP Desktop&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Native&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tauri&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;95.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET MAUI&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;95.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;183&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;181&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.0%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every test is AI-driven. Zero hand-written test code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons from Building for 8 Platforms
&lt;/h2&gt;

&lt;p&gt;Building SDKs for 8 platforms taught us things no tutorial covers:&lt;/p&gt;

&lt;h3&gt;
  
  
  Android: PNG Screenshots Kill WebSocket
&lt;/h3&gt;

&lt;p&gt;Full-resolution PNG screenshots on Android are huge. Sending them over WebSocket caused timeouts. The fix: JPEG at 80% quality, downscaled to 720p. AI reads the UI just fine at lower resolution, and it saves ~90% bandwidth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tauri: eval() Is Fire-and-Forget
&lt;/h3&gt;

&lt;p&gt;Tauri v2's &lt;code&gt;eval()&lt;/code&gt; function doesn't return values. It executes JavaScript in the webview and... that's it. No callback, no promise, no return.&lt;/p&gt;

&lt;p&gt;Our solution: open a secondary WebSocket on port 18120. The JavaScript sends its result there, and Rust receives it via a oneshot channel. Three ports total: HTTP health (18118), WS commands (18119), WS results (18120).&lt;/p&gt;

&lt;p&gt;We also had to add &lt;code&gt;ws://127.0.0.1:*&lt;/code&gt; to Tauri's CSP, otherwise WebSocket connections from the &lt;code&gt;tauri://&lt;/code&gt; origin to localhost are silently blocked.&lt;/p&gt;

&lt;h3&gt;
  
  
  React Native: Skip the Full Build
&lt;/h3&gt;

&lt;p&gt;Building a full React Native project requires native modules, CocoaPods, Gradle — the works. For testing, we used a Node.js mock that implements the bridge protocol directly. Much faster, same result.&lt;/p&gt;

&lt;h3&gt;
  
  
  The go_back Race Condition
&lt;/h3&gt;

&lt;p&gt;On Android, clearing &lt;code&gt;currentActivity&lt;/code&gt; on &lt;code&gt;onActivityPaused&lt;/code&gt; caused a race condition with &lt;code&gt;go_back&lt;/code&gt;. The previous activity pauses before the new one resumes, leaving a brief window where the SDK thinks there's no activity. Fix: only clear on &lt;code&gt;onActivityDestroyed&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use This (and When Not To)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use flutter-skill when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want to test user-facing flows without writing test code&lt;/li&gt;
&lt;li&gt;You're building across multiple platforms and want one testing approach&lt;/li&gt;
&lt;li&gt;You're doing vibe coding and need AI to verify what it builds&lt;/li&gt;
&lt;li&gt;You want to prototype and test simultaneously&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't use it for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unit testing (that's a different problem)&lt;/li&gt;
&lt;li&gt;Performance benchmarking (AI interaction adds latency)&lt;/li&gt;
&lt;li&gt;Tests that need to run in &amp;lt; 1 second (AI thinking time)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install&lt;/span&gt;
npm i &lt;span class="nt"&gt;-g&lt;/span&gt; flutter-skill

&lt;span class="c"&gt;# Auto-detect and configure your project&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;your-app
flutter-skill init

&lt;span class="c"&gt;# Or try the built-in demo&lt;/span&gt;
flutter-skill demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add to your MCP config, and start talking to your app through AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ai-dashboad/flutter-skill" rel="noopener noreferrer"&gt;github.com/ai-dashboad/flutter-skill&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MIT licensed. Contributions welcome.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;flutter-skill supports Flutter, iOS, Android, Web, Electron, Tauri, KMP, React Native, and .NET MAUI. Works with Claude, Cursor, Windsurf, and any MCP-compatible AI tool.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
  </channel>
</rss>
