Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat add flutter authentication deepdive #357

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/routes/docs/tutorials/flutter-auth/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script lang="ts">
import { globToTutorial } from '$lib/utils/tutorials.js';
import { setContext } from 'svelte';

export let data;
const tutorials = globToTutorial(data);
setContext('tutorials', tutorials);
</script>

<slot />
11 changes: 11 additions & 0 deletions src/routes/docs/tutorials/flutter-auth/+layout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { LayoutLoad } from './$types';

export const load: LayoutLoad = ({ url }) => {
const tutorials = import.meta.glob('./**/*.markdoc', {
eager: true
});
return {
tutorials,
pathname: url.pathname
};
};
6 changes: 6 additions & 0 deletions src/routes/docs/tutorials/flutter-auth/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';

export const load: PageLoad = async () => {
throw redirect(303, '/docs/tutorials/flutter-auth/step-1');
};
18 changes: 18 additions & 0 deletions src/routes/docs/tutorials/flutter-auth/step-1/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
layout: tutorial
title: Authentication with Flutter
description: Add Authentication to a Flutter project using Appwrite.
step: 1
difficulty: intermediate
readtime: 20
---

Appwrite takes away your stress of building and maintaining a backend. Appwrite helps you implement authentication, databases, file storage, and respond to real-time events with **secure** APIs out of the box.
If you're a Flutter developer, examples in this guide shows you how Appwrite can help you add authentication to Flutter apps faster.

## Before you start

Even if you've never tried Appwrite, you will get an idea of what it'll feel like to build with Flutter and Appwrite.

If you're inspired and wish to follow along, make sure you've followed [Start with Flutter](https://appwrite.io/docs/quick-starts/flutter) first.
You can also choose to clone our [Getting started](https://github.com/appwrite/getting-started-projects/tree/main/flutter) examples and follow along by looking at our example code.
51 changes: 51 additions & 0 deletions src/routes/docs/tutorials/flutter-auth/step-2/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
layout: tutorial
title: Create project
description: Add Authentication to a Flutter project using Appwrite.
step: 2
---


You can create a Flutter project using the following command

```sh
flutter create my_flutter_project
```

The command will automatically create a Flutter project with the name `my_flutter_project`. You can change the name of the project by changing the name of the project in the command.

You will see the following output after the project is created.

```sh
Creating project my_flutter_project...
Resolving dependencies in my_flutter_project... (1.9s)
Got dependencies in my_flutter_project.
Wrote 129 files.

All done!
You can find general documentation for Flutter at: https://docs.flutter.dev/
Detailed API documentation is available at: https://api.flutter.dev/
If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev

In order to run your application, type:

$ cd my_flutter_project
$ flutter run

Your application code is in my_flutter_project\lib\main.dart.
```

After the prompt is finished, you can head over to the newly create project.

```sh
cd my_flutter_project
flutter run
```

## Adding Appwrite to Your Flutter App

Appwrite provides a Web SDK that can be used in your Flutter apps. You can use Appwrite by installing the Flutter pub package.

```sh
flutter pub add appwrite
```
44 changes: 44 additions & 0 deletions src/routes/docs/tutorials/flutter-auth/step-3/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
layout: tutorial
title: Initialize SDK
description: Add Authentication to a Flutter project using Appwrite.
step: 3
---
Before you can use Appwrite, you need to instanciate the Appwrite `Client` class with the project ID and endpoint.
This tells the SDK where your Appwrite project is hosted and which one to connect to.

The client is then used to initialize services like `Databases` and `Account`, so they all point to the same Appwrite project.

You can do this by instantiating the services you need in a file like `lib/config/appwrite.dart` and **exporting the instances**.

```dart
// lib/config/appwrite.dart
import 'package:appwrite/appwrite.dart';

import 'package:my_flutter_project/constants.dart' as constants;

class Appwrite {
static final Appwrite instance = Appwrite._instance();

late final Client client;

late final Account account;

Appwrite._instance() {
client = Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject(constants.appwriteProjectID);
account = Account(client);
}
}
```

`appwriteProjectID` is a variable that you can store in a different constants file.

For example, your `lib/constants.dart` file might look something similar to this.

```dart
String appwriteProjectID = "642sdddf85b440dc7e5bf";
```

You can get the value for this variable from the Appwrite console's **Settings** page.
147 changes: 147 additions & 0 deletions src/routes/docs/tutorials/flutter-auth/step-4/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
layout: tutorial
title: Check if logged in
description: Add Authentication to a Flutter project using Appwrite.
step: 4
---

Before taking a user to the login screen, we should check if they're already logged in.
With Flutter, you can use the `FutureBuilder` to check if you're logged in before your app renders using `account.get()` method.

The first step would be to create `named routes` for the login and signup screens in `lib/main.dart`:

Also create a `lib/screens` directory and create `login.dart` and `signup.dart` files in it.

```dart
// lib/main.dart
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const MyHomePage(),
routes: {
'/login': (context) => const LogInPage(),
'/signup': (context) => const SignUpPage(),
'/home': (context) => const MyHomePage(),
},
);
}
}
```

Now Using `FutureBuilder` and providing the `account.get()` method as the future, we can check if the user is logged in. If the user is logged in, we can show the welcome message, otherwise we can show the login and signup buttons.


```dart
// lib/main.dart
FutureBuilder(
future: Appwrite.instance.account.get(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Scaffold(
body: Center(
child: Text(
'Hello ${snapshot.data!.name}',
),
),
);
} else {
// Show login and signup buttons
}
},
),
```

Comple code for `lib/main.dart` should look like this:

```dart
import 'package:flutter/material.dart';

import 'config/appwrite.dart';
import 'screens/login.dart';
import 'screens/signup.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const MyHomePage(),
routes: {
'/login': (context) => const LogInPage(),
'/signup': (context) => const SignUpPage(),
'/home': (context) => const MyHomePage(),
},
);
}
}

class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});

@override
State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: Appwrite.instance.account.get(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Hello ${snapshot.data!.name}',
),
// add a logout button
ElevatedButton(
onPressed: () async {
await Appwrite.instance.account.deleteSession(
sessionId: 'current',
);
setState(() {});
},
child: const Text('Log out'),
),
],
),
),
);
} else {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/login');
},
child: const Text('Log in'),
),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: const Text('Sign up'),
),
],
),
);
}
},
),
);
}
}
```
Loading