syntaxify 0.1.0-alpha.8 copy "syntaxify: ^0.1.0-alpha.8" to clipboard
syntaxify: ^0.1.0-alpha.8 copied to clipboard

AST-based Flutter UI code generator with multi-style design system. Write components once, render in Material, Cupertino, or custom designs.

Syntaxify ⚡ #

AST-based Flutter UI Code Generator with Multi-Style Design System

Stop writing repetitive UI code. Define components once, render in any design system.

pub package GitHub stars License: MIT Buy Me A Coffee


⚡ Quick Win: Generate Screens in Seconds #

// Create meta/login.screen.dart
final loginScreen = ScreenDefinition(
  id: 'login',
  layout: AstNode.column(children: [
    AstNode.text(text: 'Welcome'),
    AstNode.textField(label: 'Email'),
    AstNode.button(label: 'Login', onPressed: 'handleLogin'),
  ]),
);

Run: dart run syntaxify build Get: Complete Flutter screen in lib/screens/login_screen.dart

No boilerplate. No repetition. Just results.


👀 See It In Action #

Syntaxify Demo

Check out the example app - A working Flutter app demonstrating all features with live style switching!

cd example && flutter run

🤔 Why Syntaxify? #

The Problem: Flutter's Design System Scalability Crisis #

Flutter developers face a fundamental dilemma when building production apps:

The Multi-Platform UI Duplication Problem:

  • Material Design for Android
  • Cupertino for iOS
  • Custom designs for brand identity

Traditional approach means writing everything 3 times:

// You write this for EVERY component!
Widget buildButton() {
  if (Platform.isIOS) {
    return CupertinoButton(
      onPressed: onPressed,
      child: Text(label),
    );
  } else if (useCustom) {
    return CustomButton(
      onPressed: onPressed,
      label: label,
    );
  } else {
    return ElevatedButton(
      onPressed: onPressed,
      child: Text(label),
    );
  }
}

Real-World Impact:

  • 🏢 Large Apps: 100+ screens, 1000+ components
  • 👥 Team Scale: Multiple developers, changing requirements
  • 🔄 Maintenance Nightmare: "Change all buttons to rounded corners" = touching 500+ files
  • 💸 Cost: "Switch from Material to Cupertino" = rewriting the entire app
  • 🎨 Design Changes: "Our designer wants a custom look" = building everything from scratch

The Solution: Separation of WHAT and HOW #

Syntaxify delivers on Flutter's original promise: "write once, run anywhere" - but for design systems.

With Syntaxify:

// Write once
AppButton(label: 'Click Me', onPressed: ...)

// Renders appropriately everywhere
AppTheme(style: MaterialStyle())   // Material on Android
AppTheme(style: CupertinoStyle())  // iOS-native on iPhone
AppTheme(style: NeoStyle())        // Custom brand design

Change your entire app's design system in one line:

// Before: Material Design
AppTheme(style: MaterialStyle(), child: MyApp())

// After: iOS-native Cupertino
AppTheme(style: CupertinoStyle(), child: MyApp())
// Zero component code changes needed!

What Makes Syntaxify Different #

Most Flutter solutions offer partial fixes:

  • Widget libraries - Still manual integration, not design-system-aware
  • Themes - Only styling, not structure
  • Code generation - Not multi-platform aware

Syntaxify combines all three:

  • Code generation - Eliminate boilerplate
  • Design system architecture - WHAT vs HOW separation
  • Multi-platform rendering - One component, any design
  • Type-safe APIs - Compile-time safety

🎨 The Design System Architecture #

The Renderer Pattern #

Syntaxify uses a unique renderer pattern that separates concerns:

WHAT (Component Definition):

AppButton.primary(
  label: 'Click Me',
  onPressed: () => print('Hello!'),
)

HOW (Style Rendering):

  • Material: Renders as ElevatedButton with Material Design tokens
  • Cupertino: Renders as CupertinoButton with iOS styling
  • Neo: Renders with modern, neumorphic design

The Magic: Same component code, different visual output based on AppTheme:

AppTheme(
  style: MaterialStyle(),  // or CupertinoStyle() or NeoStyle()
  child: MaterialApp(home: YourApp()),
)

Why This Matters #

  1. Write Once, Render Anywhere - One component definition works across all design systems
  2. Easy Theme Switching - Change one line to switch your entire app's design
  3. Consistent Behavior - Button logic stays the same, only visuals change
  4. Custom Styles - Create your own design system by implementing DesignStyle

📦 What's Currently Available #

🌟 Screen Generation from .screen.dart Files (Star Feature!) #

The fastest way to build Flutter screens:

// meta/login.screen.dart
final loginScreen = ScreenDefinition(
  id: 'login',
  layout: AstNode.column(children: [
    AstNode.text(text: 'Welcome Back'),
    AstNode.textField(label: 'Email'),
    AstNode.button(label: 'Sign In', onPressed: 'handleLogin'),
  ]),
);

Run syntaxify build → Get a complete Flutter screen!

  • ✅ Generate entire screens from simple definitions
  • ✅ Editable after generation (you own the code)
  • ✅ Type-safe callbacks and imports
  • ✅ Proper structure and scaffolding
  • ✅ No boilerplate, no repetition

✅ Components with Full Renderer Pattern #

These components work with Material, Cupertino, and Neo styles:

  • AppButton - Buttons with variants (primary, secondary, outlined)
  • AppText - Text with typography variants (display, headline, title, body, label)
  • AppInput - Text fields with validation and keyboard types

🚧 Custom Components (Basic Support) #

You can define custom components (e.g., Card, Badge, Avatar), and Syntaxify will:

  • ✅ Generate the component class
  • ✅ Create constructor and fields
  • ⚠️ Generate basic Container widget (not full renderer pattern yet)

Coming Soon: Full renderer pattern for more components (Card, Badge, Avatar, Chip, etc.)


🚀 Complete Getting Started Guide #

Step 1: Install Syntaxify #

Option A: From pub.dev (Recommended)

# pubspec.yaml
dev_dependencies:
  syntaxify: ^0.1.0-alpha.1

Then run:

dart pub get

Option B: From GitHub (Latest)

# pubspec.yaml
dev_dependencies:
  syntaxify:
    git:
      url: https://github.com/ihardk/syntaxify.git
      ref: v0.1.0
      path: generator

⚠️ Alpha Release: This package is in alpha. API may change. See CHANGELOG for updates.

Optional: Global Installation

If you want syntaxify available system-wide (not just in your project):

dart pub global activate syntaxify

Then you can run syntaxify commands from anywhere. Otherwise, use dart run syntaxify in your project.

Step 2: Initialize Your Project #

cd your_flutter_project
dart run syntaxify init

This creates:

  • meta/ - Where you define component APIs
  • lib/syntaxify/design_system/ - Customizable design system

Step 3: Define Components #

Edit meta/button.meta.dart:

import 'package:syntaxify/syntaxify.dart';

@SyntaxComponent(description: 'A customizable button')
class ButtonMeta {
  /// The button label text
  @Required()
  final String label;

  /// The action to trigger (e.g. 'action:login')
  @Optional()
  final String? onPressed;

  /// Button variant (filled, outlined, etc)
  @Optional()
  final String? variant;

  /// Button size (sm, md, lg)
  @Optional()
  final String? size;

  /// Whether the button shows loading state
  @Optional()
  @Default('false')
  final bool isLoading;

  /// Whether the button is disabled
  @Optional()
  @Default('false')
  final bool isDisabled;
}

Step 4: Build #

dart run syntaxify build

This generates:

  • lib/syntaxify/generated/components/app_button.dart - The component
  • lib/syntaxify/design_system/ - Design system files (Material, Cupertino, Neo)
  • lib/syntaxify/index.dart - Barrel export

Step 5: Use in Your App #

import 'package:flutter/material.dart';
import 'package:your_app/syntaxify/index.dart';

void main() {
  runApp(
    AppTheme(
      style: MaterialStyle(),  // Try CupertinoStyle() or NeoStyle()!
      child: MaterialApp(
        home: Scaffold(
          body: Center(
            child: AppButton.primary(
              label: 'Click Me',
              onPressed: () => print('Hello from Syntaxify!'),
            ),
          ),
        ),
      ),
    ),
  );
}

Step 6: Generate Screens (Optional) #

Create meta/login.screen.dart:

import 'package:syntaxify/syntaxify.dart';

final loginScreen = ScreenDefinition(
  id: 'login',
  layout: AstNode.column(children: [
    AstNode.text(text: 'Welcome Back'),
    AstNode.textField(label: 'Email', keyboardType: KeyboardType.emailAddress),
    AstNode.textField(label: 'Password', obscureText: true),
    AstNode.button(label: 'Sign In', onPressed: 'handleLogin'),
  ]),
);

Run dart run syntaxify build again - generates lib/screens/login_screen.dart (editable!)


🎯 Real-World Example #

Before Syntaxify (Manual Approach) #

Material Button:

ElevatedButton(
  onPressed: onPressed,
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
    padding: EdgeInsets.all(16),
  ),
  child: Text(label),
)

Cupertino Button:

CupertinoButton.filled(
  onPressed: onPressed,
  padding: EdgeInsets.all(16),
  child: Text(label),
)

Custom Button:

Container(
  decoration: BoxDecoration(
    gradient: LinearGradient(...),
    borderRadius: BorderRadius.circular(12),
    boxShadow: [BoxShadow(...)],
  ),
  child: Material(
    color: Colors.transparent,
    child: InkWell(
      onTap: onPressed,
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Text(label),
      ),
    ),
  ),
)

Problem: 3 different implementations, hard to maintain, inconsistent behavior.

After Syntaxify #

One Definition:

AppButton.primary(label: 'Submit', onPressed: handleSubmit)

Three Renderings:

  • Wrap with MaterialStyle() → Material Design
  • Wrap with CupertinoStyle() → iOS Design
  • Wrap with NeoStyle() → Modern Design

Result: Consistent API, different visuals, easy to switch.


📂 Project Structure #

your_project/
├── meta/                          # YOU EDIT: Component & screen definitions
│   ├── button.meta.dart
│   ├── input.meta.dart
│   ├── text.meta.dart
│   ├── login.screen.dart
│   └── app_icons.dart
│
└── lib/
    ├── screens/                   # EDITABLE: Generated screens
    │   └── login_screen.dart      # Generated once, then you own it
    │
    └── syntaxify/
        ├── design_system/         # CUSTOMIZABLE: Styles & tokens
        │   ├── design_system.dart
        │   ├── app_theme.dart
        │   ├── styles/
        │   │   ├── material_style.dart
        │   │   ├── cupertino_style.dart
        │   │   └── neo_style.dart
        │   └── tokens/
        │       ├── button_tokens.dart
        │       └── input_tokens.dart
        │
        ├── generated/             # DON'T EDIT: Auto-regenerated
        │   └── components/
        │       ├── app_button.dart
        │       ├── app_input.dart
        │       └── app_text.dart
        │
        └── index.dart             # Barrel export

📖 API Reference #

For detailed API documentation, see API Reference.

Quick Overview:

Component Description
AppButton Primary, secondary, outlined button variants
AppText Typography with 6 text style variants
AppInput Text fields with keyboard types & validation

Design Styles: MaterialStyle(), CupertinoStyle(), NeoStyle()

Import: import 'package:your_app/syntaxify/index.dart';


🔄 Development Workflow #

  1. Define - Edit meta/*.meta.dart to define component APIs
  2. Build - Run dart run syntaxify build to generate implementations
  3. Use - Import from package:your_app/syntaxify/ and use
  4. Customize - Edit design system tokens in lib/syntaxify/design_system/
  5. Switch Styles - Change AppTheme(style: ...) to try different designs

Understanding Generated Code #

Important: Two types of generated code with different lifecycles:

Components (Regenerate Every Build)

Location: lib/syntaxify/generated/components/ Behavior: Regenerated on EVERY syntaxify build Rule: ⚠️ DO NOT EDIT - Your changes will be lost!

// lib/syntaxify/generated/components/app_button.dart
// This file is REGENERATED on every build
class AppButton extends StatelessWidget {
  // Generated code - DO NOT MODIFY
}

Screens (Generate Once)

Location: lib/screens/ Behavior: Generated ONCE, then YOU own it Rule:FREELY EDIT - Won't be overwritten

// lib/screens/login_screen.dart
// Generated once, then it's yours to edit
class LoginScreen extends StatelessWidget {
  // Edit this freely - it won't be regenerated
}

What happens when you rebuild?

  • Components: Completely regenerated from meta files
  • Screens: Skipped (only generated if file doesn't exist)

🛠️ Advanced Usage #

For advanced topics, see the detailed documentation:


🐛 Troubleshooting #

Having issues? See Troubleshooting Guide for common errors and solutions.

Quick fixes:

  • TextVariant.headline → Use TextVariant.headlineMedium
  • KeyboardType.email → Use TextInputType.emailAddress
  • Component not updating? → Edit meta/*.meta.dart, not generated files

Need help? GitHub Issues


✨ Features #

  • AST-Based Generation - Type-safe, declarative UI definitions
  • Renderer Pattern - Separates WHAT (behavior) from HOW (rendering)
  • Multi-Style Support - Material, Cupertino, Neo (3 components currently, more coming)
  • Smart Defaults - Auto-detects project structure
  • Screen Generation - Generate editable screen scaffolds
  • Design Tokens - Centralized styling with tokens
  • Git-Friendly - Clean, readable generated code
  • Extensible - Create custom design styles by implementing DesignStyle

🗺️ Roadmap #

v0.1.0 (Current)

  • ✅ Core architecture with renderer pattern
  • ✅ 3 components (Button, Text, Input)
  • ✅ 3 design styles (Material, Cupertino, Neo)
  • ✅ Screen generation
  • ✅ Smart build defaults

v0.2.0 (Next)

  • 🔄 More components with full renderer pattern:
    • Card, Badge, Avatar, Chip, Switch, Checkbox, Radio
  • 🔄 Golden tests for visual regression
  • 🔄 Better error messages

v1.0.0 (Future)

  • 🔮 Complete component library
  • 🔮 Theme editor UI
  • 🔮 VS Code extension
  • 🔮 Component marketplace

📚 Documentation #

Guide Description
Getting Started Installation & first steps
API Reference Component usage & options
Design System Renderer pattern & custom styles
Troubleshooting Common issues & solutions
User Manual Comprehensive user guide
Developer Manual Architecture & contributing

🤝 Contributing #

See Developer Manual for architecture details and contribution guidelines.

📄 License #

MIT License - See LICENSE for details


Built with ❤️ for Flutter developers who value consistency, productivity, and beautiful code

⭐ Star us on GitHub📦 pub.dev☕ Buy Me a Coffee

0
likes
140
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

AST-based Flutter UI code generator with multi-style design system. Write components once, render in Material, Cupertino, or custom designs.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, args, code_builder, dart_style, file, freezed_annotation, json_annotation, mason_logger, path

More

Packages that depend on syntaxify