bloomBUILD•SHIP•BLOOM
.md
Zero-Boilerplate Navigation

Filesystem Routing

Bloom brings the intuitive filesystem routing of Next.js and SvelteKit to Flutter, compiling your directory tree into high-performance, type-safe go_router routes.

File & Directory Conventions

Every Dart file placed inside lib/routes/ automatically becomes an accessible URL route:

lib/routes structure
bash
lib/routes/
├── index.dart                # / (Home Route)
├── about.dart                # /about
├── settings.dart             # /settings
├── users/
│   ├── index.dart            # /users
│   └── [id].dart             # /users/:id (Dynamic Route)
└── (auth)/                   # Route Group (omitted from URL)
    ├── login.dart            # /login
    └── register.dart         # /register

Dynamic Routes ([id].dart)

Enclose parameter names in brackets like [id].dart. Bloom automatically parses the route parameters and passes them into your widget constructor:

lib/routes/users/[id].dart
dart
// lib/routes/users/[id].dart
import 'package:flutter/material.dart';
import 'package:bloom_framework/bloom.dart';

class UserProfileRoute extends StatelessWidget {
  final String id;
  const UserProfileRoute({super.key, required this.id});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('User #$id')),
      body: Center(
        child: Text(
          'Viewing Profile for ID: $id',
          style: const TextStyle(fontSize: 18),
        ),
      ),
    );
  }
}

Authentication & Route Guards

Guards intercept navigation attempts and perform deterministic redirects based on reactive auth signals:

lib/app/guards.dart
dart
// lib/app/guards.dart
import 'package:bloom_framework/bloom.dart';
import '../services/auth_service.dart';

class AuthGuard extends BloomRouteGuard {
  @override
  Future<String?> redirect(BuildContext context, BloomRouteState state) async {
    final auth = inject<AuthService>();
    final isLoggedIn = auth.isAuthenticated.value;
    final isAuthRoute = state.matchedLocation.startsWith('/login') || 
                        state.matchedLocation.startsWith('/register');

    if (!isLoggedIn && !isAuthRoute) {
      return '/login?redirect=${Uri.encodeComponent(state.matchedLocation)}';
    }

    if (isLoggedIn && isAuthRoute) {
      return '/dashboard';
    }

    return null; // Allow navigation
  }
}