🎉 Nylo v7 āļĄāļēāđāļĨāđ‰āļ§! āļ”āļđāļŠāļīāđˆāļ‡āđƒāļŦāļĄāđˆ →

Nylo Website logo

Flutter
āđ„āļĄāđ‚āļ„āļĢāđ€āļŸāļĢāļĄāđ€āļ§āļīāļĢāđŒāļ
āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ›āļŠāļĄāļąāļĒāđƒāļŦāļĄāđˆ

āļĢāļēāļāļāļēāļ™āļ—āļĩāđˆāđāļ‚āđ‡āļ‡āđāļāļĢāđˆāļ‡āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļŠāļĢāđ‰āļēāļ‡āđāļ­āļ› Flutter āļĢāļ°āļšāļšāđ€āļŠāđ‰āļ™āļ—āļēāļ‡ āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāļŠāļ–āļēāļ™āļ° āđ€āļ„āļĢāļ·āļ­āļ‚āđˆāļēāļĒ āđāļĨāļ°āļ­āļ·āđˆāļ™āđ† āļ­āļĩāļāļĄāļēāļāļĄāļēāļĒ â€” āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āđƒāļ™āđāļžāđ‡āļāđ€āļāļˆāđ€āļ”āļĩāļĒāļ§āļ—āļĩāđˆāļŠāļ§āļĒāļ‡āļēāļĄ

āđ€āļĢāļīāđˆāļĄāļ•āđ‰āļ™āđƒāļŠāđ‰āļ‡āļēāļ™
āļŠāļģāļĢāļ§āļˆ
āļ„āļļāļ“āļŠāļĄāļšāļąāļ•āļī

āļ—āļļāļāļŠāļīāđˆāļ‡āļ—āļĩāđˆāļ„āļļāļ“āļ•āđ‰āļ­āļ‡āļāļēāļĢāļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļŠāļĢāđ‰āļēāļ‡

Nylo āļĄāļ­āļšāđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĄāļ·āļ­āļ—āļąāđ‰āļ‡āļŦāļĄāļ”āļ—āļĩāđˆāļ„āļļāļ“āļ•āđ‰āļ­āļ‡āļāļēāļĢāđ€āļžāļ·āđˆāļ­āļŠāļĢāđ‰āļēāļ‡āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™ Flutter āļ—āļĩāđˆāļžāļĢāđ‰āļ­āļĄāđƒāļŠāđ‰āļ‡āļēāļ™āļˆāļĢāļīāļ‡āļ­āļĒāđˆāļēāļ‡āļĄāļąāđˆāļ™āđƒāļˆ

āļĢāļ°āļšāļšāđ€āļŠāđ‰āļ™āļ—āļēāļ‡

āļĢāļ°āļšāļšāđ€āļŠāđ‰āļ™āļ—āļēāļ‡āđāļšāļšāļ›āļĢāļ°āļāļēāļĻāļ—āļĩāđˆāđ€āļĢāļĩāļĒāļšāļ‡āđˆāļēāļĒ āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāļ›āđ‰āļ­āļ‡āļāļąāļ™āđ€āļŠāđ‰āļ™āļ—āļēāļ‡ āļžāļēāļĢāļēāļĄāļīāđ€āļ•āļ­āļĢāđŒ āđāļĨāļ°āļĢāļ­āļ‡āļĢāļąāļš Deep Linking

āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāļŠāļ–āļēāļ™āļ°

āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāļŠāļ–āļēāļ™āļ°āđāļšāļš Reactive āđƒāļ™āļ•āļąāļ§ āļžāļĢāđ‰āļ­āļĄāļ„āļ­āļ™āđ‚āļ—āļĢāļĨāđ€āļĨāļ­āļĢāđŒāđāļĨāļ°āļāļēāļĢāļ„āļ‡āļŠāļ–āļēāļ™āļ°āļ—āļĩāđˆāļ‡āđˆāļēāļĒāļ”āļēāļĒ

āđ€āļ„āļĢāļ·āļ­āļ‚āđˆāļēāļĒ

āļ„āļĨāļēāļŠāļšāļĢāļīāļāļēāļĢ API āļ—āļĩāđˆāļŠāļ§āļĒāļ‡āļēāļĄ āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāđāļ›āļĨāļ‡āđ‚āļĄāđ€āļ”āļĨāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļīāđāļĨāļ°āļ•āļąāļ§āļ”āļąāļāļˆāļąāļš

āļŸāļ­āļĢāđŒāļĄ

āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāļŸāļ­āļĢāđŒāļĄāļ—āļĩāđˆāļ—āļĢāļ‡āļžāļĨāļąāļ‡ āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāļ•āļĢāļ§āļˆāļŠāļ­āļš āļāļēāļĢāđāļ›āļĨāļ‡āļŠāļ™āļīāļ”āļ‚āđ‰āļ­āļĄāļđāļĨ āđāļĨāļ°āļāļēāļĢāļœāļđāļāļ‚āđ‰āļ­āļĄāļđāļĨāļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī

āļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™

āļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āļ—āļĩāđˆāļ›āļĨāļ­āļ”āļ āļąāļĒ āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāļ›āđ‰āļ­āļ‡āļāļąāļ™āđ€āļŠāđ‰āļ™āļ—āļēāļ‡ āļāļēāļĢāļˆāļąāļ”āđ€āļāđ‡āļšāđ‚āļ—āđ€āļ„āđ‡āļ™ āđāļĨāļ°āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāđ€āļ‹āļŠāļŠāļąāļ™

Metro CLI

āļŠāļĢāđ‰āļēāļ‡āļŦāļ™āđ‰āļē āđ‚āļĄāđ€āļ”āļĨ āļ„āļ­āļ™āđ‚āļ—āļĢāļĨāđ€āļĨāļ­āļĢāđŒ āđāļĨāļ°āļ­āļ·āđˆāļ™āđ† āļ”āđ‰āļ§āļĒāļ„āļģāļŠāļąāđˆāļ‡ CLI āļ—āļĩāđˆāļ—āļĢāļ‡āļžāļĨāļąāļ‡

Metro CLI

āļŠāļĢāđ‰āļēāļ‡āļ—āļļāļāļ­āļĒāđˆāļēāļ‡āļˆāļēāļāđ€āļ—āļ­āļĢāđŒāļĄāļīāļ™āļąāļĨ

Metro āļ„āļ·āļ­āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĄāļ·āļ­ CLI āļ‚āļ­āļ‡ Nylo āļ—āļĩāđˆāļŠāđˆāļ§āļĒāđƒāļŦāđ‰āļ„āļļāļ“āļŠāļĢāđ‰āļēāļ‡āđ‚āļ„āļĢāļ‡āļŠāļĢāđ‰āļēāļ‡āļŦāļ™āđ‰āļē āđ‚āļĄāđ€āļ”āļĨ āļ„āļ­āļ™āđ‚āļ—āļĢāļĨāđ€āļĨāļ­āļĢāđŒ āļ§āļīāļ”āđ€āļˆāđ‡āļ• āđāļĨāļ°āļ­āļ·āđˆāļ™āđ† āļ”āđ‰āļ§āļĒāļ„āļģāļŠāļąāđˆāļ‡āđ€āļ”āļĩāļĒāļ§

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄāđ€āļāļĩāđˆāļĒāļ§āļāļąāļš Metro
metro make:page HomePage
# Creates a new page called HomePage

metro make:api_service User
# Creates a new API Service called UserApiService

metro make:model User
# Creates a new model called User

metro make:stateful_widget FavouriteWidget
# Creates a new stateful widget called FavouriteWidget
class ApiService extends NyApiService {
  @override
  String get baseUrl => "https://api.example.com/v1";

  Future<List<Post>> posts() async {
    return await network(
      request: (request) => request.get("/posts"),
    );
  }
}

// Usage in your page
final posts = await api<ApiService>((request) => request.posts());
āđ€āļ„āļĢāļ·āļ­āļ‚āđˆāļēāļĒ

āļāļēāļĢāđ€āļŠāļ·āđˆāļ­āļĄāļ•āđˆāļ­ API āļ­āļĒāđˆāļēāļ‡āļ‡āđˆāļēāļĒāļ”āļēāļĒ

āđ€āļ‚āļĩāļĒāļ™āļšāļĢāļīāļāļēāļĢ API āļ—āļĩāđˆāļŠāļ°āļ­āļēāļ”āđāļĨāļ°āļ”āļđāđāļĨāļĢāļąāļāļĐāļēāļ‡āđˆāļēāļĒ āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāđāļĒāļāļ§āļīāđ€āļ„āļĢāļēāļ°āļŦāđŒ JSON āļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāļ‚āđ‰āļ­āļœāļīāļ”āļžāļĨāļēāļ” āđāļĨāļ°āļ•āļąāļ§āļ”āļąāļāļˆāļąāļšāļ„āļģāļ‚āļ­

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄāđ€āļāļĩāđˆāļĒāļ§āļāļąāļšāđ€āļ„āļĢāļ·āļ­āļ‚āđˆāļēāļĒ
āļŠāļģāļĢāļ§āļˆ

āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĄāļ·āļ­āļ—āļĩāđˆāļ—āļĢāļ‡āļžāļĨāļąāļ‡āļŠāļģāļŦāļĢāļąāļšāļāļēāļĢāļŠāļĢāđ‰āļēāļ‡

āļ—āļļāļāļŠāļīāđˆāļ‡āļ—āļĩāđˆāļ„āļļāļ“āļ•āđ‰āļ­āļ‡āļāļēāļĢāļŠāļģāļŦāļĢāļąāļšāļŠāļĢāđ‰āļēāļ‡āđāļ­āļ› Flutter āļ–āļąāļ”āđ„āļ›āļ‚āļ­āļ‡āļ„āļļāļ“

routes/router.dart
appRouter() => nyRoutes((router) {
    router.add(HomePage.path).initialRoute();

    router.add(DiscoverPage.path);

    router.add(LoginPage.path, 
        transitionType: TransitionType.bottomToTop());

    router.add(ProfilePage.path,
        routeGuard: [
            AuthGuard()
        ]
    );
});

āļŠāļĢāđ‰āļēāļ‡āđ€āļŠāđ‰āļ™āļ—āļēāļ‡ āļ­āļīāļ™āđ€āļ—āļ­āļĢāđŒāđ€āļŸāļ‹ āđāļĨāļ°āļŦāļ™āđ‰āļē UI āļ—āļĩāđˆāļ‹āļąāļšāļ‹āđ‰āļ­āļ™āļŠāļģāļŦāļĢāļąāļšāđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™ Flutter āļ‚āļ­āļ‡āļ„āļļāļ“

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 1

āļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āļœāļđāđ‰āđƒāļŠāđ‰

String userToken = "eyJhbG123...";

await Auth.authenticate(data: {"token": userToken});
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 2

āļ•āļ­āļ™āļ™āļĩāđ‰ āđ€āļĄāļ·āđˆāļ­āļœāļđāđ‰āđƒāļŠāđ‰āļ‚āļ­āļ‡āļ„āļļāļ“āđ€āļ›āļīāļ”āđāļ­āļ› āļžāļ§āļāđ€āļ‚āļēāļˆāļ°āđ„āļ”āđ‰āļĢāļąāļšāļāļēāļĢāļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āđāļĨāđ‰āļ§

final userData = Auth.data();
// {"token": "eyJhbG123..."}

bool isAuthenticated = await Auth.isAuthenticated();
// true
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 3

āļŦāļēāļāļ„āļļāļ“āđ„āļ”āđ‰āļ•āļąāđ‰āļ‡āļ„āđˆāļē authenticatedRoute āđƒāļ™āđ€āļĢāļēāđ€āļ•āļ­āļĢāđŒāļ‚āļ­āļ‡āļ„āļļāļ“ āļŦāļ™āđ‰āļēāļ™āļĩāđ‰āļˆāļ°āļ–āļđāļāđāļŠāļ”āļ‡āđ€āļĄāļ·āđˆāļ­āļœāļđāđ‰āđƒāļŠāđ‰āđ€āļ›āļīāļ”āđāļ­āļ›āļ­āļĩāļāļ„āļĢāļąāđ‰āļ‡

routes/router.dart
appRouter() => nyRoutes((router) {
    ...
    router.add(LandingPage.path).initialRoute();

    router.add(DashboardPage.path).authenticatedRoute();
    // overrides the initial route when a user is authenticated

āļ­āļ­āļāļˆāļēāļāļĢāļ°āļšāļšāļœāļđāđ‰āđƒāļŠāđ‰

await Auth.logout();

āļĒāļ·āļ™āļĒāļąāļ™āļ•āļąāļ§āļ•āļ™āļœāļđāđ‰āđƒāļŠāđ‰āđƒāļ™āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™ Flutter āļ‚āļ­āļ‡āļ„āļļāļ“

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 1

āļŠāļĢāđ‰āļēāļ‡āļŸāļ­āļĢāđŒāļĄ

terminal
metro make:form RegisterForm
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 2

āđāļāđ‰āđ„āļ‚āļŸāļ­āļĢāđŒāļĄāļ‚āļ­āļ‡āļ„āļļāļ“

app/forms/register_form.dart
class RegisterForm extends NyFormWidget {

    RegisterForm({super.key, super.submitButton, super.onSubmit, super.onFailure});

    // Add your fields here
    @override
    fields() => [
        Field.capitalizeWords("name",
            label: "Name",
            validator: FormValidator.notEmpty(),
        ),
        Field.email("email_address",
            label: "Email",
            validator: FormValidator.email()
        ),
        Field.password("password",
            label: "Password",
            validator: FormValidator.password(),
        ),
    ];

    static NyFormActions get actions => const NyFormActions("RegisterForm");
}
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 3

āđƒāļŠāđ‰āļŸāļ­āļĢāđŒāļĄāļ‚āļ­āļ‡āļ„āļļāļ“āđƒāļ™āļ§āļīāļ”āđ€āļˆāđ‡āļ•

register_page.dart
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: RegisterForm(
      submitButton: Button.primary(text: "Submit"),
      onSubmit: (data) {
        printInfo(data);
      },
    ),
  );
}

āļˆāļąāļ”āļāļēāļĢ āļ•āļĢāļ§āļˆāļŠāļ­āļš āđāļĨāļ°āļŠāđˆāļ‡āļ‚āđ‰āļ­āļĄāļđāļĨāļ—āļąāđ‰āļ‡āļŦāļĄāļ”āđƒāļ™āļ—āļĩāđˆāđ€āļ”āļĩāļĒāļ§āļ”āđ‰āļ§āļĒ Nylo Forms

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 1

āļŠāļĢāđ‰āļēāļ‡āļ§āļīāļ”āđ€āļˆāđ‡āļ•āļ—āļĩāđˆāļˆāļąāļ”āļāļēāļĢāļŠāļ–āļēāļ™āļ°

terminal
metro make:stateful_widget CartIcon
resources/cart_icon_widget.dart
class _CartIconState extends NyState<CartIcon> {
  ...

  @override
  Map<String, Function> get stateActions => {
    "clear_cart": () {
      _items = 0;
    },
    ...
  };

  @override
  Widget view(BuildContext context) {
    return Container(child: Text("Items in cart: ${_items}"));
  }
}
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 2

Use CartIcon.action("clear_cart")

another widget
Button.primary(text: "Add to cart",
    onPressed: () {
      CartIcon.action("clear_cart");
    }
)

āļāļēāļĢāļˆāļąāļ”āļāļēāļĢāļŠāļ–āļēāļ™āļ°āļ—āļĩāđˆāļ—āļĢāļ‡āļžāļĨāļąāļ‡āļŠāļģāļŦāļĢāļąāļšāļ§āļīāļ”āđ€āļˆāđ‡āļ•āđƒāļ™āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™ Flutter āļ‚āļ­āļ‡āļ„āļļāļ“

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 1

āļŠāļĢāđ‰āļēāļ‡āđ€āļŦāļ•āļļāļāļēāļĢāļ“āđŒāļ‚āļ­āļ‡āļ„āļļāļ“

terminal
metro make:event Logout
app/events/logout_event.dart
class LogoutEvent implements NyEvent {
    @override
    final listeners = {
        DefaultListener: DefaultListener(),
    };
}

class DefaultListener extends NyListener {
    @override
    handle(dynamic event) async {

        // logout user
        await Auth.logout();

        // redirect to home page
        routeTo(HomePage.path,
            navigationType: NavigationType.pushAndForgetAll
        );
    }
}
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 2

āļŠāđˆāļ‡āđ€āļŦāļ•āļļāļāļēāļĢāļ“āđŒ

MaterialButton(child: Text("Logout"),
    onPressed: () {
        event<LogoutEvent>();
    },
)

āļŠāđˆāļ‡āđ€āļŦāļ•āļļāļāļēāļĢāļ“āđŒāđāļĨāļ°āļĢāļąāļšāļŸāļąāļ‡āđ€āļŦāļ•āļļāļāļēāļĢāļ“āđŒāđƒāļ™āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™āļ‚āļ­āļ‡āļ„āļļāļ“

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ

āļāļģāļŦāļ™āļ”āđ€āļ§āļĨāļēāđƒāļŦāđ‰āļ‡āļēāļ™āļ—āļģāļ‡āļēāļ™āļ„āļĢāļąāđ‰āļ‡āđ€āļ”āļĩāļĒāļ§

Nylo.scheduleOnce("onboarding_info", () {
    print("Perform code here to run once");
});

āļāļģāļŦāļ™āļ”āđ€āļ§āļĨāļēāđƒāļŦāđ‰āļ‡āļēāļ™āļ—āļģāļ‡āļēāļ™āļ„āļĢāļąāđ‰āļ‡āđ€āļ”āļĩāļĒāļ§āļŦāļĨāļąāļ‡āļˆāļēāļāļ§āļąāļ™āļ—āļĩāđˆāļĢāļ°āļšāļļ

Nylo.scheduleOnceAfterDate("app_review_rating", () {
    print("Perform code to run once after DateTime(2025, 04, 10)");
}, date: DateTime(2025, 04, 10));

āļāļģāļŦāļ™āļ”āđ€āļ§āļĨāļēāđƒāļŦāđ‰āļ‡āļēāļ™āļ—āļģāļ‡āļēāļ™āļ§āļąāļ™āļĨāļ°āļ„āļĢāļąāđ‰āļ‡

Nylo.scheduleOnceDaily("free_daily_coins", () {
    print("Perform code to run once daily");
});

āļāļģāļŦāļ™āļ”āđ€āļ§āļĨāļēāđƒāļŦāđ‰āļ‡āļēāļ™āļ—āļģāļ‡āļēāļ™āļ„āļĢāļąāđ‰āļ‡āđ€āļ”āļĩāļĒāļ§āļŦāļĢāļ·āļ­āļĢāļēāļĒāļ§āļąāļ™āđƒāļ™āđāļ­āļ›āļžāļĨāļīāđ€āļ„āļŠāļąāļ™ Flutter āļ‚āļ­āļ‡āļ„āļļāļ“

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 1

āļŠāļĢāđ‰āļēāļ‡āļšāļĢāļīāļāļēāļĢ API

terminal
metro make:api_service User
app/networking/user_api_service.dart
class UserApiService extends NyApiService {
    @override
    String get baseUrl => getEnv("API_BASE_URL");

    Future<User?> fetchUser(int id) async {
        return await get<User>(
            "/users/$id",
            queryParameters: {"include": "profile"},
        );
    }

    Future<User?> createUser(Map<String, dynamic> data) async {
        return await post<User>("/users", data: data);
    }
}
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 2

āđ€āļĢāļĩāļĒāļāđƒāļŠāđ‰ API āļˆāļēāļāļŦāļ™āđ‰āļēāļ‚āļ­āļ‡āļ„āļļāļ“

User? user = await api<UserApiService>(
    (request) => request.fetchUser(1),
);

āļšāļĢāļīāļāļēāļĢ API āļ—āļĩāđˆāļŠāļ§āļĒāļ‡āļēāļĄ āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāđāļĒāļāļ§āļīāđ€āļ„āļĢāļēāļ°āļŦāđŒ JSON āļ­āļąāļ•āđ‚āļ™āļĄāļąāļ•āļī āđāļ„āļŠ āđāļĨāļ°āļ•āļąāļ§āļ”āļąāļāļˆāļąāļš

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 1

āļšāļąāļ™āļ—āļķāļāļ‚āđ‰āļ­āļĄāļđāļĨāļ­āļĒāđˆāļēāļ‡āļ›āļĨāļ­āļ”āļ āļąāļĒ

saving_data.dart
// Save values to secure storage
await NyStorage.save("coins", 100);
await NyStorage.save("username", "Anthony");
await NyStorage.save("isPremium", true);

// Save with TTL (auto-expires)
await NyStorage.save("session", "abc123",
    expiry: Duration(hours: 1),
);
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 2

āļ­āđˆāļēāļ™āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāđāļ›āļĨāļ‡āļŠāļ™āļīāļ”āļ‚āđ‰āļ­āļĄāļđāļĨ

// Automatic type casting
String? username = await NyStorage.read("username");
int? coins = await NyStorage.read<int>("coins");
bool? isPremium = await NyStorage.read<bool>("isPremium");

// Delete a value
await NyStorage.delete("coins");

āļžāļ·āđ‰āļ™āļ—āļĩāđˆāļˆāļąāļ”āđ€āļāđ‡āļšāļ āļēāļĒāđƒāļ™āļ—āļĩāđˆāļ›āļĨāļ­āļ”āļ āļąāļĒ āļžāļĢāđ‰āļ­āļĄāļāļēāļĢāđāļ›āļĨāļ‡āļŠāļ™āļīāļ”āļ‚āđ‰āļ­āļĄāļđāļĨ āļāļēāļĢāļŦāļĄāļ”āļ­āļēāļĒāļļ TTL āđāļĨāļ°āļ„āļ­āļĨāđ€āļĨāļāļŠāļąāļ™

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 1

āđ€āļžāļīāđˆāļĄāđ„āļŸāļĨāđŒāļ āļēāļĐāļēāļ‚āļ­āļ‡āļ„āļļāļ“

lang/en.json
{
    "welcome": "Welcome",
    "greeting": "Hello {{name}}",
    "navigation": {
        "home": "Home",
        "profile": "Profile"
    }
}
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 2

āđāļ›āļĨāļ‚āđ‰āļ­āļ„āļ§āļēāļĄāđƒāļ™āļ§āļīāļ”āđ€āļˆāđ‡āļ•āļ‚āļ­āļ‡āļ„āļļāļ“

// Simple translation
Text("welcome".tr())  // "Welcome"

// With arguments
Text("greeting".tr(arguments: {"name": "Anthony"}))
// "Hello Anthony"

// Nested keys
Text("navigation.home".tr())  // "Home"

āļĢāļ­āļ‡āļĢāļąāļšāļŦāļĨāļēāļĒāļ āļēāļĐāļēāļ”āđ‰āļ§āļĒāđ„āļŸāļĨāđŒ JSON āļ­āļēāļĢāđŒāļāļīāļ§āđ€āļĄāļ™āļ•āđŒ āđāļĨāļ° RTL

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 1

āļŠāļĢāđ‰āļēāļ‡āļĻāļđāļ™āļĒāđŒāļāļĨāļēāļ‡āļāļēāļĢāļ™āļģāļ—āļēāļ‡

terminal
metro make:navigation_hub base
resources/pages/base_navigation_hub.dart
class _BaseNavigationHubState extends NavigationHub<BaseNavigationHub> {

    NavigationHubLayout? layout = NavigationHubLayout.bottomNav();

    @override
    bool get maintainState => true;

    _BaseNavigationHubState() : super(() async {
        return {
            0: NavigationTab(
                title: "Home",
                page: HomeTab(),
                icon: Icon(Icons.home),
            ),
            1: NavigationTab(
                title: "Settings",
                page: SettingsTab(),
                icon: Icon(Icons.settings),
            ),
        };
    });
}
āļ‚āļąāđ‰āļ™āļ•āļ­āļ™āļ—āļĩāđˆ 2

āļŠāļĨāļąāļšāđ€āļĨāļĒāđŒāđ€āļ­āļēāļ•āđŒāđ„āļ”āđ‰āļ‡āđˆāļēāļĒāđ†

// Bottom navigation
NavigationHubLayout.bottomNav()

// Top navigation
NavigationHubLayout.topNav()

// Journey / wizard flow
NavigationHubLayout.journey()

āļŠāļĢāđ‰āļēāļ‡āđāļ–āļšāļ™āļģāļ—āļēāļ‡āļ”āđ‰āļēāļ™āļĨāđˆāļēāļ‡ āđāļ–āļšāļ™āļģāļ—āļēāļ‡āļ”āđ‰āļēāļ™āļšāļ™ āļŦāļĢāļ·āļ­āđ‚āļŸāļĨāļ§āđŒāļāļēāļĢāđ€āļ”āļīāļ™āļ—āļēāļ‡ āļžāļĢāđ‰āļ­āļĄāļĢāļąāļāļĐāļēāļŠāļ–āļēāļ™āļ°

āđ€āļĢāļĩāļĒāļ™āļĢāļđāđ‰āđ€āļžāļīāđˆāļĄāđ€āļ•āļīāļĄ

āđ€āļ›āđ‡āļ™āļ—āļĩāđˆāļŠāļ·āđˆāļ™āļŠāļ­āļšāļ‚āļ­āļ‡āļŠāļļāļĄāļŠāļ™

āļŠāļīāđˆāļ‡āļ—āļĩāđˆāļ™āļąāļāļžāļąāļ’āļ™āļēāļžāļđāļ”āļ–āļķāļ‡ Nylo Website

āđ€āļ‚āđ‰āļēāļĢāđˆāļ§āļĄāļāļēāļĢāļŠāļ™āļ—āļ™āļē

I'm new to Dart and new to your framework (which I love)

Peter Senior Director of Heroku Global

I wanted to thank you guys for the great job you are doing.

@youssefKadaouiAbbassi

Just to say that I am in love with @nylo_dev's website!! Definitely gonna explore it!

@esfoliante_txt

Really love the concept of this framework

@Chrisvidal

Nylo is the best framework for flutter, which makes developing easy

@higakijin

This is incredible. Very well done!

FireflyDaniel

Very nice Framework! Thank you so much!

@ChaoChao2509

I just discovered this framework and I'm very impressed. Thank you

@lepresk

Great work on Nylo

@dylandamsma

This is by far the best framework out there. Amazing quality and features. Thanks so much.

@2kulfi

It's interesting and very amazing. It makes the work more easier and less time consuming. Great work. Thank you

darkreader01

Salut. Je viens juste de dÃĐcouvrir votre outils et je le trouve vraiment super. Une belle dÃĐcouverte pour moi 👌ðŸĪŒ

ojean-01