accessibility
Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions,…
Use when setting up auth, managing auth state, implementing email/password or social sign-in, handling auth errors, or managing users.
Claude Code
$ npx -y skills add evanca/flutter-ai-rules --skill firebase-auth --agent claude-code
Codex
$ npx skills add evanca/flutter-ai-rules --skill firebase-auth -a codex -y
Cursor
$ npx skills add evanca/flutter-ai-rules --skill firebase-auth -a cursor -y
Gemini CLI
$ npx skills add evanca/flutter-ai-rules --skill firebase-auth -a gemini-cli -y
GitHub Copilot
$ npx skills add evanca/flutter-ai-rules --skill firebase-auth -a github-copilot -y
OpenCode
$ npx skills add evanca/flutter-ai-rules --skill firebase-auth -a opencode -y
Windsurf
$ npx skills add evanca/flutter-ai-rules --skill firebase-auth -a windsurf -y
name: firebase-auth description: "Use when setting up auth, managing auth state, implementing email/password or social sign-in, handling auth errors, or managing users." license: MIT
This skill defines how to correctly use Firebase Authentication in Flutter applications.
Use this skill when:
---
flutter pub add firebase_auth
import 'package:firebase_auth/firebase_auth.dart';
**Local emulator for testing:**
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
// ...
}---
Use the appropriate stream based on what you need to observe:
| Stream | Fires when | |---|---| | `authStateChanges()` | User signs in or out | | `idTokenChanges()` | ID token changes (including custom claims) | | `userChanges()` | User data changes (e.g., profile updates) |
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
});---
**Create a new account:**
try {
final credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: emailAddress,
password: password,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}**Sign in:**
try {
final credential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailAddress,
password: password,
);
} on FirebaseAuthException catch (e) {
final String error = switch (e.code) {
'invalid-email' => 'The email address is not valid.',
// Email enumeration protection (default since Sep 2023) reports
// 'invalid-credential' instead of 'user-not-found' / 'wrong-password';
// older native SDKs report 'invalid-login-credentials'. Handle all four so
// the app works with the setting on or off.
'invalid-credential' ||
'invalid-login-credentials' ||
'user-not-found' ||
'wrong-password' =>
'The email address or password is incorrect.',
'user-disabled' => 'This account has been disabled.',
'too-many-requests' ||
'network-request-failed' =>
'Something went wrong. Try again later.',
// Always keep a default branch — codes differ by platform and SDK version
// (for example Windows reports 'unknown-error' for a wrong password).
_ => 'Sign-in failed (${e.code}).',
};
print(error);
}**Share authentication state between Apple apps:**
On Apple platforms, share auth state between apps in the same developer account by storing it in a shared Keychain access group. Enable the Keychain Sharing capability for each app with the same access group, then configure Firebase Auth with the fully qualified access group:
await FirebaseAuth.instance.setSettings( userAccessGroup: 'TEAMID.com.example.group1', );
Switching from the default Keychain to a shared access group signs out the existing user unless migrated. Pass `migrateCurrentUser: true` (requires a non-null `userAccessGroup`) to preserve the current session, including an anonymous one — safe to call at app startup before any other Auth call, since it reads the existing session straight from the Keychain before Auth restores it. Migration can overwrite a user already stored in the destination access group.
---
**Google Sign-In (native platforms):**
Future<UserCredential> signInWithGoogle() async {
final GoogleSignInAccount? googleUser = await GoogleSignIn.instance.authenticate();
final GoogleSignInAuthentication googleAuth = googleUser.authentication;
final credential = GoogleAuthProvider.credential(idToken: googleAuth.idToken);
return await FirebaseAuth.instance.signInWithCredential(credential);
}**Google Sign-In (web):**
Future<UserCredential> signInWithGoogle() async {
GoogleAuthProvider googleProvider = GoogleAuthProvider();
googleProvider.addScope('https://www.googleapis.com/auth/contacts.readonly');
googleProvider.setCustomParameters({'login_hint': 'user@example.com'});
r36 Flutter and Dart skills your coding agent loads by itself, sourced only from official documentation. A skill is a folder with a SKILL.md file.
Use when working on accessibility, a11y, WCAG, ARIA, screen readers, keyboard nav, focus order, contrast, alt text, captions,…
Use when creating a feature, designing folder structure, adding repositories/services/view models, wiring dependency injection,…
Use when creating a Cubit or Bloc, modeling state with sealed classes or status enums, wiring…
Use when asked to review a PR, MR, branch, or diff, audit changed files, or check code quality.
Use when writing switch statements, refactoring if-else chains, creating data classes, choosing records vs classes, destructuring…
Use when building AI agents in Dart, implementing Genkit flows or tools, integrating LLMs into Dart or Flutter applications, or…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.