The Problem Nobody Talks About
Flutter Web has a secret: it's not really "the web."
When you build a Flutter Web app, everything renders to a <canvas> element. That's fine for complex apps, but for websites it creates serious problems:
- No SEO – Google can't index canvas pixels
- Huge bundles – 2-5 MB minimum, even for simple apps
- Poor accessibility – No semantic HTML for screen readers
- Slow first paint – 3-8 seconds to see content
I hit this wall when a client asked me to build a marketing site in Flutter. It looked great, but Google Search Console showed zero impressions. The site was invisible.
A Different Approach
What if Flutter compiled to actual HTML instead of canvas?
That's what I built. FlutterJS takes your normal Flutter/Dart code:
Scaffold(
appBar: AppBar(title: Text('My Site')),
body: Center(
child: Text('Hello, World!'),
),
)
And outputs semantic HTML:
<main>
<header><h1>My Site</h1></header>
<section>
<p>Hello, World!</p>
</section>
</main>
Same Flutter DX. Real web output.
How It Works
- Write normal Flutter code – no special syntax
- Dart CLI analyzes your AST – full type resolution
- Generates JavaScript – with a lightweight VNode runtime
- Outputs semantic HTML – that search engines can index
The JavaScript runtime handles diffing and updates, similar to React's virtual DOM but optimized for Flutter's widget model.
The Results
| Metric | Flutter Web | FlutterJS |
|---|---|---|
| Bundle Size | 2-5 MB | 50-100 KB |
| First Paint | 3-8s | <1s |
| SEO Score | 0-30 | 90-100 |
What Works Today
Layout widgets:
- Container, Row, Column, Center, Padding
- Stack, Positioned, Expanded, Flexible, SizedBox
Material widgets:
- Scaffold, AppBar, Drawer
- ElevatedButton, TextButton, IconButton
- TextField, Checkbox, Radio, Switch
- Text, Icon, Image, Card
State management:
- StatefulWidget, setState()
- InheritedWidget
- Navigation
What's Missing (For Now)
- Package support – External pub.dev packages aren't fully supported yet. Pure UI code works great!
- Animations
- Advanced Material widgets (Tabs, Dialog, BottomSheet)
- Cupertino widgets
- CustomPainter
These are on the roadmap. The architecture supports them, I just haven't implemented them yet.
Try It
# Clone the repository
git clone --recursive https://github.com/flutterjsdev/flutterjs.git
cd flutterjs
# Activate the Dart CLI
dart pub global activate --source path .
dart pub get
dart run tool/init.dart
# Now you can use flutterjs commands
flutterjs --help
Open http://localhost:3000 and inspect the page. You'll see real HTML elements.
Links
- Website: flutterjs.dev
- GitHub: github.com/flutterjsdev/flutterjs
- pub.dev: pub.dev/packages/flutterjs_seo
I Need Your Help
This is open source and I'm looking for contributors. If you care about Flutter on the web:
- Test it and report bugs
- Contribute missing widgets
- Help with documentation
What widgets would you need for your use case? Let me know in the comments.
Top comments (0)