From 9364d43aefad18086974d8d5173f43623d9344f7 Mon Sep 17 00:00:00 2001
From: Simon Lightfoot
Date: Tue, 20 Jan 2026 15:00:17 +0000
Subject: [PATCH 01/27] feat: docs site
---
.github/workflows/deploy-docs.yml | 63 +++
README.md | 164 +++++-
docs/.gitignore | 8 +
docs/CONTRIBUTING.md | 279 ++++++++++
docs/DEPLOYMENT.md | 228 +++++++++
docs/Gemfile | 35 ++
docs/README.md | 166 ++++++
docs/_config.yml | 78 +++
docs/_config_production.yml | 7 +
docs/_sass/color_schemes/clerk.scss | 56 ++
docs/_sass/custom/custom.scss | 167 ++++++
docs/_sass/custom/syntax-highlighting.scss | 159 ++++++
docs/api/_index.md | 40 ++
docs/api/widgets.md | 304 +++++++++++
docs/assets/images/clerk-logo.svg | 7 +
docs/getting-started.md | 133 +++++
docs/getting-started/quickstart-dart.md | 261 ++++++++++
docs/getting-started/quickstart-flutter.md | 390 ++++++++++++++
docs/guides/_index.md | 43 ++
docs/guides/authentication.md | 370 ++++++++++++++
docs/guides/backend-integration.md | 567 +++++++++++++++++++++
docs/guides/customization.md | 461 +++++++++++++++++
docs/guides/error-handling.md | 481 +++++++++++++++++
docs/guides/organizations.md | 411 +++++++++++++++
docs/guides/session-tokens.md | 331 ++++++++++++
docs/guides/user-management.md | 456 +++++++++++++++++
docs/index.md | 96 ++++
docs/packages/_index.md | 64 +++
docs/packages/clerk-auth.md | 354 +++++++++++++
docs/packages/clerk-flutter.md | 434 ++++++++++++++++
packages/clerk_auth/README.md | 31 +-
packages/clerk_flutter/README.md | 27 +
32 files changed, 6665 insertions(+), 6 deletions(-)
create mode 100644 .github/workflows/deploy-docs.yml
create mode 100644 docs/.gitignore
create mode 100644 docs/CONTRIBUTING.md
create mode 100644 docs/DEPLOYMENT.md
create mode 100644 docs/Gemfile
create mode 100644 docs/README.md
create mode 100644 docs/_config.yml
create mode 100644 docs/_config_production.yml
create mode 100644 docs/_sass/color_schemes/clerk.scss
create mode 100644 docs/_sass/custom/custom.scss
create mode 100644 docs/_sass/custom/syntax-highlighting.scss
create mode 100644 docs/api/_index.md
create mode 100644 docs/api/widgets.md
create mode 100644 docs/assets/images/clerk-logo.svg
create mode 100644 docs/getting-started.md
create mode 100644 docs/getting-started/quickstart-dart.md
create mode 100644 docs/getting-started/quickstart-flutter.md
create mode 100644 docs/guides/_index.md
create mode 100644 docs/guides/authentication.md
create mode 100644 docs/guides/backend-integration.md
create mode 100644 docs/guides/customization.md
create mode 100644 docs/guides/error-handling.md
create mode 100644 docs/guides/organizations.md
create mode 100644 docs/guides/session-tokens.md
create mode 100644 docs/guides/user-management.md
create mode 100644 docs/index.md
create mode 100644 docs/packages/_index.md
create mode 100644 docs/packages/clerk-auth.md
create mode 100644 docs/packages/clerk-flutter.md
diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml
new file mode 100644
index 00000000..cb1d469e
--- /dev/null
+++ b/.github/workflows/deploy-docs.yml
@@ -0,0 +1,63 @@
+name: Deploy Documentation to GitHub Pages
+
+on:
+ push:
+ branches:
+ - main
+ - 'feat/341-docs'
+ paths:
+ - 'docs/**'
+ - '.github/workflows/deploy-docs.yml'
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: '3.1'
+ bundler-cache: true
+ working-directory: docs
+
+ - name: Setup Pages
+ id: pages
+ uses: actions/configure-pages@v4
+
+ - name: Build with Jekyll
+ working-directory: docs
+ run: |
+ bundle install
+ bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" --config _config.yml,_config_production.yml
+ env:
+ JEKYLL_ENV: production
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: docs/_site
+
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
+
diff --git a/README.md b/README.md
index 99e6944f..407045a2 100644
--- a/README.md
+++ b/README.md
@@ -8,16 +8,172 @@
+
+
+[](https://pub.dev/packages/clerk_flutter)
+[](https://pub.dev/packages/clerk_auth)
+[](https://discord.com/invite/b5rXHjAg7A)
+[](https://clerk.com/docs)
+
+
# Clerk Dart and Flutter SDKs
-The official [Clerk](https://clerk.com) Flutter/Dart client library.
+The official [Clerk](https://clerk.com) Dart and Flutter SDKs for authentication and user management.
+
+**Clerk helps developers build user management. We provide streamlined user experiences for your users to sign up, sign in, and manage their profiles.**
+
+> ### ⚠️ Beta Notice
+> These SDKs are currently in Beta. Breaking changes should be expected until the first stable release (1.0.0).
+
+---
+
+## 📚 Documentation
+
+**[View Full Documentation →](https://clerk.github.io/clerk-sdk-flutter/)**
+
+Our comprehensive documentation includes:
+
+- 🚀 [Getting Started Guides](https://clerk.github.io/clerk-sdk-flutter/getting-started)
+- 📖 [API Reference](https://clerk.github.io/clerk-sdk-flutter/packages/clerk-auth)
+- 🎯 [Authentication Flows](https://clerk.github.io/clerk-sdk-flutter/guides/authentication)
+- 👤 [User Management](https://clerk.github.io/clerk-sdk-flutter/guides/user-management)
+- 🎨 [Customization](https://clerk.github.io/clerk-sdk-flutter/guides/customization)
+
+---
+
+## 📦 Packages
+
+### [clerk_auth](./packages/clerk_auth) - Dart SDK
+
+Pure Dart SDK for backend and CLI applications.
+
+[](https://pub.dev/packages/clerk_auth)
+[](https://pub.dev/packages/clerk_auth/score)
+
+```yaml
+dependencies:
+ clerk_auth: ^0.0.13-beta
+```
+
+**[View clerk_auth Documentation →](https://clerk.github.io/clerk-sdk-flutter/packages/clerk-auth)**
+
+### [clerk_flutter](./packages/clerk_flutter) - Flutter SDK
+
+Flutter SDK with pre-built UI components for iOS, Android, Web, and Desktop.
+
+[](https://pub.dev/packages/clerk_flutter)
+[](https://pub.dev/packages/clerk_flutter/score)
+
+```yaml
+dependencies:
+ clerk_flutter: ^0.0.13-beta
+```
+
+**[View clerk_flutter Documentation →](https://clerk.github.io/clerk-sdk-flutter/packages/clerk-flutter)**
+---
-* [clerk_auth](./packages/clerk_auth): Dart SDK
-* [clerk_flutter](./packages/clerk_flutter): Flutter SDK
+## 🚀 Quick Start
+### Dart (clerk_auth)
-### License
+```dart
+import 'dart:io';
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future main() async {
+ final auth = Auth(
+ config: AuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ ),
+ );
+
+ await auth.initialize();
+
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'password',
+ );
+
+ print('Signed in as ${auth.user?.emailAddress}');
+}
+```
+
+**[View Dart Quickstart →](https://clerk.github.io/clerk-sdk-flutter/getting-started/quickstart-dart)**
+
+### Flutter (clerk_flutter)
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+void main() => runApp(const MyApp());
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ ),
+ child: MaterialApp(
+ home: Scaffold(
+ body: ClerkAuthBuilder(
+ signedInBuilder: (context, authState) {
+ return Center(
+ child: ClerkUserButton(showName: true),
+ );
+ },
+ signedOutBuilder: (context, authState) {
+ return const Center(
+ child: ClerkAuthentication(),
+ );
+ },
+ ),
+ ),
+ ),
+ );
+ }
+}
+```
+
+**[View Flutter Quickstart →](https://clerk.github.io/clerk-sdk-flutter/getting-started/quickstart-flutter)**
+
+---
+
+## ✨ Features
+
+- 🔐 **Complete Authentication** - Email, phone, OAuth, passwordless, and MFA
+- 👤 **User Management** - Pre-built UI components and headless APIs
+- 🏢 **Organizations** - Multi-tenant support with RBAC
+- 🎨 **Customizable UI** - Themeable components that match your brand
+- 📱 **Cross-Platform** - iOS, Android, Web, Windows, macOS, Linux
+- 🚀 **Production Ready** - Battle-tested infrastructure
+
+---
+
+## 🤝 Community & Support
+
+- 💬 [Discord Community](https://clerk.com/discord) - Chat with the community and Clerk team
+- 📖 [Main Clerk Docs](https://clerk.com/docs) - Comprehensive guides and references
+- 🐛 [GitHub Issues](https://github.com/clerk/clerk-sdk-flutter/issues) - Report bugs and request features
+- 🐦 [Twitter](https://twitter.com/ClerkDev) - Latest updates and announcements
+
+---
+
+## 📄 License
These SDKs are licensed under the MIT license found in the [LICENSE](./LICENSE) file.
+
+---
+
+
+
Made with ❤️ by Clerk
+
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 00000000..1774ecf9
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,8 @@
+_site/
+.sass-cache/
+.jekyll-cache/
+.jekyll-metadata
+vendor/
+.bundle/
+Gemfile.lock
+
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
new file mode 100644
index 00000000..2d522841
--- /dev/null
+++ b/docs/CONTRIBUTING.md
@@ -0,0 +1,279 @@
+# Contributing to Clerk Dart & Flutter Documentation
+
+Thank you for your interest in contributing to the Clerk Dart & Flutter SDK documentation! This guide will help you get started.
+
+## 📋 Table of Contents
+
+- [Getting Started](#getting-started)
+- [Documentation Structure](#documentation-structure)
+- [Writing Guidelines](#writing-guidelines)
+- [Local Development](#local-development)
+- [Submitting Changes](#submitting-changes)
+
+---
+
+## Getting Started
+
+### Prerequisites
+
+- Ruby >= 3.1
+- Bundler
+- Git
+
+### Setup
+
+1. Fork the repository
+2. Clone your fork:
+ ```bash
+ git clone https://github.com/YOUR_USERNAME/clerk-sdk-flutter.git
+ cd clerk-sdk-flutter/docs
+ ```
+
+3. Install dependencies:
+ ```bash
+ bundle install
+ ```
+
+4. Start the local server:
+ ```bash
+ bundle exec jekyll serve
+ ```
+
+5. Open http://localhost:4000/clerk-sdk-flutter in your browser
+
+---
+
+## Documentation Structure
+
+```
+docs/
+├── index.md # Homepage
+├── getting-started.md # Getting started overview
+├── getting-started/ # Quickstart guides
+│ ├── quickstart-dart.md
+│ └── quickstart-flutter.md
+├── guides/ # Comprehensive guides
+│ ├── authentication.md
+│ ├── user-management.md
+│ ├── customization.md
+│ └── ...
+├── packages/ # Package-specific docs
+│ ├── clerk-auth.md
+│ └── clerk-flutter.md
+├── api/ # API reference
+│ └── widgets.md
+└── assets/ # Images and static files
+```
+
+---
+
+## Writing Guidelines
+
+### Front Matter
+
+Every page must include front matter at the top:
+
+```yaml
+---
+layout: default
+title: Your Page Title
+parent: Parent Page (optional)
+nav_order: 1
+---
+```
+
+### Front Matter Options
+
+| Option | Description | Required |
+|--------|-------------|----------|
+| `layout` | Page layout (usually `default`) | Yes |
+| `title` | Page title shown in navigation | Yes |
+| `parent` | Parent page for hierarchy | No |
+| `nav_order` | Order in navigation menu | No |
+| `has_children` | Set to `true` if page has children | No |
+| `permalink` | Custom URL path | No |
+
+### Markdown Style
+
+#### Headings
+
+Use ATX-style headings with proper hierarchy:
+
+```markdown
+# Page Title (H1 - only one per page)
+
+## Section (H2)
+
+### Subsection (H3)
+
+#### Detail (H4)
+```
+
+#### Code Blocks
+
+Always specify the language for syntax highlighting:
+
+````markdown
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+void main() {
+ runApp(MyApp());
+}
+```
+````
+
+Supported languages: `dart`, `yaml`, `bash`, `json`, `xml`, `swift`, `kotlin`
+
+#### Tables
+
+Use tables for structured information:
+
+```markdown
+| Column 1 | Column 2 | Column 3 |
+|----------|----------|----------|
+| Value 1 | Value 2 | Value 3 |
+```
+
+#### Callouts
+
+Use callouts for important information:
+
+```markdown
+{: .note }
+> This is a note callout
+
+{: .warning }
+> This is a warning callout
+
+{: .tip }
+> This is a tip callout
+```
+
+#### Links
+
+- **Internal links:** Use relative paths: `[Link Text](/guides/authentication)`
+- **External links:** Use full URLs: `[Clerk Docs](https://clerk.com/docs)`
+- **API references:** Link to pub.dev for detailed API docs
+
+### Content Guidelines
+
+1. **Be Clear and Concise**
+ - Use simple, direct language
+ - Avoid jargon when possible
+ - Explain technical terms when first used
+
+2. **Provide Examples**
+ - Include code examples for all features
+ - Show complete, working code when possible
+ - Add comments to explain complex code
+
+3. **Be Consistent**
+ - Use consistent terminology throughout
+ - Follow the existing documentation style
+ - Use the same code formatting conventions
+
+4. **Keep It Updated**
+ - Ensure code examples work with the latest SDK version
+ - Update version numbers when they change
+ - Remove deprecated features
+
+5. **Think About the User**
+ - Start with the most common use cases
+ - Provide step-by-step instructions
+ - Include troubleshooting tips
+
+---
+
+## Local Development
+
+### Running the Site Locally
+
+```bash
+cd docs
+bundle exec jekyll serve
+```
+
+The site will be available at http://localhost:4000/clerk-sdk-flutter
+
+### Live Reload
+
+Jekyll automatically reloads when you save changes to Markdown files. Refresh your browser to see updates.
+
+### Building for Production
+
+```bash
+bundle exec jekyll build
+```
+
+The built site will be in `docs/_site/`.
+
+---
+
+## Submitting Changes
+
+### Before Submitting
+
+1. **Test Locally**
+ - Run the site locally and verify your changes
+ - Check all links work correctly
+ - Ensure code examples are correct
+
+2. **Check Formatting**
+ - Use proper Markdown syntax
+ - Include required front matter
+ - Follow the style guidelines
+
+3. **Review Content**
+ - Proofread for typos and grammar
+ - Ensure technical accuracy
+ - Verify code examples work
+
+### Pull Request Process
+
+1. Create a new branch:
+ ```bash
+ git checkout -b docs/your-feature-name
+ ```
+
+2. Make your changes and commit:
+ ```bash
+ git add .
+ git commit -m "docs: Add guide for X feature"
+ ```
+
+3. Push to your fork:
+ ```bash
+ git push origin docs/your-feature-name
+ ```
+
+4. Open a Pull Request on GitHub
+
+5. Fill out the PR template with:
+ - Description of changes
+ - Screenshots (if applicable)
+ - Related issues
+
+### Commit Message Format
+
+Use conventional commits:
+
+- `docs: Add new guide for authentication`
+- `docs: Update Flutter quickstart`
+- `docs: Fix typo in user management guide`
+- `docs: Improve code examples in customization`
+
+---
+
+## Questions?
+
+If you have questions about contributing to the documentation:
+
+- 💬 [Join our Discord](https://clerk.com/discord)
+- 🐛 [Open an issue](https://github.com/clerk/clerk-sdk-flutter/issues)
+- 📧 Email: support@clerk.com
+
+---
+
+Thank you for contributing to Clerk's documentation! 🎉
+
diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md
new file mode 100644
index 00000000..13866b15
--- /dev/null
+++ b/docs/DEPLOYMENT.md
@@ -0,0 +1,228 @@
+# Documentation Deployment Guide
+
+This guide explains how the Clerk Dart & Flutter SDK documentation is deployed to GitHub Pages.
+
+## 🌐 Live Site
+
+The documentation is available at: **https://clerk.github.io/clerk-sdk-flutter/**
+
+---
+
+## 📋 Deployment Overview
+
+The documentation uses:
+- **Jekyll** - Static site generator
+- **Just the Docs** - Documentation theme
+- **GitHub Actions** - Automated deployment
+- **GitHub Pages** - Hosting
+
+---
+
+## 🚀 Automatic Deployment
+
+### Trigger Conditions
+
+The documentation is automatically deployed when:
+
+1. Changes are pushed to the `main` branch
+2. Changes affect files in the `docs/` directory
+3. Changes affect `.github/workflows/deploy-docs.yml`
+
+### Workflow Steps
+
+The deployment workflow (`.github/workflows/deploy-docs.yml`) performs:
+
+1. **Checkout** - Checks out the repository
+2. **Setup Ruby** - Installs Ruby 3.1 and dependencies
+3. **Setup Pages** - Configures GitHub Pages
+4. **Build** - Builds the Jekyll site
+5. **Upload** - Uploads the built site as an artifact
+6. **Deploy** - Deploys to GitHub Pages
+
+### Viewing Deployment Status
+
+1. Go to the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions)
+2. Look for "Deploy Documentation to GitHub Pages" workflow
+3. Click on a run to see details and logs
+
+---
+
+## 🔧 Manual Deployment
+
+### Trigger Manual Deployment
+
+1. Go to the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions)
+2. Select "Deploy Documentation to GitHub Pages"
+3. Click "Run workflow"
+4. Select the `main` branch
+5. Click "Run workflow"
+
+### Local Build Test
+
+Before deploying, test the build locally:
+
+```bash
+cd docs
+bundle install
+bundle exec jekyll build --baseurl "/clerk-sdk-flutter"
+```
+
+The built site will be in `docs/_site/`.
+
+---
+
+## ⚙️ GitHub Pages Configuration
+
+### Repository Settings
+
+To enable GitHub Pages for this repository:
+
+1. Go to **Settings** → **Pages**
+2. Under **Source**, select:
+ - Source: **GitHub Actions**
+3. The site will be published to: `https://clerk.github.io/clerk-sdk-flutter/`
+
+### Custom Domain (Optional)
+
+To use a custom domain:
+
+1. Add a `CNAME` file to `docs/` with your domain
+2. Configure DNS settings with your domain provider
+3. Update `baseurl` in `docs/_config.yml`
+
+---
+
+## 🐛 Troubleshooting
+
+### Build Failures
+
+If the build fails:
+
+1. Check the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions) for error logs
+2. Common issues:
+ - **Jekyll build errors**: Check Markdown syntax and front matter
+ - **Missing dependencies**: Ensure `Gemfile` is up to date
+ - **Configuration errors**: Verify `_config.yml` syntax
+
+### Local Testing
+
+Always test locally before pushing:
+
+```bash
+cd docs
+bundle exec jekyll serve
+```
+
+Visit http://localhost:4000/clerk-sdk-flutter to preview.
+
+### Common Errors
+
+**Error: "Could not find gem"**
+```bash
+cd docs
+bundle install
+```
+
+**Error: "Permission denied"**
+- Check repository permissions
+- Ensure GitHub Actions has write access to Pages
+
+**Error: "404 Not Found" after deployment**
+- Verify `baseurl` in `_config.yml` is set to `/clerk-sdk-flutter`
+- Check that files are in the `docs/` directory
+- Ensure GitHub Pages is enabled in repository settings
+
+---
+
+## 📝 Deployment Checklist
+
+Before deploying major changes:
+
+- [ ] Test locally with `bundle exec jekyll serve`
+- [ ] Verify all links work
+- [ ] Check code examples are correct
+- [ ] Review for typos and formatting
+- [ ] Ensure front matter is correct on all pages
+- [ ] Test responsive design (mobile/desktop)
+- [ ] Verify navigation hierarchy
+- [ ] Check that search works (if enabled)
+
+---
+
+## 🔄 Rollback
+
+If you need to rollback a deployment:
+
+1. Go to the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions)
+2. Find the last successful deployment
+3. Click "Re-run all jobs"
+
+Or revert the commit:
+
+```bash
+git revert
+git push origin main
+```
+
+---
+
+## 📊 Monitoring
+
+### Analytics
+
+To add Google Analytics:
+
+1. Add your tracking ID to `docs/_config.yml`:
+ ```yaml
+ google_analytics: UA-XXXXXXXXX-X
+ ```
+
+2. The Just the Docs theme will automatically include the tracking code
+
+### Performance
+
+Monitor site performance:
+- Use [Google PageSpeed Insights](https://pagespeed.web.dev/)
+- Check [Lighthouse](https://developers.google.com/web/tools/lighthouse) scores
+- Monitor build times in GitHub Actions
+
+---
+
+## 🔐 Security
+
+### Permissions
+
+The workflow requires these permissions:
+- `contents: read` - Read repository contents
+- `pages: write` - Write to GitHub Pages
+- `id-token: write` - Generate deployment token
+
+These are configured in `.github/workflows/deploy-docs.yml`.
+
+### Secrets
+
+No secrets are required for basic deployment. If you add custom features that need secrets:
+
+1. Go to **Settings** → **Secrets and variables** → **Actions**
+2. Add your secrets
+3. Reference them in the workflow with `${{ secrets.SECRET_NAME }}`
+
+---
+
+## 📚 Additional Resources
+
+- [Jekyll Documentation](https://jekyllrb.com/docs/)
+- [Just the Docs Theme](https://just-the-docs.github.io/just-the-docs/)
+- [GitHub Pages Documentation](https://docs.github.com/en/pages)
+- [GitHub Actions Documentation](https://docs.github.com/en/actions)
+
+---
+
+## 🆘 Support
+
+If you encounter issues with deployment:
+
+- 💬 [Join our Discord](https://clerk.com/discord)
+- 🐛 [Open an issue](https://github.com/clerk/clerk-sdk-flutter/issues)
+- 📧 Email: support@clerk.com
+
diff --git a/docs/Gemfile b/docs/Gemfile
new file mode 100644
index 00000000..72ed083d
--- /dev/null
+++ b/docs/Gemfile
@@ -0,0 +1,35 @@
+source "https://rubygems.org"
+
+gem "jekyll", "~> 4.3"
+gem "just-the-docs", "~> 0.10.0"
+
+# Pin sass-embedded to avoid deprecation warnings with older Sass
+gem "sass-embedded", "~> 1.69.0"
+
+# Required for Ruby 3.4+
+gem "bigdecimal"
+gem "csv"
+gem "base64"
+gem "fiddle"
+
+group :jekyll_plugins do
+ gem "jekyll-seo-tag"
+ gem "jekyll-github-metadata"
+ gem "jekyll-include-cache"
+ gem "jekyll-relative-links"
+end
+
+# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
+# and associated library.
+platforms :mingw, :x64_mingw, :mswin, :jruby do
+ gem "tzinfo", ">= 1", "< 3"
+ gem "tzinfo-data"
+end
+
+# Performance-booster for watching directories on Windows
+gem "wdm", "~> 0.1", :platforms => [:mingw, :x64_mingw, :mswin]
+
+# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
+# do not have a Java counterpart.
+gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
+
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..546f0d83
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,166 @@
+# Clerk Dart & Flutter SDK Documentation
+
+This directory contains the documentation site for Clerk's Dart and Flutter SDKs, built with Jekyll and hosted on GitHub Pages.
+
+## 🌐 Live Documentation
+
+Visit the live documentation at: **https://clerk.github.io/clerk-sdk-flutter/**
+
+## 📁 Structure
+
+```
+docs/
+├── _config.yml # Jekyll configuration
+├── index.md # Homepage
+├── getting-started.md # Getting started overview
+├── getting-started/ # Quickstart guides
+│ ├── quickstart-dart.md
+│ └── quickstart-flutter.md
+├── guides/ # Comprehensive guides
+│ ├── authentication.md
+│ ├── user-management.md
+│ ├── customization.md
+│ └── ...
+├── packages/ # Package-specific documentation
+│ ├── clerk-auth.md
+│ └── clerk-flutter.md
+└── assets/ # Images and static assets
+```
+
+## 🚀 Local Development
+
+### Prerequisites
+
+- Ruby >= 3.1
+- Bundler
+
+### Setup
+
+1. Install dependencies:
+
+```bash
+cd docs
+bundle install
+```
+
+2. Run the local server:
+
+```bash
+bundle exec jekyll serve
+```
+
+3. Open http://localhost:4000/clerk-sdk-flutter in your browser
+
+{: .note }
+> The site uses the local `just-the-docs` gem for development and `remote_theme` for GitHub Pages deployment. This is configured automatically via `_config.yml` and `_config_production.yml`.
+
+### Live Reload
+
+The server will automatically reload when you make changes to the documentation files.
+
+## 📝 Writing Documentation
+
+### Adding a New Page
+
+1. Create a new Markdown file in the appropriate directory
+2. Add front matter at the top:
+
+```yaml
+---
+layout: default
+title: Your Page Title
+parent: Parent Page (optional)
+nav_order: 1
+---
+```
+
+3. Write your content in Markdown
+
+### Front Matter Options
+
+| Option | Description |
+|--------|-------------|
+| `layout` | Page layout (usually `default`) |
+| `title` | Page title |
+| `parent` | Parent page for navigation hierarchy |
+| `nav_order` | Order in navigation menu |
+| `has_children` | Set to `true` if page has child pages |
+| `permalink` | Custom URL path |
+
+### Markdown Features
+
+The documentation supports:
+
+- Standard Markdown syntax
+- Code blocks with syntax highlighting
+- Tables
+- Callouts (notes, warnings, etc.)
+- Table of contents
+
+#### Code Blocks
+
+````markdown
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+void main() {
+ runApp(MyApp());
+}
+```
+````
+
+#### Callouts
+
+```markdown
+{: .note }
+> This is a note callout
+
+{: .warning }
+> This is a warning callout
+```
+
+## 🎨 Theme
+
+The documentation uses the [Just the Docs](https://just-the-docs.github.io/just-the-docs/) theme with custom Clerk branding.
+
+## 🚢 Deployment
+
+The documentation is automatically deployed to GitHub Pages when changes are pushed to the `main` branch.
+
+### GitHub Actions Workflow
+
+The deployment is handled by `.github/workflows/deploy-docs.yml`:
+
+1. Triggered on push to `main` branch (when `docs/**` files change)
+2. Builds the Jekyll site
+3. Deploys to GitHub Pages
+
+### Manual Deployment
+
+You can also trigger a manual deployment:
+
+1. Go to the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions)
+2. Select "Deploy Documentation to GitHub Pages"
+3. Click "Run workflow"
+
+## 📦 Dependencies
+
+- **Jekyll** - Static site generator
+- **just-the-docs** - Documentation theme
+- **jekyll-seo-tag** - SEO optimization
+- **jekyll-github-metadata** - GitHub integration
+
+## 🤝 Contributing
+
+To contribute to the documentation:
+
+1. Fork the [repository](https://github.com/clerk/clerk-sdk-flutter)
+2. Create a new branch for your changes
+3. Make your edits in the `docs/` directory
+4. Test locally with `bundle exec jekyll serve`
+5. Submit a pull request
+
+## 📄 License
+
+This documentation is part of the Clerk Dart & Flutter SDK and is licensed under the MIT License.
+
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 00000000..659aaccb
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1,78 @@
+# Clerk Dart & Flutter SDK Documentation
+title: Clerk Dart & Flutter SDK
+description: Official documentation for Clerk's Dart and Flutter SDKs
+baseurl: "/clerk-sdk-flutter"
+url: "https://clerk.github.io"
+
+# Theme
+theme: just-the-docs
+
+# Logo and branding
+logo: "/assets/images/clerk-logo.svg"
+# Custom Clerk color scheme
+color_scheme: clerk
+
+# Navigation
+nav_enabled: true
+nav_sort: case_insensitive
+
+# Search
+search_enabled: true
+search:
+ heading_level: 2
+ previews: 3
+ preview_words_before: 5
+ preview_words_after: 10
+ tokenizer_separator: /[\s/]+/
+ rel_url: true
+ button: true
+
+# Enable relative URLs for all links
+aux_links_new_tab: false
+
+# Footer
+footer_content: "Copyright © 2026 Clerk, Inc. Licensed under the MIT License."
+
+# Aux links
+aux_links:
+ "Clerk Dart & Flutter SDK on GitHub":
+ - "https://github.com/clerk/clerk-sdk-flutter"
+ "Clerk Documentation":
+ - "https://clerk.com/docs"
+ "Clerk Dashboard":
+ - "https://dashboard.clerk.com"
+
+# Defaults
+defaults:
+ - scope:
+ path: ""
+ values:
+ layout: default
+
+# Plugins
+plugins:
+ - jekyll-seo-tag
+ - jekyll-github-metadata
+ - jekyll-include-cache
+ - jekyll-relative-links
+
+# Relative links configuration
+relative_links:
+ enabled: true
+ collections: true
+
+# Syntax highlighting
+kramdown:
+ syntax_highlighter: rouge
+ syntax_highlighter_opts:
+ css_class: 'highlight'
+ default_lang: dart
+
+# Exclude from processing
+exclude:
+ - node_modules/
+ - vendor/
+ - Gemfile
+ - Gemfile.lock
+ - README.md
+
diff --git a/docs/_config_production.yml b/docs/_config_production.yml
new file mode 100644
index 00000000..a4dbf458
--- /dev/null
+++ b/docs/_config_production.yml
@@ -0,0 +1,7 @@
+# Production overrides for GitHub Pages deployment
+# This file is merged with _config.yml during GitHub Pages build
+
+# Use remote_theme for GitHub Pages
+remote_theme: just-the-docs/just-the-docs
+theme: null
+
diff --git a/docs/_sass/color_schemes/clerk.scss b/docs/_sass/color_schemes/clerk.scss
new file mode 100644
index 00000000..3f591631
--- /dev/null
+++ b/docs/_sass/color_schemes/clerk.scss
@@ -0,0 +1,56 @@
+// Clerk color scheme - matching https://clerk.com/docs
+// Based on dark theme with Clerk brand colors
+
+// Background colors
+$body-background-color: #0F0F0F;
+$sidebar-color: #0F0F0F;
+$code-background-color: #1A1A1A;
+$table-background-color: #1A1A1A;
+$feedback-color: darken($sidebar-color, 3%);
+
+// Text colors
+$body-text-color: #E5E5E5;
+$body-heading-color: #FFFFFF;
+$nav-child-link-color: #A1A1A1;
+$link-color: #9B8FD9;
+$btn-primary-color: #6C47FF;
+$base-button-color: #6C47FF;
+
+// Border colors
+$border-color: #2A2A2A;
+
+// Code colors
+$code-linenumber-color: #6B6B6B;
+
+// Search
+$search-background-color: #1A1A1A;
+$search-result-preview-color: #A1A1A1;
+
+// Sidebar
+$sidebar-width: 264px;
+$sidebar-width-sm: 200px;
+
+// Navigation
+$nav-list-link-color: #E5E5E5;
+$nav-list-link-color-hover: #FFFFFF;
+$nav-list-link-color-active: #FFFFFF;
+$nav-list-expander-color: #6B6B6B;
+
+// Buttons
+$btn-primary-color: #6C47FF;
+
+// Base button (outline style)
+$base-button-color: transparent;
+
+// Feedback colors
+$label-green: #10B981;
+$label-blue: #3B82F6;
+$label-purple: #6C47FF;
+$label-red: #EF4444;
+$label-yellow: #F59E0B;
+
+// Callouts/Admonitions
+$note-color: #3B82F6;
+$warning-color: #F59E0B;
+$important-color: #EF4444;
+
diff --git a/docs/_sass/custom/custom.scss b/docs/_sass/custom/custom.scss
new file mode 100644
index 00000000..75db400e
--- /dev/null
+++ b/docs/_sass/custom/custom.scss
@@ -0,0 +1,167 @@
+// Import syntax highlighting
+@import "./syntax-highlighting";
+
+
+// Custom styles to match Clerk documentation
+
+// Smooth scrolling
+html {
+ scroll-behavior: smooth;
+}
+
+// Logo styling
+.site-logo {
+ max-height: 32px;
+}
+
+// Navigation improvements
+.site-nav {
+ padding-top: 1.5rem;
+}
+
+.nav-list .nav-list-item {
+ margin: 0.25rem 0;
+}
+
+.nav-list-link {
+ border-radius: 6px;
+ padding: 0.5rem 0.75rem;
+ transition: all 0.2s ease;
+
+ &:hover {
+ background-color: rgba(108, 71, 255, 0.1);
+ }
+
+ &.active {
+ background-color: rgba(108, 71, 255, 0.15);
+ font-weight: 500;
+ }
+}
+
+// Code blocks
+pre.highlight {
+ border-radius: 8px;
+ border: 1px solid #2A2A2A;
+}
+
+code {
+ border-radius: 4px;
+ padding: 0.2em 0.4em;
+ font-size: 0.9em;
+}
+
+// Tables
+table {
+ border-radius: 8px;
+ overflow: hidden;
+
+ th {
+ background-color: #1A1A1A;
+ font-weight: 600;
+ }
+
+ td, th {
+ border-color: #2A2A2A;
+ }
+}
+
+// Buttons
+.btn {
+ border-radius: 6px;
+ font-weight: 500;
+ transition: all 0.2s ease;
+ border: 1px solid #2A2A2A;
+ background-color: transparent;
+ color: #E5E5E5;
+
+ &:hover {
+ border-color: #6C47FF;
+ background-color: rgba(108, 71, 255, 0.1);
+ color: #FFFFFF;
+ }
+}
+
+.btn-primary {
+ background-color: #6C47FF;
+ border-color: #6C47FF;
+ color: #FFFFFF;
+
+ &:hover {
+ background-color: #5A38E6;
+ border-color: #5A38E6;
+ transform: translateY(-1px);
+ box-shadow: 0 4px 12px rgba(108, 71, 255, 0.3);
+ }
+}
+
+// Headings
+h1, h2, h3, h4, h5, h6 {
+ font-weight: 600;
+ letter-spacing: -0.02em;
+}
+
+// Links
+a {
+ transition: color 0.2s ease;
+
+ &:hover {
+ color: #B5AAEB;
+ }
+}
+
+// Search
+.search-input {
+ border-radius: 8px;
+ background-color: #1A1A1A;
+ border: 1px solid #2A2A2A;
+
+ &:focus {
+ border-color: #6C47FF;
+ box-shadow: 0 0 0 3px rgba(108, 71, 255, 0.1);
+ }
+}
+
+// Callouts
+.label,
+.label-blue,
+.label-green,
+.label-purple,
+.label-red,
+.label-yellow {
+ border-radius: 4px;
+ font-weight: 500;
+}
+
+// Note/Warning boxes
+blockquote {
+ border-left: 4px solid #6C47FF;
+ background-color: rgba(108, 71, 255, 0.05);
+ border-radius: 4px;
+ padding: 1rem;
+ margin: 1.5rem 0;
+}
+
+// Sidebar footer
+.site-footer {
+ border-top: 1px solid #2A2A2A;
+ padding: 1rem;
+ font-size: 0.875rem;
+ color: #6B6B6B;
+}
+
+// Main content area
+.main-content {
+ max-width: 50rem;
+
+ h1 {
+ margin-bottom: 1.5rem;
+ }
+
+ h2 {
+ margin-top: 2.5rem;
+ margin-bottom: 1rem;
+ padding-bottom: 0.5rem;
+ border-bottom: 1px solid #2A2A2A;
+ }
+}
+
diff --git a/docs/_sass/custom/syntax-highlighting.scss b/docs/_sass/custom/syntax-highlighting.scss
new file mode 100644
index 00000000..86229cda
--- /dev/null
+++ b/docs/_sass/custom/syntax-highlighting.scss
@@ -0,0 +1,159 @@
+// Dark theme syntax highlighting for code blocks
+// Based on GitHub Dark theme
+
+.highlight {
+ background-color: #1A1A1A;
+ color: #E5E5E5;
+
+ // Comments
+ .c, .cm, .c1, .cs {
+ color: #8B949E;
+ font-style: italic;
+ }
+
+ // Keywords
+ .k, .kc, .kd, .kn, .kp, .kr, .kt {
+ color: #FF7B72;
+ }
+
+ // Operators
+ .o, .ow {
+ color: #FF7B72;
+ }
+
+ // Strings
+ .s, .s1, .s2, .sb, .sc, .sd, .se, .sh, .si, .sx {
+ color: #A5D6FF;
+ }
+
+ // Numbers
+ .m, .mf, .mh, .mi, .mo, .il {
+ color: #79C0FF;
+ }
+
+ // Names
+ .n, .na, .nb, .nc, .no, .nd, .ni, .ne, .nf, .nl, .nn, .nx, .py {
+ color: #D2A8FF;
+ }
+
+ // Variables
+ .nv, .vc, .vg, .vi {
+ color: #FFA657;
+ }
+
+ // Built-ins
+ .nb {
+ color: #79C0FF;
+ }
+
+ // Functions
+ .nf {
+ color: #D2A8FF;
+ }
+
+ // Classes
+ .nc {
+ color: #FFA657;
+ }
+
+ // Booleans
+ .bp {
+ color: #79C0FF;
+ }
+
+ // Punctuation
+ .p {
+ color: #E5E5E5;
+ }
+
+ // Generic
+ .gd {
+ color: #FF7B72;
+ background-color: #3F1F1F;
+ }
+
+ .gi {
+ color: #7EE787;
+ background-color: #1F3F1F;
+ }
+
+ .ge {
+ font-style: italic;
+ }
+
+ .gs {
+ font-weight: bold;
+ }
+
+ // Line numbers
+ .lineno {
+ color: #6B6B6B;
+ user-select: none;
+ padding-right: 1em;
+ border-right: 1px solid #2A2A2A;
+ margin-right: 1em;
+ }
+
+ // Dart-specific
+ .kd {
+ color: #FF7B72; // class, void, var, final, const
+ }
+
+ .kt {
+ color: #79C0FF; // int, String, bool, etc.
+ }
+
+ // YAML-specific
+ .l-Scalar-Plain {
+ color: #A5D6FF;
+ }
+
+ .na {
+ color: #79C0FF; // YAML keys
+ }
+
+ // JSON-specific
+ .s2 {
+ color: #A5D6FF; // JSON strings
+ }
+
+ // Bash/Shell
+ .nv {
+ color: #79C0FF; // environment variables
+ }
+
+ .nb {
+ color: #D2A8FF; // built-in commands
+ }
+}
+
+// Inline code
+code {
+ background-color: #1A1A1A;
+ color: #E5E5E5;
+ border: 1px solid #2A2A2A;
+}
+
+// Code blocks
+pre {
+ background-color: #1A1A1A;
+ border: 1px solid #2A2A2A;
+
+ code {
+ background-color: transparent;
+ border: none;
+ color: #E5E5E5;
+ }
+}
+
+// Highlighted lines in code blocks
+.highlight .hll {
+ background-color: #2A2A2A;
+}
+
+// Error highlighting
+.highlight .err {
+ color: #FF7B72;
+ background-color: transparent;
+}
+
diff --git a/docs/api/_index.md b/docs/api/_index.md
new file mode 100644
index 00000000..e85256f5
--- /dev/null
+++ b/docs/api/_index.md
@@ -0,0 +1,40 @@
+---
+layout: default
+title: API Reference
+nav_order: 5
+has_children: true
+permalink: /api
+---
+
+# API Reference
+
+Detailed API documentation for Clerk's Dart and Flutter SDKs.
+
+## Available References
+
+### [Widget Reference]({{ '/api/widgets' | relative_url }})
+Complete reference for all Clerk Flutter widgets including ClerkAuth, ClerkAuthentication, ClerkUserButton, and more.
+
+### [clerk_auth Package]({{ '/packages/clerk-auth' | relative_url }})
+API documentation for the Dart SDK including Auth, User, Session, and configuration classes.
+
+### [clerk_flutter Package]({{ '/packages/clerk-flutter' | relative_url }})
+API documentation for the Flutter SDK including widgets, themes, and Flutter-specific features.
+
+---
+
+## External API Documentation
+
+For detailed API documentation generated from source code:
+
+- **[clerk_auth on pub.dev](https://pub.dev/documentation/clerk_auth/latest/)** - Complete Dart API reference
+- **[clerk_flutter on pub.dev](https://pub.dev/documentation/clerk_flutter/latest/)** - Complete Flutter API reference
+
+---
+
+## Quick Links
+
+- [Getting Started](/getting-started)
+- [Guides](/guides)
+- [GitHub Repository](https://github.com/clerk/clerk-sdk-flutter)
+
diff --git a/docs/api/widgets.md b/docs/api/widgets.md
new file mode 100644
index 00000000..b8592628
--- /dev/null
+++ b/docs/api/widgets.md
@@ -0,0 +1,304 @@
+---
+layout: default
+title: Widget Reference
+parent: API Reference
+nav_order: 1
+---
+
+# Widget Reference
+{: .no_toc }
+
+Complete reference for all Clerk Flutter widgets.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Control Widgets
+
+### ClerkAuth
+
+The root widget that initializes and provides Clerk authentication to your app.
+
+```dart
+ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ ),
+ child: MaterialApp(/* ... */),
+)
+```
+
+**Properties:**
+
+| Name | Type | Required | Description |
+|------|------|----------|-------------|
+| `config` | `ClerkAuthConfig` | Yes | Configuration object |
+| `child` | `Widget` | Yes | Your app widget |
+| `persistor` | `Persistor?` | No | Custom storage mechanism |
+| `httpService` | `HttpService?` | No | Custom HTTP service |
+| `authState` | `ClerkAuthState?` | No | Pre-initialized auth state |
+
+---
+
+### ClerkAuthBuilder
+
+Builds different UI based on authentication state.
+
+```dart
+ClerkAuthBuilder(
+ signedInBuilder: (context, authState) => SignedInWidget(),
+ signedOutBuilder: (context, authState) => SignedOutWidget(),
+)
+```
+
+**Properties:**
+
+| Name | Type | Required | Description |
+|------|------|----------|-------------|
+| `signedInBuilder` | `AuthWidgetBuilder?` | No | Builder when user is signed in |
+| `signedOutBuilder` | `AuthWidgetBuilder?` | No | Builder when user is signed out |
+| `builder` | `AuthWidgetBuilder?` | No | Fallback builder |
+
+---
+
+### ClerkSignedIn
+
+Only renders its child when a user is signed in.
+
+```dart
+ClerkSignedIn(
+ child: Text('Protected content'),
+)
+```
+
+**Properties:**
+
+| Name | Type | Required | Description |
+|------|------|----------|-------------|
+| `child` | `Widget` | Yes | Widget to show when signed in |
+
+---
+
+### ClerkSignedOut
+
+Only renders its child when no user is signed in.
+
+```dart
+ClerkSignedOut(
+ child: Text('Please sign in'),
+)
+```
+
+**Properties:**
+
+| Name | Type | Required | Description |
+|------|------|----------|-------------|
+| `child` | `Widget` | Yes | Widget to show when signed out |
+
+---
+
+### ClerkErrorListener
+
+Listens for authentication errors and displays them.
+
+```dart
+ClerkErrorListener(
+ child: YourWidget(),
+)
+```
+
+**Properties:**
+
+| Name | Type | Required | Description |
+|------|------|----------|-------------|
+| `child` | `Widget` | Yes | Child widget |
+
+---
+
+## Authentication Widgets
+
+### ClerkAuthentication
+
+Pre-built authentication UI with sign-in and sign-up flows.
+
+```dart
+const ClerkAuthentication()
+```
+
+**Features:**
+- Email/password authentication
+- OAuth provider buttons
+- Email verification
+- Password reset
+- Automatic error handling
+- Responsive design
+
+---
+
+## User Widgets
+
+### ClerkUserButton
+
+User menu button with profile and sign-out options.
+
+```dart
+ClerkUserButton(
+ showName: true,
+ sessionActions: [
+ ClerkUserAction(
+ label: 'Settings',
+ icon: Icons.settings,
+ onPressed: (context, authState) {
+ // Handle action
+ },
+ ),
+ ],
+)
+```
+
+**Properties:**
+
+| Name | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `showName` | `bool` | No | `true` | Show user's name next to avatar |
+| `sessionActions` | `List?` | No | `null` | Custom actions for session row |
+| `additionalActions` | `List?` | No | `null` | Additional menu items |
+
+---
+
+### ClerkUserAction
+
+Defines a custom action for the user menu.
+
+```dart
+ClerkUserAction(
+ label: 'Settings',
+ icon: Icons.settings,
+ onPressed: (context, authState) {
+ Navigator.push(
+ context,
+ MaterialPageRoute(builder: (_) => SettingsPage()),
+ );
+ },
+)
+```
+
+**Properties:**
+
+| Name | Type | Required | Description |
+|------|------|----------|-------------|
+| `label` | `String` | Yes | Action label text |
+| `icon` | `IconData` | Yes | Action icon |
+| `onPressed` | `Function(BuildContext, ClerkAuthState)` | Yes | Callback when pressed |
+
+---
+
+## Organization Widgets
+
+### ClerkOrganizationList
+
+Display and manage organizations (if enabled in your Clerk instance).
+
+```dart
+const ClerkOrganizationList()
+```
+
+**Features:**
+- List all user's organizations
+- Create new organizations
+- Switch active organization
+- Manage organization settings
+
+---
+
+## Accessing ClerkAuth
+
+### ClerkAuth.of()
+
+Access the ClerkAuthState from anywhere in your widget tree.
+
+```dart
+final authState = ClerkAuth.of(context);
+final user = authState.user;
+```
+
+**Parameters:**
+
+| Name | Type | Required | Default | Description |
+|------|------|----------|---------|-------------|
+| `context` | `BuildContext` | Yes | - | Build context |
+| `listen` | `bool` | No | `true` | Whether to rebuild on changes |
+
+**Returns:** `ClerkAuthState`
+
+---
+
+## ClerkAuthState
+
+The main state object for Clerk authentication.
+
+### Properties
+
+| Name | Type | Description |
+|------|------|-------------|
+| `user` | `User?` | Current signed-in user |
+| `client` | `Client` | Client object with sessions |
+| `env` | `Environment` | Environment configuration |
+| `isSignedIn` | `bool` | Whether a user is signed in |
+| `sessionTokenStream` | `Stream` | Stream of session tokens |
+
+### Methods
+
+| Method | Description |
+|--------|-------------|
+| `attemptSignIn()` | Start a sign-in attempt |
+| `attemptSignUp()` | Start a sign-up attempt |
+| `attemptSignInVerification()` | Verify a sign-in attempt |
+| `attemptSignUpVerification()` | Verify a sign-up attempt |
+| `signOut()` | Sign out the current user |
+| `signOutOf(Session)` | Sign out of a specific session |
+| `safelyCall()` | Execute async operation with error handling |
+
+---
+
+## Configuration
+
+### ClerkAuthConfig
+
+Configuration object for ClerkAuth.
+
+```dart
+ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ redirectionGenerator: (url) => Uri.parse('myapp://oauth'),
+ deepLinkStream: AppLinks().allUriLinkStream.map(
+ (uri) => ClerkDeepLink(uri: uri),
+ ),
+ loading: CircularProgressIndicator(),
+)
+```
+
+**Properties:**
+
+| Name | Type | Required | Description |
+|------|------|----------|-------------|
+| `publishableKey` | `String` | Yes | Your Clerk publishable key |
+| `redirectionGenerator` | `Function(String)?` | No | Generate OAuth redirect URLs |
+| `deepLinkStream` | `Stream?` | No | Handle OAuth callbacks |
+| `loading` | `Widget?` | No | Widget shown during initialization |
+
+---
+
+## Next Steps
+
+- [Customization Guide]({{ '/guides/customization' | relative_url }}) - Theme and style your widgets
+- [Flutter Quickstart]({{ '/getting-started/quickstart-flutter' | relative_url }}) - Get started quickly
+- [Authentication Flows]({{ '/guides/authentication' | relative_url }}) - Implement auth flows
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Manage user profiles
+
diff --git a/docs/assets/images/clerk-logo.svg b/docs/assets/images/clerk-logo.svg
new file mode 100644
index 00000000..0d7dd8cc
--- /dev/null
+++ b/docs/assets/images/clerk-logo.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/docs/getting-started.md b/docs/getting-started.md
new file mode 100644
index 00000000..35c27fe5
--- /dev/null
+++ b/docs/getting-started.md
@@ -0,0 +1,133 @@
+---
+layout: default
+title: Getting Started
+nav_order: 2
+has_children: true
+permalink: /getting-started
+---
+
+# Getting Started with Clerk Dart & Flutter SDKs
+
+This guide will help you integrate Clerk authentication into your Dart or Flutter application.
+
+## Choose Your SDK
+
+Clerk provides two SDKs for Dart and Flutter development:
+
+### clerk_auth (Dart SDK)
+
+The `clerk_auth` package is a pure Dart SDK suitable for:
+- Backend applications
+- CLI tools
+- Server-side Dart applications
+- Any Dart environment where you need authentication
+
+**[Get started with clerk_auth →]({{ '/getting-started/quickstart-dart' | relative_url }})**
+
+### clerk_flutter (Flutter SDK)
+
+The `clerk_flutter` package is designed for Flutter applications and includes:
+- Pre-built UI components
+- Material Design integration
+- Cross-platform support (iOS, Android, Web, Desktop)
+- Seamless integration with Flutter's widget tree
+
+**[Get started with clerk_flutter →]({{ '/getting-started/quickstart-flutter' | relative_url }})**
+
+---
+
+## Prerequisites
+
+Before you begin, you'll need:
+
+1. **A Clerk Account** - [Sign up for free](https://dashboard.clerk.com/sign-up)
+2. **A Clerk Application** - Create one in the [Clerk Dashboard](https://dashboard.clerk.com)
+3. **Your Publishable Key** - Found in your application's API Keys section
+
+### Finding Your Publishable Key
+
+1. Navigate to the [Clerk Dashboard](https://dashboard.clerk.com)
+2. Select your application
+3. Go to **API Keys** in the sidebar
+4. Copy your **Publishable Key** (starts with `pk_test_` or `pk_live_`)
+
+{: .warning }
+> Never commit your secret keys to version control. Use environment variables or secure configuration management.
+
+---
+
+## Installation
+
+### For Dart Projects (clerk_auth)
+
+Add `clerk_auth` to your `pubspec.yaml`:
+
+```yaml
+dependencies:
+ clerk_auth: ^0.0.13-beta
+```
+
+Then run:
+
+```bash
+dart pub get
+```
+
+### For Flutter Projects (clerk_flutter)
+
+Add `clerk_flutter` to your `pubspec.yaml`:
+
+```yaml
+dependencies:
+ clerk_flutter: ^0.0.13-beta
+```
+
+Then run:
+
+```bash
+flutter pub get
+```
+
+{: .note }
+> The `clerk_flutter` package automatically includes `clerk_auth` as a dependency, so you don't need to add both.
+
+---
+
+## Platform-Specific Setup
+
+### Android
+
+Add the following permission to your `android/app/src/main/AndroidManifest.xml`:
+
+```xml
+
+```
+
+### iOS
+
+No additional setup required for basic functionality.
+
+### Web
+
+No additional setup required for basic functionality.
+
+### Desktop (Windows, macOS, Linux)
+
+No additional setup required for basic functionality.
+
+---
+
+## Next Steps
+
+Choose your quickstart guide based on your project type:
+
+- **[Dart Quickstart]({{ '/getting-started/quickstart-dart' | relative_url }})** - For pure Dart applications
+- **[Flutter Quickstart]({{ '/getting-started/quickstart-flutter' | relative_url }})** - For Flutter applications
+
+Or explore specific topics:
+
+- [Authentication Flows]({{ '/guides/authentication' | relative_url }})
+- [User Management]({{ '/guides/user-management' | relative_url }})
+- [Organizations]({{ '/guides/organizations' | relative_url }})
+- [Customization]({{ '/guides/customization' | relative_url }})
+
diff --git a/docs/getting-started/quickstart-dart.md b/docs/getting-started/quickstart-dart.md
new file mode 100644
index 00000000..3676e92d
--- /dev/null
+++ b/docs/getting-started/quickstart-dart.md
@@ -0,0 +1,261 @@
+---
+layout: default
+title: Dart Quickstart
+parent: Getting Started
+nav_order: 1
+---
+
+# Dart Quickstart
+{: .no_toc }
+
+Get started with Clerk authentication in your Dart application in minutes.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Install clerk_auth
+
+Add `clerk_auth` to your `pubspec.yaml`:
+
+```yaml
+dependencies:
+ clerk_auth: ^0.0.13-beta
+```
+
+Install the package:
+
+```bash
+dart pub get
+```
+
+---
+
+## Set up your environment
+
+Create a `.env` file or set environment variables with your Clerk publishable key:
+
+```bash
+CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxx
+```
+
+{: .warning }
+> Never commit your `.env` file to version control. Add it to your `.gitignore`.
+
+---
+
+## Initialize Clerk Auth
+
+Create an `Auth` instance and initialize it:
+
+```dart
+import 'dart:io';
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future main() async {
+ // Create the Auth instance
+ final auth = Auth(
+ config: AuthConfig(
+ publishableKey: Platform.environment['CLERK_PUBLISHABLE_KEY']!,
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ ),
+ );
+
+ // Initialize the auth system
+ await auth.initialize();
+
+ // Your app logic here
+
+ // Clean up when done
+ auth.terminate();
+}
+```
+
+---
+
+## Sign in with email and password
+
+```dart
+import 'dart:io';
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future main() async {
+ final auth = Auth(
+ config: AuthConfig(
+ publishableKey: Platform.environment['CLERK_PUBLISHABLE_KEY']!,
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ ),
+ );
+
+ await auth.initialize();
+
+ try {
+ // Attempt to sign in
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'your-password',
+ );
+
+ print('✅ Signed in as: ${auth.user?.emailAddress}');
+ print('User ID: ${auth.user?.id}');
+
+ // Access the current user
+ final user = auth.user;
+ if (user != null) {
+ print('Name: ${user.firstName} ${user.lastName}');
+ print('Email: ${user.emailAddress}');
+ }
+
+ } on ClerkApiException catch (e) {
+ print('❌ Sign in failed: ${e.message}');
+ } finally {
+ auth.terminate();
+ }
+}
+```
+
+---
+
+## Sign up a new user
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future signUpUser(Auth auth) async {
+ try {
+ // Start the sign-up process
+ await auth.attemptSignUp(
+ strategy: Strategy.password,
+ identifier: 'newuser@example.com',
+ password: 'secure-password',
+ );
+
+ // If email verification is required
+ if (auth.signUp?.verification?.status == VerificationStatus.unverified) {
+ print('📧 Verification email sent');
+
+ // User enters the code from their email
+ final code = '123456'; // Get this from user input
+
+ await auth.attemptSignUpVerification(
+ strategy: Strategy.emailCode,
+ code: code,
+ );
+ }
+
+ print('✅ Sign up successful!');
+ print('User: ${auth.user?.emailAddress}');
+
+ } on ClerkApiException catch (e) {
+ print('❌ Sign up failed: ${e.message}');
+ }
+}
+```
+
+---
+
+## Sign out
+
+```dart
+Future signOutUser(Auth auth) async {
+ await auth.signOut();
+ print('👋 Signed out successfully');
+}
+```
+
+---
+
+## Access session tokens
+
+Session tokens are automatically managed and can be accessed via a stream:
+
+```dart
+import 'dart:async';
+
+Future listenToSessionTokens(Auth auth) async {
+ // Listen to session token updates
+ final subscription = auth.sessionTokenStream.listen((token) {
+ if (token != null) {
+ print('🔑 New session token: ${token.substring(0, 20)}...');
+ // Use this token for authenticated API requests
+ }
+ });
+
+ // Remember to cancel the subscription when done
+ await Future.delayed(Duration(seconds: 30));
+ await subscription.cancel();
+}
+```
+
+---
+
+## Next steps
+
+Now that you have basic authentication working, explore more features:
+
+- [Authentication Strategies]({{ '/guides/authentication' | relative_url }}) - OAuth, passwordless, MFA
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Update profiles, manage sessions
+- [Session Token Polling]({{ '/guides/session-tokens' | relative_url }}) - Configure token refresh behavior
+- [Error Handling]({{ '/guides/error-handling' | relative_url }}) - Handle authentication errors gracefully
+
+---
+
+## Complete example
+
+Here's a complete example with sign-up, sign-in, and sign-out:
+
+```dart
+import 'dart:io';
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future main() async {
+ final auth = Auth(
+ config: AuthConfig(
+ publishableKey: Platform.environment['CLERK_PUBLISHABLE_KEY']!,
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ ),
+ );
+
+ await auth.initialize();
+
+ try {
+ // Check if already signed in
+ if (auth.user != null) {
+ print('Already signed in as: ${auth.user?.emailAddress}');
+ } else {
+ // Sign in
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'password',
+ );
+ print('Signed in successfully!');
+ }
+
+ // Do authenticated work
+ print('User ID: ${auth.user?.id}');
+
+ // Sign out
+ await auth.signOut();
+ print('Signed out');
+
+ } catch (e) {
+ print('Error: $e');
+ } finally {
+ auth.terminate();
+ }
+}
+```
+
diff --git a/docs/getting-started/quickstart-flutter.md b/docs/getting-started/quickstart-flutter.md
new file mode 100644
index 00000000..f631906f
--- /dev/null
+++ b/docs/getting-started/quickstart-flutter.md
@@ -0,0 +1,390 @@
+---
+layout: default
+title: Flutter Quickstart
+parent: Getting Started
+nav_order: 2
+---
+
+# Flutter Quickstart
+{: .no_toc }
+
+Get started with Clerk authentication in your Flutter application with pre-built UI components.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Install clerk_flutter
+
+Add `clerk_flutter` to your `pubspec.yaml`:
+
+```yaml
+dependencies:
+ clerk_flutter: ^0.0.13-beta
+```
+
+Install the package:
+
+```bash
+flutter pub get
+```
+
+---
+
+## Platform setup
+
+### Android
+
+Add the Internet permission to `android/app/src/main/AndroidManifest.xml`:
+
+```xml
+
+
+
+
+```
+
+### iOS, Web, Desktop
+
+No additional setup required.
+
+---
+
+## Wrap your app with ClerkAuth
+
+Wrap your `MaterialApp` with the `ClerkAuth` widget:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+void main() {
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ ),
+ child: MaterialApp(
+ title: 'My Clerk App',
+ theme: ThemeData.light(),
+ darkTheme: ThemeData.dark(),
+ home: const HomePage(),
+ ),
+ );
+ }
+}
+```
+
+{: .warning }
+> Replace `pk_test_xxxxxxxxxxxxx` with your actual publishable key from the [Clerk Dashboard](https://dashboard.clerk.com).
+
+---
+
+## Build conditional UI with ClerkAuthBuilder
+
+Use `ClerkAuthBuilder` to show different UI based on authentication state:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class HomePage extends StatelessWidget {
+ const HomePage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: SafeArea(
+ child: ClerkErrorListener(
+ child: ClerkAuthBuilder(
+ signedInBuilder: (context, authState) {
+ // User is signed in
+ return Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text('Welcome, ${authState.user?.firstName}!'),
+ const SizedBox(height: 20),
+ const ClerkUserButton(),
+ ],
+ ),
+ );
+ },
+ signedOutBuilder: (context, authState) {
+ // User is signed out
+ return const Center(
+ child: ClerkAuthentication(),
+ );
+ },
+ ),
+ ),
+ ),
+ );
+ }
+}
+```
+
+---
+
+## Use pre-built authentication UI
+
+The `ClerkAuthentication` widget provides a complete sign-in/sign-up flow:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class SignInPage extends StatelessWidget {
+ const SignInPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: SafeArea(
+ child: Center(
+ child: ClerkAuthentication(),
+ ),
+ ),
+ );
+ }
+}
+```
+
+The `ClerkAuthentication` widget automatically handles:
+- Email/password sign-in
+- Email/password sign-up
+- OAuth providers (Google, GitHub, etc.)
+- Email verification
+- Password reset
+- Error states
+
+---
+
+## Use the ClerkUserButton
+
+The `ClerkUserButton` provides a user menu with profile management and sign-out:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class ProfilePage extends StatelessWidget {
+ const ProfilePage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Profile'),
+ actions: const [
+ ClerkUserButton(),
+ ],
+ ),
+ body: ClerkSignedIn(
+ child: Center(
+ child: Text('Protected content'),
+ ),
+ ),
+ );
+ }
+}
+```
+
+---
+
+## Conditional rendering with ClerkSignedIn/ClerkSignedOut
+
+Use these widgets to conditionally render content:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class ConditionalPage extends StatelessWidget {
+ const ConditionalPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Column(
+ children: [
+ ClerkSignedIn(
+ child: Text('This is only visible when signed in'),
+ ),
+ ClerkSignedOut(
+ child: Text('This is only visible when signed out'),
+ ),
+ ],
+ ),
+ );
+ }
+}
+```
+
+---
+
+## Access the current user
+
+Access user information through the `ClerkAuth` inherited widget:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class UserInfoWidget extends StatelessWidget {
+ const UserInfoWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final authState = ClerkAuth.of(context);
+ final user = authState.user;
+
+ if (user == null) {
+ return const Text('Not signed in');
+ }
+
+ return Column(
+ children: [
+ Text('Name: ${user.firstName} ${user.lastName}'),
+ Text('Email: ${user.emailAddress}'),
+ Text('User ID: ${user.id}'),
+ if (user.imageUrl != null)
+ Image.network(user.imageUrl!),
+ ],
+ );
+ }
+}
+```
+
+---
+
+## Handle deep links for OAuth
+
+For OAuth authentication, you need to handle deep links:
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+import 'package:app_links/app_links.dart';
+
+ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ redirectionGenerator: (url) {
+ // Generate your app's deep link
+ return Uri.parse('myapp://oauth-callback');
+ },
+ deepLinkStream: AppLinks().allUriLinkStream.map((uri) {
+ // Handle incoming deep links
+ return ClerkDeepLink(uri: uri);
+ }),
+ ),
+ child: MaterialApp(
+ // ...
+ ),
+)
+```
+
+Add the `app_links` package to handle deep links:
+
+```yaml
+dependencies:
+ app_links: ^3.5.1
+```
+
+---
+
+## Next steps
+
+Explore more features and customization options:
+
+- [Widget Reference]({{ '/api/widgets' | relative_url }}) - All available widgets and their properties
+- [Customization]({{ '/guides/customization' | relative_url }}) - Theme and style your components
+- [Authentication Flows]({{ '/guides/authentication' | relative_url }}) - OAuth, passwordless, MFA
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Profile updates, session management
+- [Organizations]({{ '/guides/organizations' | relative_url }}) - Multi-tenant support
+
+---
+
+## Complete example
+
+Here's a complete Flutter app with Clerk authentication:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+void main() {
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ ),
+ child: MaterialApp(
+ title: 'Clerk Flutter Demo',
+ theme: ThemeData.light(),
+ darkTheme: ThemeData.dark(),
+ home: const HomePage(),
+ ),
+ );
+ }
+}
+
+class HomePage extends StatelessWidget {
+ const HomePage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Clerk Flutter Demo'),
+ ),
+ body: SafeArea(
+ child: ClerkErrorListener(
+ child: ClerkAuthBuilder(
+ signedInBuilder: (context, authState) {
+ return Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text(
+ 'Welcome, ${authState.user?.firstName ?? "User"}!',
+ style: Theme.of(context).textTheme.headlineMedium,
+ ),
+ const SizedBox(height: 20),
+ const ClerkUserButton(showName: true),
+ ],
+ ),
+ );
+ },
+ signedOutBuilder: (context, authState) {
+ return const Center(
+ child: ClerkAuthentication(),
+ );
+ },
+ ),
+ ),
+ ),
+ );
+ }
+}
+```
+
diff --git a/docs/guides/_index.md b/docs/guides/_index.md
new file mode 100644
index 00000000..af6f5bb9
--- /dev/null
+++ b/docs/guides/_index.md
@@ -0,0 +1,43 @@
+---
+layout: default
+title: Guides
+nav_order: 3
+has_children: true
+permalink: /guides
+---
+
+# Guides
+
+Comprehensive guides for implementing authentication and user management with Clerk's Dart and Flutter SDKs.
+
+## Available Guides
+
+### [Authentication]({{ '/guides/authentication' | relative_url }})
+Learn how to implement various authentication strategies including email/password, passwordless, OAuth, and multi-factor authentication.
+
+### [User Management]({{ '/guides/user-management' | relative_url }})
+Manage user profiles, update user information, handle email addresses and phone numbers, and work with user metadata.
+
+### [Organizations]({{ '/guides/organizations' | relative_url }})
+Implement multi-tenant functionality with organizations, roles, and permissions.
+
+### [Customization]({{ '/guides/customization' | relative_url }})
+Customize the appearance and behavior of Clerk's UI components to match your brand.
+
+### [Session Tokens]({{ '/guides/session-tokens' | relative_url }})
+Work with JWT session tokens for authenticated API requests.
+
+### [Error Handling]({{ '/guides/error-handling' | relative_url }})
+Handle authentication errors and provide great user experiences.
+
+### [Backend Integration]({{ '/guides/backend-integration' | relative_url }})
+Integrate Clerk with your backend services and APIs.
+
+---
+
+## Quick Navigation
+
+- **Getting Started?** Check out the [Dart Quickstart]({{ '/getting-started/quickstart-dart' | relative_url }}) or [Flutter Quickstart]({{ '/getting-started/quickstart-flutter' | relative_url }})
+- **Need API Reference?** See the [API Documentation]({{ '/api' | relative_url }})
+- **Looking for Examples?** Browse the [GitHub Examples](https://github.com/clerk/clerk-sdk-flutter/tree/main/packages/clerk_flutter/example)
+
diff --git a/docs/guides/authentication.md b/docs/guides/authentication.md
new file mode 100644
index 00000000..e8185c32
--- /dev/null
+++ b/docs/guides/authentication.md
@@ -0,0 +1,370 @@
+---
+layout: default
+title: Authentication
+parent: Guides
+nav_order: 1
+---
+
+# Authentication Flows
+{: .no_toc }
+
+Learn how to implement various authentication strategies with Clerk's Dart and Flutter SDKs.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+Clerk supports multiple authentication strategies to meet your application's needs:
+
+- **Email & Password** - Traditional username/password authentication
+- **Email Code (Passwordless)** - One-time codes sent via email
+- **Phone Code (Passwordless)** - One-time codes sent via SMS
+- **OAuth** - Social login with Google, GitHub, Facebook, and more
+- **Multi-Factor Authentication (MFA)** - Additional security layer
+
+---
+
+## Email and Password Authentication
+
+### Sign In
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future signInWithPassword(Auth auth, String email, String password) async {
+ try {
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: email,
+ password: password,
+ );
+
+ print('✅ Signed in as: ${auth.user?.emailAddress}');
+ } on ClerkApiException catch (e) {
+ print('❌ Sign in failed: ${e.message}');
+ // Handle specific error codes
+ if (e.errors.any((err) => err.code == 'form_password_incorrect')) {
+ print('Incorrect password');
+ }
+ }
+}
+```
+
+### Sign Up
+
+```dart
+Future signUpWithPassword(
+ Auth auth,
+ String email,
+ String password,
+ {String? firstName, String? lastName}
+) async {
+ try {
+ await auth.attemptSignUp(
+ strategy: Strategy.password,
+ identifier: email,
+ password: password,
+ firstName: firstName,
+ lastName: lastName,
+ );
+
+ // Check if email verification is required
+ if (auth.signUp?.verification?.status == VerificationStatus.unverified) {
+ print('📧 Verification email sent to $email');
+ // Proceed to verification step
+ } else {
+ print('✅ Sign up successful!');
+ }
+ } on ClerkApiException catch (e) {
+ print('❌ Sign up failed: ${e.message}');
+ }
+}
+```
+
+### Email Verification
+
+```dart
+Future verifyEmail(Auth auth, String code) async {
+ try {
+ await auth.attemptSignUpVerification(
+ strategy: Strategy.emailCode,
+ code: code,
+ );
+
+ print('✅ Email verified! User is now signed in.');
+ } on ClerkApiException catch (e) {
+ print('❌ Verification failed: ${e.message}');
+ }
+}
+```
+
+---
+
+## Passwordless Authentication
+
+### Email Code (Magic Link)
+
+```dart
+Future signInWithEmailCode(Auth auth, String email) async {
+ try {
+ // Step 1: Request the code
+ await auth.attemptSignIn(
+ strategy: Strategy.emailCode,
+ identifier: email,
+ );
+
+ print('📧 Verification code sent to $email');
+
+ // Step 2: User enters the code from their email
+ final code = '123456'; // Get from user input
+
+ await auth.attemptSignInVerification(
+ strategy: Strategy.emailCode,
+ code: code,
+ );
+
+ print('✅ Signed in successfully!');
+ } on ClerkApiException catch (e) {
+ print('❌ Error: ${e.message}');
+ }
+}
+```
+
+### Phone Code (SMS)
+
+```dart
+Future signInWithPhoneCode(Auth auth, String phoneNumber) async {
+ try {
+ // Step 1: Request the SMS code
+ await auth.attemptSignIn(
+ strategy: Strategy.phoneCode,
+ identifier: phoneNumber, // Format: +1234567890
+ );
+
+ print('📱 SMS code sent to $phoneNumber');
+
+ // Step 2: User enters the code from SMS
+ final code = '123456'; // Get from user input
+
+ await auth.attemptSignInVerification(
+ strategy: Strategy.phoneCode,
+ code: code,
+ );
+
+ print('✅ Signed in successfully!');
+ } on ClerkApiException catch (e) {
+ print('❌ Error: ${e.message}');
+ }
+}
+```
+
+---
+
+## OAuth Authentication
+
+### Flutter OAuth Flow
+
+For Flutter applications, use the built-in OAuth support:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class OAuthSignInPage extends StatelessWidget {
+ const OAuthSignInPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Center(
+ child: ClerkAuthentication(),
+ ),
+ );
+ }
+}
+```
+
+The `ClerkAuthentication` widget automatically displays configured OAuth providers.
+
+### Custom OAuth Button
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class CustomOAuthButton extends StatelessWidget {
+ const CustomOAuthButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final authState = ClerkAuth.of(context);
+
+ return ElevatedButton.icon(
+ icon: Icon(Icons.login),
+ label: Text('Sign in with Google'),
+ onPressed: () async {
+ try {
+ await authState.attemptSignIn(
+ strategy: Strategy.oauth(OAuthProvider.google),
+ );
+ } catch (e) {
+ print('OAuth error: $e');
+ }
+ },
+ );
+ }
+}
+```
+
+### Supported OAuth Providers
+
+Clerk supports the following OAuth providers:
+
+- Google (`OAuthProvider.google`)
+- GitHub (`OAuthProvider.github`)
+- Facebook (`OAuthProvider.facebook`)
+- Microsoft (`OAuthProvider.microsoft`)
+- Apple (`OAuthProvider.apple`)
+- Discord (`OAuthProvider.discord`)
+- Twitter/X (`OAuthProvider.twitter`)
+- LinkedIn (`OAuthProvider.linkedin`)
+- And many more...
+
+---
+
+## Multi-Factor Authentication (MFA)
+
+### Enable MFA for a User
+
+```dart
+Future enableMFA(Auth auth) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ try {
+ // Generate TOTP secret
+ final totp = await user.createTOTP();
+
+ print('Scan this QR code: ${totp.qrCodeUrl}');
+ print('Or enter this secret: ${totp.secret}');
+
+ // User scans QR code and enters verification code
+ final code = '123456'; // Get from user input
+
+ await totp.verify(code: code);
+
+ print('✅ MFA enabled successfully!');
+ } catch (e) {
+ print('❌ MFA setup failed: $e');
+ }
+}
+```
+
+### Sign In with MFA
+
+```dart
+Future signInWithMFA(Auth auth, String email, String password) async {
+ try {
+ // Step 1: Initial sign-in
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: email,
+ password: password,
+ );
+
+ // Step 2: Check if MFA is required
+ if (auth.signIn?.secondFactor?.status == VerificationStatus.unverified) {
+ print('🔐 MFA code required');
+
+ // User enters their TOTP code
+ final mfaCode = '123456'; // Get from user input
+
+ await auth.attemptSignInVerification(
+ strategy: Strategy.totp,
+ code: mfaCode,
+ );
+ }
+
+ print('✅ Signed in with MFA!');
+ } catch (e) {
+ print('❌ Sign in failed: $e');
+ }
+}
+```
+
+---
+
+## Password Reset
+
+```dart
+Future resetPassword(Auth auth, String email) async {
+ try {
+ // Step 1: Request password reset
+ await auth.resetPassword(email: email);
+
+ print('📧 Password reset email sent to $email');
+
+ // Step 2: User clicks link in email and enters new password
+ // This typically happens in a web view or separate flow
+
+ } catch (e) {
+ print('❌ Password reset failed: $e');
+ }
+}
+```
+
+---
+
+## Session Management
+
+### Check Authentication Status
+
+```dart
+bool isSignedIn(Auth auth) {
+ return auth.user != null;
+}
+```
+
+### Get Current Session
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+Session? getCurrentSession(Auth auth) {
+ return auth.client.activeSession;
+}
+```
+
+### Sign Out
+
+```dart
+Future signOut(Auth auth) async {
+ await auth.signOut();
+ print('👋 Signed out successfully');
+}
+```
+
+### Sign Out of Specific Session
+
+```dart
+Future signOutOfSession(Auth auth, Session session) async {
+ await auth.signOutOf(session);
+ print('👋 Signed out of session: ${session.id}');
+}
+```
+
+---
+
+## Next Steps
+
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Manage user profiles and data
+- [Session Tokens]({{ '/guides/session-tokens' | relative_url }}) - Work with JWT tokens
+- [Error Handling]({{ '/guides/error-handling' | relative_url }}) - Handle authentication errors
+- [Organizations]({{ '/guides/organizations' | relative_url }}) - Multi-tenant authentication
+
diff --git a/docs/guides/backend-integration.md b/docs/guides/backend-integration.md
new file mode 100644
index 00000000..572e646b
--- /dev/null
+++ b/docs/guides/backend-integration.md
@@ -0,0 +1,567 @@
+---
+layout: default
+title: Backend Integration
+parent: Guides
+nav_order: 7
+---
+
+# Backend Integration
+{: .no_toc }
+
+Learn how to integrate Clerk authentication with your backend services and verify session tokens.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+When building applications with Clerk, you'll often need to:
+
+- Verify session tokens on your backend
+- Access user information server-side
+- Implement protected API endpoints
+- Manage users from your backend
+
+---
+
+## Verifying Session Tokens
+
+Session tokens are JWTs that can be verified using Clerk's public keys.
+
+### Using Clerk Backend SDK
+
+The recommended approach is to use Clerk's backend SDK for your server language:
+
+**Node.js/Express:**
+```javascript
+import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node';
+
+app.get('/api/protected',
+ ClerkExpressRequireAuth(),
+ (req, res) => {
+ const userId = req.auth.userId;
+ res.json({ message: 'Protected data', userId });
+ }
+);
+```
+
+**Python/Flask:**
+```python
+from clerk_backend_api import Clerk
+
+clerk = Clerk(bearer_auth="sk_live_xxxxx")
+
+@app.route('/api/protected')
+def protected():
+ token = request.headers.get('Authorization').replace('Bearer ', '')
+
+ try:
+ session = clerk.sessions.verify_token(token)
+ return {'message': 'Protected data', 'userId': session.user_id}
+ except Exception as e:
+ return {'error': 'Unauthorized'}, 401
+```
+
+---
+
+## Manual JWT Verification
+
+If you need to manually verify JWTs:
+
+### 1. Get Clerk's Public Keys
+
+Clerk's public keys are available at:
+```
+https://[your-frontend-api]/.well-known/jwks.json
+```
+
+Example:
+```
+https://clerk.example.com/.well-known/jwks.json
+```
+
+### 2. Verify the JWT
+
+**Node.js Example:**
+```javascript
+import jwt from 'jsonwebtoken';
+import jwksClient from 'jwks-rsa';
+
+const client = jwksClient({
+ jwksUri: 'https://clerk.example.com/.well-known/jwks.json'
+});
+
+function getKey(header, callback) {
+ client.getSigningKey(header.kid, (err, key) => {
+ const signingKey = key.publicKey || key.rsaPublicKey;
+ callback(null, signingKey);
+ });
+}
+
+function verifyToken(token) {
+ return new Promise((resolve, reject) => {
+ jwt.verify(token, getKey, {
+ algorithms: ['RS256']
+ }, (err, decoded) => {
+ if (err) reject(err);
+ else resolve(decoded);
+ });
+ });
+}
+
+// Usage
+app.get('/api/protected', async (req, res) => {
+ const token = req.headers.authorization?.replace('Bearer ', '');
+
+ try {
+ const payload = await verifyToken(token);
+ res.json({ userId: payload.sub });
+ } catch (err) {
+ res.status(401).json({ error: 'Unauthorized' });
+ }
+});
+```
+
+---
+
+## Token Claims
+
+A verified Clerk session token contains these claims:
+
+```json
+{
+ "sub": "user_2abc123", // User ID
+ "sid": "sess_xyz789", // Session ID
+ "iat": 1616239022, // Issued at
+ "exp": 1616242622, // Expires at
+ "azp": "https://example.com", // Authorized party
+ "org_id": "org_456", // Organization ID (if applicable)
+ "org_role": "admin", // Organization role (if applicable)
+ "org_permissions": ["read", "write"] // Permissions (if applicable)
+}
+```
+
+---
+
+
+---
+
+## Protecting API Endpoints
+
+### Example: Express.js Middleware
+
+```javascript
+import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node';
+
+// Protect a single route
+app.get('/api/user/profile',
+ ClerkExpressRequireAuth(),
+ (req, res) => {
+ const userId = req.auth.userId;
+ res.json({ userId, message: 'Protected data' });
+ }
+);
+
+// Protect multiple routes
+app.use('/api/admin', ClerkExpressRequireAuth());
+
+app.get('/api/admin/users', (req, res) => {
+ // Only accessible with valid session token
+ res.json({ users: [] });
+});
+```
+
+### Example: Python/FastAPI
+
+```python
+from fastapi import FastAPI, Depends, HTTPException
+from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
+from clerk_backend_api import Clerk
+
+app = FastAPI()
+security = HTTPBearer()
+clerk = Clerk(bearer_auth="sk_live_xxxxx")
+
+async def verify_clerk_token(
+ credentials: HTTPAuthorizationCredentials = Depends(security)
+):
+ try:
+ session = clerk.sessions.verify_token(credentials.credentials)
+ return session
+ except Exception:
+ raise HTTPException(status_code=401, detail="Unauthorized")
+
+@app.get("/api/protected")
+async def protected_route(session = Depends(verify_clerk_token)):
+ return {"userId": session.user_id, "message": "Protected data"}
+```
+
+---
+
+## Organization-Based Access Control
+
+Verify organization membership and roles:
+
+### Node.js Example
+
+```javascript
+import { clerkClient } from '@clerk/clerk-sdk-node';
+
+app.get('/api/org/:orgId/data',
+ ClerkExpressRequireAuth(),
+ async (req, res) => {
+ const { userId, orgId, orgRole } = req.auth;
+ const requestedOrgId = req.params.orgId;
+
+ // Verify user belongs to the organization
+ if (orgId !== requestedOrgId) {
+ return res.status(403).json({ error: 'Forbidden' });
+ }
+
+ // Check role-based permissions
+ if (orgRole === 'admin') {
+ // Admin-only data
+ return res.json({ data: 'Admin data' });
+ } else {
+ // Member data
+ return res.json({ data: 'Member data' });
+ }
+ }
+);
+```
+
+### Dart Backend Example
+
+```dart
+import 'package:clerk_backend_api/clerk_backend_api.dart';
+import 'package:shelf/shelf.dart';
+
+Future handleOrgRequest(Request request) async {
+ final token = request.headers['authorization']?.replaceFirst('Bearer ', '');
+
+ if (token == null) {
+ return Response.forbidden('No token provided');
+ }
+
+ try {
+ // Verify token and get claims
+ final session = await clerk.sessions.verifyToken(token);
+ final orgId = session.organizationId;
+ final orgRole = session.organizationRole;
+
+ // Check organization access
+ if (orgId != request.params['orgId']) {
+ return Response.forbidden('Access denied');
+ }
+
+ // Role-based logic
+ if (orgRole == 'admin') {
+ return Response.ok('Admin data');
+ } else {
+ return Response.ok('Member data');
+ }
+
+ } catch (e) {
+ return Response.forbidden('Invalid token');
+ }
+}
+```
+
+---
+
+## Managing Users from Backend
+
+Use the Clerk Backend API to manage users server-side:
+
+### Create User
+
+```dart
+import 'package:clerk_backend_api/clerk_backend_api.dart';
+
+final clerk = Clerk(
+ security: Security(bearerAuth: 'sk_live_xxxxxxxxxxxxx'),
+);
+
+// Create a new user
+final user = await clerk.users.createUser(
+ request: CreateUserRequestBody(
+ emailAddress: ['user@example.com'],
+ password: 'securePassword123',
+ firstName: 'John',
+ lastName: 'Doe',
+ ),
+);
+
+print('Created user: ${user.id}');
+```
+
+### Update User
+
+```dart
+// Update user metadata
+final updatedUser = await clerk.users.updateUser(
+ userId: 'user_123',
+ request: UpdateUserRequestBody(
+ publicMetadata: {
+ 'plan': 'premium',
+ 'credits': 100,
+ },
+ ),
+);
+```
+
+### Delete User
+
+```dart
+// Delete a user
+await clerk.users.deleteUser(userId: 'user_123');
+```
+
+---
+
+## Session Management
+
+### List User Sessions
+
+```dart
+// Get all sessions for a user
+final sessions = await clerk.sessions.getSessionList(
+ userId: 'user_123',
+);
+
+for (final session in sessions.data) {
+ print('Session: ${session.id}');
+ print('Last active: ${session.lastActiveAt}');
+}
+```
+
+### Revoke Session
+
+```dart
+// Revoke a specific session
+await clerk.sessions.revokeSession(sessionId: 'sess_xyz789');
+
+// This will sign the user out of that session
+```
+
+---
+
+## Webhooks
+
+Clerk can send webhooks to your backend when events occur:
+
+### Common Webhook Events
+
+- `user.created` - New user signed up
+- `user.updated` - User profile updated
+- `user.deleted` - User deleted
+- `session.created` - New session started
+- `session.ended` - Session ended
+- `organization.created` - Organization created
+- `organizationMembership.created` - User joined organization
+
+### Verifying Webhooks
+
+```javascript
+import { Webhook } from 'svix';
+
+app.post('/api/webhooks/clerk', async (req, res) => {
+ const webhookSecret = process.env.CLERK_WEBHOOK_SECRET;
+ const headers = req.headers;
+ const payload = req.body;
+
+ const wh = new Webhook(webhookSecret);
+
+ try {
+ const evt = wh.verify(JSON.stringify(payload), {
+ 'svix-id': headers['svix-id'],
+ 'svix-timestamp': headers['svix-timestamp'],
+ 'svix-signature': headers['svix-signature'],
+ });
+
+ // Handle the event
+ switch (evt.type) {
+ case 'user.created':
+ console.log('New user:', evt.data.id);
+ break;
+ case 'user.updated':
+ console.log('User updated:', evt.data.id);
+ break;
+ }
+
+ res.json({ received: true });
+ } catch (err) {
+ res.status(400).json({ error: 'Invalid signature' });
+ }
+});
+```
+
+---
+
+## Best Practices
+
+### 1. Always Verify Tokens Server-Side
+
+```dart
+// ❌ DON'T: Trust client-provided user IDs
+app.get('/api/user/:userId/data', (req, res) => {
+ const userId = req.params.userId; // Can be forged!
+ // ...
+});
+
+// ✅ DO: Get user ID from verified token
+app.get('/api/user/data',
+ ClerkExpressRequireAuth(),
+ (req, res) => {
+ const userId = req.auth.userId; // From verified JWT
+ // ...
+ }
+);
+```
+
+### 2. Use Secret Keys Securely
+
+```dart
+// ✅ DO: Use environment variables
+final clerk = Clerk(
+ security: Security(
+ bearerAuth: Platform.environment['CLERK_SECRET_KEY']!,
+ ),
+);
+
+// ❌ DON'T: Hardcode secret keys
+final clerk = Clerk(
+ security: Security(bearerAuth: 'sk_live_xxxxx'), // Never do this!
+);
+```
+
+### 3. Implement Rate Limiting
+
+```javascript
+import rateLimit from 'express-rate-limit';
+
+const limiter = rateLimit({
+ windowMs: 15 * 60 * 1000, // 15 minutes
+ max: 100 // limit each IP to 100 requests per windowMs
+});
+
+app.use('/api/', limiter);
+```
+
+### 4. Log Security Events
+
+```dart
+void logSecurityEvent(String event, Map data) {
+ print('[SECURITY] $event: ${json.encode(data)}');
+ // Send to logging service (e.g., Sentry, CloudWatch)
+}
+
+// Usage
+try {
+ final session = await clerk.sessions.verifyToken(token);
+ logSecurityEvent('token_verified', {'userId': session.userId});
+} catch (e) {
+ logSecurityEvent('token_verification_failed', {'error': e.toString()});
+}
+```
+
+---
+
+## Next Steps
+
+- [Session Tokens]({{ '/guides/session-tokens' | relative_url }}) - Understanding JWT tokens
+- [Organizations]({{ '/guides/organizations' | relative_url }}) - Multi-tenant access control
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Client-side user operations
+- [Error Handling]({{ '/guides/error-handling' | relative_url }}) - Handle backend errors gracefully
+
+
+## Sending Tokens from Client
+
+### From Dart (clerk_auth)
+
+```dart
+import 'package:http/http.dart' as http;
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future callProtectedApi(Auth auth) async {
+ final token = await auth.sessionTokenStream.first;
+
+ if (token == null) {
+ throw Exception('Not authenticated');
+ }
+
+ final response = await http.get(
+ Uri.parse('https://api.example.com/protected'),
+ headers: {
+ 'Authorization': 'Bearer $token',
+ },
+ );
+
+ print('Response: ${response.body}');
+}
+```
+
+### From Flutter (clerk_flutter)
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class ApiService {
+ Future fetchData(BuildContext context) async {
+ final authState = ClerkAuth.of(context);
+ final token = await authState.sessionTokenStream.first;
+
+ if (token == null) {
+ throw Exception('Not authenticated');
+ }
+
+ final response = await http.get(
+ Uri.parse('https://api.example.com/protected'),
+ headers: {
+ 'Authorization': 'Bearer $token',
+ },
+ );
+ }
+}
+```
+
+---
+
+## Using Clerk Backend API
+
+For advanced backend operations, use the Clerk Backend API:
+
+### Available Operations
+
+- **Users**: Create, update, delete users
+- **Sessions**: List, revoke sessions
+- **Organizations**: Manage organizations and memberships
+- **Invitations**: Send and manage invitations
+
+### Dart Backend API Client
+
+```dart
+import 'package:clerk_backend_api/clerk_backend_api.dart';
+
+final clerk = Clerk(
+ security: Security(bearerAuth: 'sk_live_xxxxxxxxxxxxx'),
+);
+
+// Get user by ID
+final user = await clerk.users.getUser(userId: 'user_123');
+print('User: ${user.emailAddress}');
+
+// List all users
+final users = await clerk.users.getUserList();
+for (final user in users.data) {
+ print('User: ${user.emailAddress}');
+}
+```
+
+
diff --git a/docs/guides/customization.md b/docs/guides/customization.md
new file mode 100644
index 00000000..379fadd6
--- /dev/null
+++ b/docs/guides/customization.md
@@ -0,0 +1,461 @@
+---
+layout: default
+title: Customization
+parent: Guides
+nav_order: 4
+---
+
+# Customization
+{: .no_toc }
+
+Learn how to customize the appearance and behavior of Clerk's Flutter UI components to match your brand.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+Clerk's Flutter SDK provides extensive customization options through:
+
+- **ClerkTheme** - Theme extension for colors, typography, and spacing
+- **Widget Properties** - Customize individual widget behavior
+- **Custom Builders** - Build your own authentication UI
+
+---
+
+## Theming with ClerkTheme
+
+### Basic Theme Setup
+
+Apply a custom theme to your Clerk components:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ ),
+ child: MaterialApp(
+ title: 'My App',
+ theme: ThemeData.light().copyWith(
+ extensions: [
+ ClerkTheme(
+ colors: ClerkColors.light(
+ primary: Colors.blue,
+ background: Colors.white,
+ text: Colors.black87,
+ ),
+ ),
+ ],
+ ),
+ darkTheme: ThemeData.dark().copyWith(
+ extensions: [
+ ClerkTheme(
+ colors: ClerkColors.dark(
+ primary: Colors.blueAccent,
+ background: Colors.grey[900]!,
+ text: Colors.white,
+ ),
+ ),
+ ],
+ ),
+ home: const HomePage(),
+ ),
+ );
+ }
+}
+```
+
+### Custom Colors
+
+Define a complete custom color scheme:
+
+```dart
+ClerkTheme(
+ colors: ClerkColors(
+ primary: Color(0xFF6366F1), // Primary brand color
+ secondary: Color(0xFF8B5CF6), // Secondary accent
+ background: Color(0xFFFFFFFF), // Background color
+ altBackground: Color(0xFFF9FAFB), // Alternative background
+ text: Color(0xFF111827), // Primary text
+ textSecondary: Color(0xFF6B7280), // Secondary text
+ border: Color(0xFFE5E7EB), // Border color
+ error: Color(0xFFEF4444), // Error color
+ success: Color(0xFF10B981), // Success color
+ warning: Color(0xFFF59E0B), // Warning color
+ ),
+)
+```
+
+### Typography Customization
+
+Customize text styles:
+
+```dart
+ClerkTheme(
+ typography: ClerkTypography(
+ headlineLarge: TextStyle(
+ fontSize: 32,
+ fontWeight: FontWeight.bold,
+ fontFamily: 'YourCustomFont',
+ ),
+ headlineMedium: TextStyle(
+ fontSize: 24,
+ fontWeight: FontWeight.w600,
+ ),
+ bodyLarge: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.normal,
+ ),
+ bodyMedium: TextStyle(
+ fontSize: 14,
+ ),
+ labelLarge: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ ),
+ ),
+)
+```
+
+---
+
+## Customizing Individual Widgets
+
+### ClerkAuthentication Widget
+
+Customize the authentication flow:
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+ClerkAuthentication(
+ // Customize which strategies are shown
+ // (Note: This depends on your Clerk Dashboard configuration)
+
+ // Add custom styling
+ // The widget respects your ClerkTheme configuration
+)
+```
+
+### ClerkUserButton Widget
+
+Customize the user button:
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+ClerkUserButton(
+ showName: true, // Show user's name next to avatar
+
+ // Add custom actions
+ sessionActions: [
+ ClerkUserAction(
+ label: 'Custom Action',
+ icon: Icons.star,
+ onPressed: (context, authState) {
+ // Handle custom action
+ print('Custom action pressed');
+ },
+ ),
+ ],
+
+ // Add additional menu items
+ additionalActions: [
+ ClerkUserAction(
+ label: 'Settings',
+ icon: Icons.settings,
+ onPressed: (context, authState) {
+ Navigator.push(
+ context,
+ MaterialPageRoute(builder: (_) => SettingsPage()),
+ );
+ },
+ ),
+ ClerkUserAction(
+ label: 'Help',
+ icon: Icons.help,
+ onPressed: (context, authState) {
+ // Show help dialog
+ },
+ ),
+ ],
+)
+```
+
+---
+
+## Building Custom Authentication UI
+
+### Custom Sign-In Form
+
+Build your own sign-in UI using the Auth API:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class CustomSignInForm extends StatefulWidget {
+ const CustomSignInForm({super.key});
+
+ @override
+ State createState() => _CustomSignInFormState();
+}
+
+class _CustomSignInFormState extends State {
+ final _emailController = TextEditingController();
+ final _passwordController = TextEditingController();
+ bool _isLoading = false;
+ String? _errorMessage;
+
+ @override
+ void dispose() {
+ _emailController.dispose();
+ _passwordController.dispose();
+ super.dispose();
+ }
+
+ Future _signIn() async {
+ setState(() {
+ _isLoading = true;
+ _errorMessage = null;
+ });
+
+ final authState = ClerkAuth.of(context, listen: false);
+
+ try {
+ await authState.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: _emailController.text,
+ password: _passwordController.text,
+ );
+
+ // Success - navigation handled by ClerkAuthBuilder
+ } catch (e) {
+ setState(() {
+ _errorMessage = e.toString();
+ });
+ } finally {
+ setState(() {
+ _isLoading = false;
+ });
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Card(
+ margin: const EdgeInsets.all(16),
+ child: Padding(
+ padding: const EdgeInsets.all(24),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Text(
+ 'Sign In',
+ style: Theme.of(context).textTheme.headlineMedium,
+ textAlign: TextAlign.center,
+ ),
+ const SizedBox(height: 24),
+
+ // Email Field
+ TextField(
+ controller: _emailController,
+ decoration: const InputDecoration(
+ labelText: 'Email',
+ border: OutlineInputBorder(),
+ prefixIcon: Icon(Icons.email),
+ ),
+ keyboardType: TextInputType.emailAddress,
+ enabled: !_isLoading,
+ ),
+ const SizedBox(height: 16),
+
+ // Password Field
+ TextField(
+ controller: _passwordController,
+ decoration: const InputDecoration(
+ labelText: 'Password',
+ border: OutlineInputBorder(),
+ prefixIcon: Icon(Icons.lock),
+ ),
+ obscureText: true,
+ enabled: !_isLoading,
+ ),
+ const SizedBox(height: 24),
+
+ // Error Message
+ if (_errorMessage != null)
+ Padding(
+ padding: const EdgeInsets.only(bottom: 16),
+ child: Text(
+ _errorMessage!,
+ style: TextStyle(color: Theme.of(context).colorScheme.error),
+ textAlign: TextAlign.center,
+ ),
+ ),
+
+ // Sign In Button
+ ElevatedButton(
+ onPressed: _isLoading ? null : _signIn,
+ child: _isLoading
+ ? const SizedBox(
+ height: 20,
+ width: 20,
+ child: CircularProgressIndicator(strokeWidth: 2),
+ )
+ : const Text('Sign In'),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
+```
+
+### Custom OAuth Buttons
+
+Create custom-styled OAuth buttons:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class CustomOAuthButtons extends StatelessWidget {
+ const CustomOAuthButtons({super.key});
+
+ Widget _buildOAuthButton({
+ required BuildContext context,
+ required String label,
+ required IconData icon,
+ required Color color,
+ required OAuthProvider provider,
+ }) {
+ final authState = ClerkAuth.of(context, listen: false);
+
+ return ElevatedButton.icon(
+ icon: Icon(icon),
+ label: Text(label),
+ style: ElevatedButton.styleFrom(
+ backgroundColor: color,
+ foregroundColor: Colors.white,
+ minimumSize: const Size(double.infinity, 48),
+ ),
+ onPressed: () async {
+ try {
+ await authState.attemptSignIn(
+ strategy: Strategy.oauth(provider),
+ );
+ } catch (e) {
+ if (context.mounted) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(content: Text('Sign in failed: $e')),
+ );
+ }
+ }
+ },
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ _buildOAuthButton(
+ context: context,
+ label: 'Continue with Google',
+ icon: Icons.g_mobiledata,
+ color: Colors.red,
+ provider: OAuthProvider.google,
+ ),
+ const SizedBox(height: 12),
+ _buildOAuthButton(
+ context: context,
+ label: 'Continue with GitHub',
+ icon: Icons.code,
+ color: Colors.black,
+ provider: OAuthProvider.github,
+ ),
+ ],
+ );
+ }
+}
+```
+
+---
+
+## Localization
+
+Clerk supports localization through Flutter's localization system:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+import 'package:flutter_localizations/flutter_localizations.dart';
+
+MaterialApp(
+ localizationsDelegates: const [
+ ClerkSdkLocalizations.delegate,
+ GlobalMaterialLocalizations.delegate,
+ GlobalWidgetsLocalizations.delegate,
+ GlobalCupertinoLocalizations.delegate,
+ ],
+ supportedLocales: const [
+ Locale('en', ''), // English
+ // Add more locales as needed
+ ],
+ // ...
+)
+```
+
+---
+
+## Responsive Design
+
+Make your authentication UI responsive:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class ResponsiveAuthPage extends StatelessWidget {
+ const ResponsiveAuthPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Center(
+ child: ConstrainedBox(
+ constraints: const BoxConstraints(maxWidth: 400),
+ child: const ClerkAuthentication(),
+ ),
+ ),
+ );
+ }
+}
+```
+
+---
+
+## Next Steps
+
+- [Widget Reference]({{ '/api/widgets' | relative_url }}) - Complete widget API documentation
+- [ClerkTheme API]({{ '/api/clerk-theme' | relative_url }}) - Detailed theming options
+- [Examples](https://github.com/clerk/clerk-sdk-flutter/tree/main/packages/clerk_flutter/example) - See complete examples
+
diff --git a/docs/guides/error-handling.md b/docs/guides/error-handling.md
new file mode 100644
index 00000000..06faef59
--- /dev/null
+++ b/docs/guides/error-handling.md
@@ -0,0 +1,481 @@
+---
+layout: default
+title: Error Handling
+parent: Guides
+nav_order: 6
+---
+
+# Error Handling
+{: .no_toc }
+
+Learn how to handle authentication errors and provide great user experiences in your Dart and Flutter applications.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+Clerk provides structured error handling through the `ClerkApiException` class. All authentication operations can throw this exception when errors occur.
+
+---
+
+## ClerkApiException
+
+The main exception class for Clerk API errors:
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+try {
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'wrong-password',
+ );
+} on ClerkApiException catch (e) {
+ print('Error: ${e.message}');
+ print('Status Code: ${e.status}');
+
+ // Access individual errors
+ for (final error in e.errors) {
+ print('Code: ${error.code}');
+ print('Message: ${error.message}');
+ print('Field: ${error.meta?.paramName}');
+ }
+}
+```
+
+**Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `message` | `String` | Human-readable error message |
+| `status` | `int?` | HTTP status code |
+| `errors` | `List` | Detailed error information |
+
+---
+
+## ClerkApiError
+
+Individual error details:
+
+```dart
+class ClerkApiError {
+ final String code; // Error code (e.g., 'form_password_incorrect')
+ final String message; // Error message
+ final String? longMessage; // Detailed explanation
+ final ErrorMeta? meta; // Additional metadata
+}
+```
+
+---
+
+## Common Error Codes
+
+### Authentication Errors
+
+| Code | Description | Solution |
+|------|-------------|----------|
+| `form_identifier_not_found` | Email/username not found | User needs to sign up |
+| `form_password_incorrect` | Wrong password | Prompt user to retry or reset password |
+| `form_code_incorrect` | Wrong verification code | Ask user to re-enter code |
+| `verification_expired` | Verification code expired | Send new verification code |
+
+### Validation Errors
+
+| Code | Description | Solution |
+|------|-------------|----------|
+| `form_param_format_invalid` | Invalid format (e.g., email) | Validate input before submission |
+| `form_password_pwned` | Password found in breach database | Require stronger password |
+| `form_password_length_too_short` | Password too short | Show password requirements |
+
+### Rate Limiting
+
+| Code | Description | Solution |
+|------|-------------|----------|
+| `rate_limit_exceeded` | Too many requests | Show cooldown message |
+
+---
+
+## Handling Errors in Dart
+
+### Basic Error Handling
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future signIn(String email, String password) async {
+ try {
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: email,
+ password: password,
+ );
+
+ print('✅ Sign in successful');
+
+ } on ClerkApiException catch (e) {
+ // Handle Clerk-specific errors
+ print('❌ Sign in failed: ${e.message}');
+
+ for (final error in e.errors) {
+ if (error.code == 'form_password_incorrect') {
+ print('Wrong password. Please try again.');
+ } else if (error.code == 'form_identifier_not_found') {
+ print('Account not found. Please sign up.');
+ }
+ }
+
+ } catch (e) {
+ // Handle other errors
+ print('❌ Unexpected error: $e');
+ }
+}
+```
+
+### Field-Specific Errors
+
+```dart
+Map getFieldErrors(ClerkApiException e) {
+ final fieldErrors = {};
+
+ for (final error in e.errors) {
+ final fieldName = error.meta?.paramName;
+ if (fieldName != null) {
+
+
+### Custom Error Display
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class SignInForm extends StatefulWidget {
+ @override
+ _SignInFormState createState() => _SignInFormState();
+}
+
+class _SignInFormState extends State {
+ final _emailController = TextEditingController();
+ final _passwordController = TextEditingController();
+ String? _errorMessage;
+ Map _fieldErrors = {};
+
+ Future _handleSignIn() async {
+ setState(() {
+ _errorMessage = null;
+ _fieldErrors = {};
+ });
+
+ try {
+ final authState = ClerkAuth.of(context);
+
+ await authState.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: _emailController.text,
+ password: _passwordController.text,
+ );
+
+ } on ClerkApiException catch (e) {
+ setState(() {
+ _errorMessage = e.message;
+
+ // Extract field-specific errors
+ for (final error in e.errors) {
+ final field = error.meta?.paramName;
+ if (field != null) {
+ _fieldErrors[field] = error.message;
+ }
+ }
+ });
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ if (_errorMessage != null)
+ Container(
+ padding: EdgeInsets.all(12),
+ color: Colors.red.shade100,
+ child: Text(
+ _errorMessage!,
+ style: TextStyle(color: Colors.red.shade900),
+ ),
+ ),
+
+ TextField(
+ controller: _emailController,
+ decoration: InputDecoration(
+ labelText: 'Email',
+ errorText: _fieldErrors['identifier'],
+ ),
+ ),
+
+ TextField(
+ controller: _passwordController,
+ obscureText: true,
+ decoration: InputDecoration(
+ labelText: 'Password',
+ errorText: _fieldErrors['password'],
+ ),
+ ),
+
+ ElevatedButton(
+ onPressed: _handleSignIn,
+ child: Text('Sign In'),
+ ),
+ ],
+ );
+ }
+}
+```
+
+---
+
+## Error Recovery Strategies
+
+### Password Reset Flow
+
+```dart
+Future handlePasswordError(ClerkApiException e, String identifier) async {
+ for (final error in e.errors) {
+ if (error.code == 'form_password_incorrect') {
+ // Offer password reset
+ print('Forgot your password?');
+
+ try {
+ await auth.resetPassword(identifier: identifier);
+ print('Password reset email sent!');
+ } catch (e) {
+ print('Failed to send reset email: $e');
+ }
+ }
+ }
+}
+```
+
+### Retry with Exponential Backoff
+
+```dart
+Future signInWithRetry(
+ String email,
+ String password, {
+ int maxRetries = 3,
+}) async {
+ int retries = 0;
+
+ while (retries < maxRetries) {
+ try {
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: email,
+ password: password,
+ );
+ return; // Success
+
+ } on ClerkApiException catch (e) {
+ // Check if error is retryable
+ final isRateLimit = e.errors.any((err) =>
+ err.code == 'rate_limit_exceeded'
+ );
+
+ if (isRateLimit && retries < maxRetries - 1) {
+ retries++;
+ final delay = Duration(seconds: pow(2, retries).toInt());
+ print('Rate limited. Retrying in ${delay.inSeconds}s...');
+ await Future.delayed(delay);
+ } else {
+ rethrow; // Not retryable or max retries reached
+ }
+ }
+ }
+}
+```
+
+---
+
+## Logging Errors
+
+### Development Logging
+
+```dart
+void logClerkError(ClerkApiException e) {
+ print('=== Clerk API Error ===');
+ print('Message: ${e.message}');
+ print('Status: ${e.status}');
+ print('Errors:');
+
+ for (final error in e.errors) {
+ print(' - Code: ${error.code}');
+ print(' Message: ${error.message}');
+ print(' Field: ${error.meta?.paramName ?? 'N/A'}');
+ }
+
+ print('=====================');
+}
+
+// Usage
+try {
+ await auth.attemptSignIn(/* ... */);
+} on ClerkApiException catch (e) {
+ logClerkError(e);
+}
+```
+
+### Production Error Tracking
+
+```dart
+import 'package:sentry_flutter/sentry_flutter.dart';
+
+try {
+ await auth.attemptSignIn(/* ... */);
+} on ClerkApiException catch (e, stackTrace) {
+ // Log to error tracking service
+ await Sentry.captureException(
+ e,
+ stackTrace: stackTrace,
+ hint: Hint.withMap({
+ 'error_codes': e.errors.map((err) => err.code).toList(),
+ 'status': e.status,
+ }),
+ );
+
+ // Show user-friendly message
+ showErrorDialog(context, 'Sign in failed. Please try again.');
+}
+```
+
+---
+
+## Best Practices
+
+### 1. Show User-Friendly Messages
+
+```dart
+String getUserFriendlyMessage(ClerkApiException e) {
+ for (final error in e.errors) {
+ switch (error.code) {
+ case 'form_password_incorrect':
+ return 'Incorrect password. Please try again.';
+ case 'form_identifier_not_found':
+ return 'Account not found. Please sign up.';
+ case 'rate_limit_exceeded':
+ return 'Too many attempts. Please try again later.';
+ default:
+ return 'Something went wrong. Please try again.';
+ }
+ }
+ return e.message;
+}
+```
+
+### 2. Validate Before Submission
+
+```dart
+String? validateEmail(String email) {
+ if (email.isEmpty) return 'Email is required';
+ if (!email.contains('@')) return 'Invalid email format';
+ return null;
+}
+
+String? validatePassword(String password) {
+ if (password.isEmpty) return 'Password is required';
+ if (password.length < 8) return 'Password must be at least 8 characters';
+ return null;
+}
+```
+
+### 3. Provide Clear Next Steps
+
+```dart
+void handleSignInError(ClerkApiException e, BuildContext context) {
+ for (final error in e.errors) {
+ if (error.code == 'form_identifier_not_found') {
+ showDialog(
+ context: context,
+ builder: (context) => AlertDialog(
+ title: Text('Account Not Found'),
+ content: Text('Would you like to create an account?'),
+ actions: [
+ TextButton(
+ onPressed: () => Navigator.pop(context),
+ child: Text('Cancel'),
+ ),
+ ElevatedButton(
+ onPressed: () {
+ Navigator.pop(context);
+ Navigator.pushNamed(context, '/sign-up');
+ },
+ child: Text('Sign Up'),
+ ),
+ ],
+ ),
+ );
+ }
+ }
+}
+```
+
+---
+
+## Next Steps
+
+- [Authentication]({{ '/guides/authentication' | relative_url }}) - Implement authentication flows
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Handle user-related errors
+- [Session Tokens]({{ '/guides/session-tokens' | relative_url }}) - Handle token errors
+- [Backend Integration]({{ '/guides/backend-integration' | relative_url }}) - Server-side error handling
+
+ fieldErrors[fieldName] = error.message;
+ }
+ }
+
+ return fieldErrors;
+}
+
+// Usage
+try {
+ await auth.attemptSignUp(/* ... */);
+} on ClerkApiException catch (e) {
+ final errors = getFieldErrors(e);
+
+ if (errors.containsKey('email_address')) {
+ print('Email error: ${errors['email_address']}');
+ }
+ if (errors.containsKey('password')) {
+ print('Password error: ${errors['password']}');
+ }
+}
+```
+
+---
+
+## Handling Errors in Flutter
+
+### Using ClerkErrorListener
+
+The `ClerkErrorListener` widget automatically displays errors:
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: ClerkErrorListener(
+ child: YourWidget(),
+ ),
+ );
+ }
+}
+```
+
+
diff --git a/docs/guides/organizations.md b/docs/guides/organizations.md
new file mode 100644
index 00000000..229fb766
--- /dev/null
+++ b/docs/guides/organizations.md
@@ -0,0 +1,411 @@
+---
+layout: default
+title: Organizations
+parent: Guides
+nav_order: 3
+---
+
+# Organizations
+{: .no_toc }
+
+Learn how to implement multi-tenant functionality with organizations in your Dart and Flutter applications.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+Organizations in Clerk enable you to build multi-tenant applications where users can belong to one or more organizations. Each organization can have:
+
+- Multiple members with different roles
+- Custom permissions and access control
+- Organization-specific metadata
+- Invitations and membership management
+
+---
+
+## Prerequisites
+
+Before using organizations, you need to:
+
+1. **Enable Organizations** in your [Clerk Dashboard](https://dashboard.clerk.com)
+ - Go to your application settings
+ - Navigate to **Organizations**
+ - Enable the Organizations feature
+
+2. **Configure Roles** (optional)
+ - Define custom roles for your organization members
+ - Set up permissions for each role
+
+---
+
+## Accessing Organizations
+
+### In Dart (clerk_auth)
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+void listUserOrganizations(Auth auth) {
+ final user = auth.user;
+
+ if (user == null) {
+ print('No user signed in');
+ return;
+ }
+
+ // Get all organizations the user belongs to
+ final memberships = user.organizationMemberships;
+
+ for (final membership in memberships) {
+ print('Organization: ${membership.organization.name}');
+ print('Role: ${membership.role}');
+ }
+}
+```
+
+### In Flutter (clerk_flutter)
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class OrganizationsPage extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('My Organizations')),
+ body: const ClerkOrganizationList(),
+ );
+ }
+}
+```
+
+---
+
+## Organization Object
+
+The `Organization` object contains information about an organization:
+
+```dart
+final organization = membership.organization;
+
+print('ID: ${organization.id}');
+print('Name: ${organization.name}');
+print('Slug: ${organization.slug}');
+print('Logo: ${organization.imageUrl}');
+print('Created: ${organization.createdAt}');
+```
+
+**Key Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `id` | `String` | Unique organization identifier |
+| `name` | `String` | Organization name |
+| `slug` | `String` | URL-friendly identifier |
+| `imageUrl` | `String?` | Organization logo URL |
+| `createdAt` | `DateTime` | Creation timestamp |
+| `publicMetadata` | `Map` | Public metadata |
+
+---
+
+## Organization Membership
+
+The `OrganizationMembership` object represents a user's membership in an organization:
+
+```dart
+final membership = user.organizationMemberships.first;
+
+print('Organization: ${membership.organization.name}');
+print('Role: ${membership.role}');
+print('Joined: ${membership.createdAt}');
+```
+
+**Key Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `id` | `String` | Membership identifier |
+| `organization` | `Organization` | The organization |
+| `role` | `String` | User's role in the organization |
+| `createdAt` | `DateTime` | When user joined |
+| `publicMetadata` | `Map` | Membership metadata |
+
+---
+
+## Common Organization Roles
+
+Clerk provides default roles for organizations:
+
+- **`admin`** - Full access to organization settings and members
+- **`member`** - Standard member access
+
+You can also define custom roles in your Clerk Dashboard with specific permissions.
+
+
+---
+
+## Switching Active Organization
+
+Users can belong to multiple organizations. You can switch the active organization context:
+
+### In Dart (clerk_auth)
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future switchOrganization(Auth auth, String organizationId) async {
+ try {
+ // Set the active organization
+ await auth.setActiveOrganization(organizationId);
+
+ print('Switched to organization: $organizationId');
+ } catch (e) {
+ print('Failed to switch organization: $e');
+ }
+}
+```
+
+### In Flutter (clerk_flutter)
+
+The `ClerkOrganizationList` widget handles organization switching automatically. When a user selects an organization, it becomes the active organization.
+
+---
+
+## Checking Organization Membership
+
+You can check if a user belongs to a specific organization:
+
+```dart
+bool isUserInOrganization(User user, String organizationId) {
+ return user.organizationMemberships.any(
+ (membership) => membership.organization.id == organizationId,
+ );
+}
+```
+
+Check if user has a specific role:
+
+```dart
+bool isUserAdmin(User user, String organizationId) {
+ final membership = user.organizationMemberships.firstWhere(
+ (m) => m.organization.id == organizationId,
+ orElse: () => null,
+ );
+
+ return membership?.role == 'admin';
+}
+```
+
+---
+
+## Organization Invitations
+
+Organizations can invite new members via email.
+
+{: .note }
+> Organization invitations are managed through the Clerk Dashboard or Backend API. The Dart/Flutter SDKs currently support viewing and accepting invitations.
+
+### Viewing Pending Invitations
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+void listPendingInvitations(User user) {
+ // Check for pending organization invitations
+ final invitations = user.organizationInvitations ?? [];
+
+ for (final invitation in invitations) {
+ print('Invited to: ${invitation.organization.name}');
+ print('Role: ${invitation.role}');
+ print('Invited by: ${invitation.inviterEmail}');
+ }
+}
+```
+
+---
+
+## Multi-Tenant Data Isolation
+
+When building multi-tenant applications, you'll want to scope data to the active organization:
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+class ApiService {
+ final Auth auth;
+
+ ApiService(this.auth);
+
+ Future fetchOrganizationData() async {
+ final user = auth.user;
+ if (user == null) return;
+
+ // Get the active organization
+ final activeOrgId = user.activeOrganizationId;
+
+ if (activeOrgId == null) {
+ print('No active organization');
+ return;
+ }
+
+ // Fetch data scoped to this organization
+ final token = await auth.sessionTokenStream.first;
+
+ // Make API request with organization context
+ // The session token will include organization claims
+ final response = await http.get(
+ Uri.parse('https://api.example.com/org/$activeOrgId/data'),
+ headers: {
+ 'Authorization': 'Bearer $token',
+ },
+ );
+ }
+}
+```
+
+---
+
+## Session Tokens with Organization Claims
+
+When a user has an active organization, the session token includes organization-specific claims:
+
+```dart
+import 'dart:convert';
+import 'package:clerk_auth/clerk_auth.dart';
+
+void printOrganizationClaims(Auth auth) {
+ auth.sessionTokenStream.listen((token) {
+ if (token == null) return;
+
+ // Decode JWT (for demonstration - use a proper JWT library)
+ final parts = token.split('.');
+ if (parts.length != 3) return;
+
+ final payload = json.decode(
+ utf8.decode(base64Url.decode(base64Url.normalize(parts[1]))),
+ );
+
+ print('Organization ID: ${payload['org_id']}');
+ print('Organization Role: ${payload['org_role']}');
+ print('Organization Permissions: ${payload['org_permissions']}');
+ });
+}
+```
+
+---
+
+## Best Practices
+
+### 1. Always Check Active Organization
+
+```dart
+Future performOrganizationAction(Auth auth) async {
+ final user = auth.user;
+
+ if (user?.activeOrganizationId == null) {
+ throw Exception('No active organization selected');
+ }
+
+ // Proceed with organization-scoped action
+}
+```
+
+### 2. Handle Organization Switching
+
+```dart
+class OrganizationAwareWidget extends StatefulWidget {
+ @override
+ _OrganizationAwareWidgetState createState() =>
+ _OrganizationAwareWidgetState();
+}
+
+class _OrganizationAwareWidgetState extends State {
+ String? _currentOrgId;
+
+ @override
+ void initState() {
+ super.initState();
+ _loadOrganizationData();
+ }
+
+ void _loadOrganizationData() {
+ final authState = ClerkAuth.of(context);
+ final newOrgId = authState.user?.activeOrganizationId;
+
+ if (newOrgId != _currentOrgId) {
+ setState(() {
+ _currentOrgId = newOrgId;
+ });
+ // Reload data for new organization
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ child: Text('Current Org: $_currentOrgId'),
+ );
+ }
+}
+```
+
+### 3. Validate Permissions
+
+Always validate organization permissions on your backend, not just in the client:
+
+```dart
+// Client-side check (for UI only)
+bool canEditSettings = user.organizationMemberships
+ .firstWhere((m) => m.organization.id == activeOrgId)
+ .role == 'admin';
+
+// Always verify on backend before performing sensitive operations
+```
+
+---
+
+## Next Steps
+
+- [Authentication]({{ '/guides/authentication' | relative_url }}) - Implement authentication flows
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Manage user profiles
+- [Session Tokens]({{ '/guides/session-tokens' | relative_url }}) - Work with JWT tokens
+- [Backend Integration]({{ '/guides/backend-integration' | relative_url }}) - Verify organization claims on your backend
+
+
+---
+
+## Using ClerkOrganizationList Widget
+
+The `ClerkOrganizationList` widget provides a pre-built UI for managing organizations:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class MyApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ home: Scaffold(
+ appBar: AppBar(title: const Text('Organizations')),
+ body: const ClerkOrganizationList(),
+ ),
+ );
+ }
+}
+```
+
+Features:
+- List all organizations the user belongs to
+- Switch between organizations
+- Create new organizations (if enabled)
+- Leave organizations
+
diff --git a/docs/guides/session-tokens.md b/docs/guides/session-tokens.md
new file mode 100644
index 00000000..59ed0109
--- /dev/null
+++ b/docs/guides/session-tokens.md
@@ -0,0 +1,331 @@
+---
+layout: default
+title: Session Tokens
+parent: Guides
+nav_order: 5
+---
+
+# Session Tokens
+{: .no_toc }
+
+Learn how to work with JWT session tokens for authenticated API requests in your Dart and Flutter applications.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+Clerk uses JSON Web Tokens (JWTs) for session management. These tokens:
+
+- Are automatically generated when a user signs in
+- Contain user and session information
+- Are cryptographically signed by Clerk
+- Can be verified on your backend
+- Automatically refresh to stay valid
+
+---
+
+## Accessing Session Tokens
+
+### In Dart (clerk_auth)
+
+The `clerk_auth` package provides a stream of session tokens:
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+final auth = Auth(
+ config: AuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ ),
+);
+
+await auth.initialize();
+
+// Listen to session token updates
+auth.sessionTokenStream.listen((token) {
+ if (token != null) {
+ print('Session token: $token');
+ // Use for authenticated API requests
+ } else {
+ print('No active session');
+ }
+});
+```
+
+### In Flutter (clerk_flutter)
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ final authState = ClerkAuth.of(context);
+
+ // Access the session token stream
+ return StreamBuilder(
+ stream: authState.sessionTokenStream,
+ builder: (context, snapshot) {
+ final token = snapshot.data;
+
+ if (token == null) {
+ return Text('No session token');
+ }
+
+ return Text('Token available');
+ },
+ );
+ }
+}
+```
+
+---
+
+## Making Authenticated API Requests
+
+Use the session token to authenticate requests to your backend:
+
+```dart
+import 'package:http/http.dart' as http;
+import 'package:clerk_auth/clerk_auth.dart';
+
+class ApiClient {
+ final Auth auth;
+
+ ApiClient(this.auth);
+
+ Future fetchUserData() async {
+ // Get the current session token
+ final token = await auth.sessionTokenStream.first;
+
+ if (token == null) {
+ throw Exception('No active session');
+ }
+
+ // Make authenticated request
+ final response = await http.get(
+ Uri.parse('https://api.example.com/user/profile'),
+ headers: {
+ 'Authorization': 'Bearer $token',
+ 'Content-Type': 'application/json',
+ },
+ );
+
+ return response;
+ }
+}
+```
+
+---
+
+## Session Token Polling
+
+By default, `clerk_auth` automatically polls for fresh session tokens to ensure they remain valid.
+
+### Enable/Disable Polling
+
+```dart
+final auth = Auth(
+ config: AuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ sessionTokenPolling: true, // Enable (default)
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ ),
+);
+```
+
+### Why Polling?
+
+
+
+---
+
+## Token Claims
+
+Common claims in a Clerk session token:
+
+| Claim | Description |
+|-------|-------------|
+| `sub` | User ID (subject) |
+| `sid` | Session ID |
+| `iat` | Issued at timestamp |
+| `exp` | Expiration timestamp |
+| `azp` | Authorized party (your app URL) |
+| `org_id` | Organization ID (if user has active org) |
+| `org_role` | User's role in the organization |
+| `org_permissions` | Array of permissions |
+
+### Decoding Token Claims (Client-Side)
+
+{: .warning }
+> **Security Note:** Never trust client-side token decoding for authorization. Always verify tokens on your backend.
+
+```dart
+import 'dart:convert';
+
+Map decodeJwtPayload(String token) {
+ final parts = token.split('.');
+ if (parts.length != 3) {
+ throw Exception('Invalid JWT');
+ }
+
+ // Decode the payload (second part)
+ final payload = parts[1];
+ final normalized = base64Url.normalize(payload);
+ final decoded = utf8.decode(base64Url.decode(normalized));
+
+ return json.decode(decoded);
+}
+
+// Usage
+final token = await auth.sessionTokenStream.first;
+if (token != null) {
+ final claims = decodeJwtPayload(token);
+ print('User ID: ${claims['sub']}');
+ print('Expires: ${DateTime.fromMillisecondsSinceEpoch(claims['exp'] * 1000)}');
+}
+```
+
+---
+
+## Verifying Tokens on Backend
+
+Always verify session tokens on your backend before trusting them. See the [Backend Integration](/guides/backend-integration) guide for details.
+
+**Quick Example (Node.js):**
+
+```javascript
+import { verifyToken } from '@clerk/backend';
+
+app.get('/api/protected', async (req, res) => {
+ const token = req.headers.authorization?.replace('Bearer ', '');
+
+ try {
+ const payload = await verifyToken(token, {
+ secretKey: process.env.CLERK_SECRET_KEY
+ });
+
+ res.json({ userId: payload.sub });
+ } catch (err) {
+ res.status(401).json({ error: 'Unauthorized' });
+ }
+});
+```
+
+---
+
+## Token Expiration
+
+Session tokens expire after a period of time (default: 1 hour). Clerk automatically handles token refresh through polling.
+
+### Handling Expired Tokens
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future getValidToken(Auth auth) async {
+ final token = await auth.sessionTokenStream.first;
+
+ if (token == null) {
+ throw Exception('No active session');
+ }
+
+ // Token is automatically refreshed by Clerk
+ // Just use the latest token from the stream
+ return token;
+}
+```
+
+---
+
+## Best Practices
+
+### 1. Always Use HTTPS
+
+Session tokens should only be transmitted over HTTPS to prevent interception.
+
+### 2. Store Tokens Securely
+
+The `clerk_auth` package handles token storage securely. Don't store tokens in:
+- Local storage (web)
+- Shared preferences without encryption
+- Plain text files
+
+### 3. Verify on Backend
+
+Never trust client-side token validation. Always verify tokens on your backend:
+
+```dart
+// ❌ DON'T: Trust client-side checks
+if (decodeJwtPayload(token)['exp'] > DateTime.now()) {
+ // Allow access
+}
+
+// ✅ DO: Verify on backend
+final response = await http.get(
+ Uri.parse('https://api.example.com/protected'),
+ headers: {'Authorization': 'Bearer $token'},
+);
+```
+
+### 4. Handle Token Refresh
+
+Let Clerk handle token refresh automatically:
+
+```dart
+// ✅ DO: Use the stream
+auth.sessionTokenStream.listen((token) {
+ // Always get the latest valid token
+ if (token != null) {
+ makeApiRequest(token);
+ }
+});
+
+// ❌ DON'T: Cache tokens manually
+String? cachedToken;
+final token = await auth.sessionTokenStream.first;
+cachedToken = token; // Token might expire!
+```
+
+---
+
+## Next Steps
+
+- [Backend Integration]({{ '/guides/backend-integration' | relative_url }}) - Verify tokens on your backend
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Access user data from tokens
+- [Organizations]({{ '/guides/organizations' | relative_url }}) - Work with organization claims
+- [Error Handling]({{ '/guides/error-handling' | relative_url }}) - Handle token-related errors
+
+- Session tokens expire after a period of time
+- Polling ensures you always have a valid token
+- Clerk automatically refreshes tokens before they expire
+- No manual token refresh logic needed
+
+---
+
+## Token Structure
+
+A Clerk session token is a JWT with three parts:
+
+```
+eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzEyMyIsImlhdCI6MTYxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
+```
+
+**Parts:**
+1. **Header** - Algorithm and token type
+2. **Payload** - Claims (user data, session info)
+3. **Signature** - Cryptographic signature
+
+
diff --git a/docs/guides/user-management.md b/docs/guides/user-management.md
new file mode 100644
index 00000000..cf2b7d37
--- /dev/null
+++ b/docs/guides/user-management.md
@@ -0,0 +1,456 @@
+---
+layout: default
+title: User Management
+parent: Guides
+nav_order: 2
+---
+
+# User Management
+{: .no_toc }
+
+Learn how to manage user profiles, update user information, and handle user data with Clerk's Dart and Flutter SDKs.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+The `User` object contains all account information for a user in your application. Clerk provides comprehensive APIs to:
+
+- Access user profile data
+- Update user information
+- Manage email addresses and phone numbers
+- Upload profile images
+- Handle user metadata
+
+---
+
+## Accessing the Current User
+
+### In Dart (clerk_auth)
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+void printUserInfo(Auth auth) {
+ final user = auth.user;
+
+ if (user == null) {
+ print('No user signed in');
+ return;
+ }
+
+ print('User ID: ${user.id}');
+ print('Email: ${user.emailAddress}');
+ print('Name: ${user.firstName} ${user.lastName}');
+ print('Username: ${user.username}');
+ print('Profile Image: ${user.imageUrl}');
+ print('Created: ${user.createdAt}');
+ print('Updated: ${user.updatedAt}');
+}
+```
+
+### In Flutter (clerk_flutter)
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class UserProfileWidget extends StatelessWidget {
+ const UserProfileWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final authState = ClerkAuth.of(context);
+ final user = authState.user;
+
+ if (user == null) {
+ return const Text('Not signed in');
+ }
+
+ return Column(
+ children: [
+ if (user.imageUrl != null)
+ CircleAvatar(
+ radius: 50,
+ backgroundImage: NetworkImage(user.imageUrl!),
+ ),
+ Text('${user.firstName} ${user.lastName}'),
+ Text(user.emailAddress ?? 'No email'),
+ Text('User ID: ${user.id}'),
+ ],
+ );
+ }
+}
+```
+
+---
+
+## User Properties
+
+The `User` object includes the following properties:
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `id` | `String` | Unique identifier for the user |
+| `firstName` | `String?` | User's first name |
+| `lastName` | `String?` | User's last name |
+| `username` | `String?` | User's username |
+| `emailAddress` | `String?` | Primary email address |
+| `phoneNumber` | `String?` | Primary phone number |
+| `imageUrl` | `String?` | URL to profile image |
+| `hasImage` | `bool` | Whether user has uploaded an image |
+| `primaryEmailAddressId` | `String?` | ID of primary email |
+| `primaryPhoneNumberId` | `String?` | ID of primary phone |
+| `emailAddresses` | `List` | All email addresses |
+| `phoneNumbers` | `List` | All phone numbers |
+| `externalAccounts` | `List` | Connected OAuth accounts |
+| `publicMetadata` | `Map` | Public metadata |
+| `privateMetadata` | `Map` | Private metadata (backend only) |
+| `unsafeMetadata` | `Map` | Unsafe metadata |
+| `createdAt` | `DateTime` | Account creation timestamp |
+| `updatedAt` | `DateTime` | Last update timestamp |
+
+---
+
+## Updating User Profile
+
+### Update Basic Information
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future updateUserProfile(Auth auth) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ try {
+ await user.update(
+ firstName: 'John',
+ lastName: 'Doe',
+ username: 'johndoe',
+ );
+
+ print('✅ Profile updated successfully');
+ } catch (e) {
+ print('❌ Update failed: $e');
+ }
+}
+```
+
+### Update Profile Image
+
+```dart
+import 'dart:io';
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future updateProfileImage(Auth auth, File imageFile) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ try {
+ await user.setProfileImage(imageFile);
+ print('✅ Profile image updated');
+ } catch (e) {
+ print('❌ Image upload failed: $e');
+ }
+}
+```
+
+### In Flutter with Image Picker
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+import 'package:image_picker/image_picker.dart';
+import 'dart:io';
+
+class ProfileImageUploader extends StatelessWidget {
+ const ProfileImageUploader({super.key});
+
+ Future _pickAndUploadImage(BuildContext context) async {
+ final authState = ClerkAuth.of(context, listen: false);
+ final user = authState.user;
+ if (user == null) return;
+
+ final picker = ImagePicker();
+ final pickedFile = await picker.pickImage(source: ImageSource.gallery);
+
+ if (pickedFile != null) {
+ try {
+ await user.setProfileImage(File(pickedFile.path));
+ if (context.mounted) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('Profile image updated!')),
+ );
+ }
+ } catch (e) {
+ if (context.mounted) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(content: Text('Upload failed: $e')),
+ );
+ }
+ }
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return ElevatedButton.icon(
+ icon: const Icon(Icons.upload),
+ label: const Text('Upload Profile Image'),
+ onPressed: () => _pickAndUploadImage(context),
+ );
+ }
+}
+```
+
+---
+
+## Managing Email Addresses
+
+### Add Email Address
+
+```dart
+Future addEmailAddress(Auth auth, String email) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ try {
+ final emailAddress = await user.createEmailAddress(email);
+
+ print('📧 Verification email sent to $email');
+
+ // User enters verification code
+ final code = '123456'; // Get from user input
+
+ await emailAddress.attemptVerification(code: code);
+
+ print('✅ Email address verified and added');
+ } catch (e) {
+ print('❌ Failed to add email: $e');
+ }
+}
+```
+
+### Set Primary Email
+
+```dart
+Future setPrimaryEmail(Auth auth, String emailAddressId) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ try {
+ await user.update(primaryEmailAddressId: emailAddressId);
+ print('✅ Primary email updated');
+ } catch (e) {
+ print('❌ Failed to update primary email: $e');
+ }
+}
+```
+
+### Remove Email Address
+
+```dart
+Future removeEmailAddress(Auth auth, String emailAddressId) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ try {
+ final emailAddress = user.emailAddresses
+ .firstWhere((e) => e.id == emailAddressId);
+
+ await emailAddress.destroy();
+ print('✅ Email address removed');
+ } catch (e) {
+ print('❌ Failed to remove email: $e');
+ }
+}
+```
+
+---
+
+## Managing Phone Numbers
+
+### Add Phone Number
+
+```dart
+Future addPhoneNumber(Auth auth, String phoneNumber) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ try {
+ final phone = await user.createPhoneNumber(phoneNumber);
+
+ print('📱 SMS verification sent to $phoneNumber');
+
+ // User enters verification code
+ final code = '123456'; // Get from user input
+
+ await phone.attemptVerification(code: code);
+
+ print('✅ Phone number verified and added');
+ } catch (e) {
+ print('❌ Failed to add phone: $e');
+ }
+}
+```
+
+---
+
+## User Metadata
+
+Clerk provides three types of metadata:
+
+### Public Metadata
+Visible to the frontend and included in session tokens.
+
+```dart
+Future updatePublicMetadata(Auth auth) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ await user.update(
+ publicMetadata: {
+ 'theme': 'dark',
+ 'language': 'en',
+ 'notifications': true,
+ },
+ );
+}
+```
+
+### Unsafe Metadata
+Editable by the user, visible to the frontend.
+
+```dart
+Future updateUnsafeMetadata(Auth auth) async {
+ final user = auth.user;
+ if (user == null) return;
+
+ await user.update(
+ unsafeMetadata: {
+ 'preferences': {
+ 'newsletter': true,
+ 'marketing': false,
+ },
+ },
+ );
+}
+```
+
+### Private Metadata
+Only accessible from the backend (requires Backend API).
+
+{: .note }
+> Private metadata can only be set using the Backend API, not from client SDKs.
+
+---
+
+## User Profile Component (Flutter)
+
+Here's a complete user profile component:
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class UserProfilePage extends StatelessWidget {
+ const UserProfilePage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final authState = ClerkAuth.of(context);
+ final user = authState.user;
+
+ if (user == null) {
+ return const Scaffold(
+ body: Center(child: Text('Not signed in')),
+ );
+ }
+
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Profile'),
+ actions: const [ClerkUserButton()],
+ ),
+ body: ListView(
+ padding: const EdgeInsets.all(16),
+ children: [
+ // Profile Image
+ Center(
+ child: CircleAvatar(
+ radius: 60,
+ backgroundImage: user.imageUrl != null
+ ? NetworkImage(user.imageUrl!)
+ : null,
+ child: user.imageUrl == null
+ ? Text(
+ user.firstName?.substring(0, 1).toUpperCase() ?? 'U',
+ style: const TextStyle(fontSize: 40),
+ )
+ : null,
+ ),
+ ),
+ const SizedBox(height: 24),
+
+ // Name
+ ListTile(
+ leading: const Icon(Icons.person),
+ title: const Text('Name'),
+ subtitle: Text('${user.firstName ?? ''} ${user.lastName ?? ''}'),
+ ),
+
+ // Email
+ ListTile(
+ leading: const Icon(Icons.email),
+ title: const Text('Email'),
+ subtitle: Text(user.emailAddress ?? 'No email'),
+ ),
+
+ // Username
+ if (user.username != null)
+ ListTile(
+ leading: const Icon(Icons.alternate_email),
+ title: const Text('Username'),
+ subtitle: Text(user.username!),
+ ),
+
+ // Phone
+ if (user.phoneNumber != null)
+ ListTile(
+ leading: const Icon(Icons.phone),
+ title: const Text('Phone'),
+ subtitle: Text(user.phoneNumber!),
+ ),
+
+ // Account Created
+ ListTile(
+ leading: const Icon(Icons.calendar_today),
+ title: const Text('Member Since'),
+ subtitle: Text(
+ '${user.createdAt.year}-${user.createdAt.month}-${user.createdAt.day}',
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
+```
+
+---
+
+## Next Steps
+
+- [Organizations]({{ '/guides/organizations' | relative_url }}) - Multi-tenant user management
+- [Session Tokens]({{ '/guides/session-tokens' | relative_url }}) - Access user data in tokens
+- [Customization]({{ '/guides/customization' | relative_url }}) - Customize user profile UI
+- [Backend Integration]({{ '/guides/backend-integration' | relative_url }}) - Manage users from your backend
+
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..362e1ed4
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,96 @@
+---
+layout: default
+title: Home
+nav_order: 1
+description: "Official documentation for Clerk's Dart and Flutter SDKs - Add complete user management to your Dart and Flutter applications."
+permalink: /
+---
+
+# Clerk Dart & Flutter SDK Documentation
+{: .fs-9 }
+
+Add complete user management to your Dart and Flutter applications in minutes.
+{: .fs-6 .fw-300 }
+
+[Get Started]({{ '/getting-started' | relative_url }}){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }
+[View on GitHub](https://github.com/clerk/clerk-sdk-flutter){: .btn .fs-5 .mb-4 .mb-md-0 }
+
+---
+
+## Beta Notice
+
+{: .warning }
+> ⚠️ **The Clerk Dart and Flutter SDKs are in Beta**
+>
+> Breaking changes should be expected until the first stable release (1.0.0). We recommend pinning to specific versions and reviewing changelogs before upgrading.
+
+---
+
+## Overview
+
+Clerk provides streamlined user experiences for your users to sign up, sign in, and manage their profiles from your Dart and Flutter applications. Our SDKs offer:
+
+- 🔐 **Complete Authentication** - Email, phone, OAuth, passwordless, and multi-factor authentication
+- 👤 **User Management** - Pre-built UI components and headless APIs for user profiles
+- 🏢 **Organizations** - Multi-tenant support with role-based access control
+- 🎨 **Customizable UI** - Beautiful, themeable components that match your brand
+- 📱 **Cross-Platform** - Works on iOS, Android, Web, Windows, macOS, and Linux
+- 🚀 **Production Ready** - Battle-tested infrastructure handling millions of users
+
+---
+
+## Quick Links
+
+### 🚀 Getting Started
+
+- [Installation & Setup]({{ '/getting-started' | relative_url }})
+- [Dart Quickstart]({{ '/getting-started/quickstart-dart' | relative_url }})
+- [Flutter Quickstart]({{ '/getting-started/quickstart-flutter' | relative_url }})
+
+### 📚 Guides
+
+- [Authentication]({{ '/guides/authentication' | relative_url }}) - Authentication flows, OAuth, passwordless, MFA
+- [User Management]({{ '/guides/user-management' | relative_url }}) - Managing user profiles and data
+- [Organizations]({{ '/guides/organizations' | relative_url }}) - Multi-tenant functionality
+- [Customization]({{ '/guides/customization' | relative_url }}) - Theming and styling
+- [Session Tokens]({{ '/guides/session-tokens' | relative_url }}) - Working with JWTs
+- [Error Handling]({{ '/guides/error-handling' | relative_url }}) - Handling errors gracefully
+- [Backend Integration]({{ '/guides/backend-integration' | relative_url }}) - Server-side verification
+
+### 📦 Packages
+
+- [clerk_auth]({{ '/packages/clerk-auth' | relative_url }}) - Dart SDK for backend and CLI applications
+- [clerk_flutter]({{ '/packages/clerk-flutter' | relative_url }}) - Flutter SDK with pre-built UI components
+
+### 🔧 API Reference
+
+- [Widget Reference]({{ '/api/widgets' | relative_url }}) - Complete Flutter widget documentation
+- [clerk_auth API](https://pub.dev/documentation/clerk_auth/latest/) - Dart API documentation
+- [clerk_flutter API](https://pub.dev/documentation/clerk_flutter/latest/) - Flutter API documentation
+
+---
+
+## Requirements
+
+### Dart SDK (clerk_auth)
+- Dart >= 3.6.2
+
+### Flutter SDK (clerk_flutter)
+- Flutter >= 3.27.4
+- Dart >= 3.6.2
+
+---
+
+## Community & Support
+
+- 💬 [Join our Discord](https://clerk.com/discord) - Chat with the community and Clerk team
+- 📖 [Main Clerk Documentation](https://clerk.com/docs) - Comprehensive guides and references
+- 🐛 [Report Issues](https://github.com/clerk/clerk-sdk-flutter/issues) - Bug reports and feature requests
+- 🐦 [Follow us on Twitter](https://twitter.com/ClerkDev) - Latest updates and announcements
+
+---
+
+## License
+
+These SDKs are licensed under the MIT license. See the [LICENSE](https://github.com/clerk/clerk-sdk-flutter/blob/main/LICENSE) file for details.
+
diff --git a/docs/packages/_index.md b/docs/packages/_index.md
new file mode 100644
index 00000000..2c63f99e
--- /dev/null
+++ b/docs/packages/_index.md
@@ -0,0 +1,64 @@
+---
+layout: default
+title: Packages
+nav_order: 4
+has_children: true
+permalink: /packages
+---
+
+# Packages
+
+Official Clerk packages for Dart and Flutter development.
+
+## Available Packages
+
+### [clerk_auth]({{ '/packages/clerk-auth' | relative_url }})
+Pure Dart SDK for backend applications, CLI tools, and server-side Dart applications.
+
+**Features:**
+- Complete authentication API
+- Session management
+- User management
+- Organization support
+- No UI dependencies
+
+**Install:**
+```yaml
+dependencies:
+ clerk_auth: ^0.0.13-beta
+```
+
+---
+
+### [clerk_flutter]({{ '/packages/clerk-flutter' | relative_url }})
+Flutter SDK with pre-built UI components for mobile, web, and desktop applications.
+
+**Features:**
+- Pre-built authentication widgets
+- Material Design integration
+- Customizable themes
+- Cross-platform support
+- Includes clerk_auth
+
+**Install:**
+```yaml
+dependencies:
+ clerk_flutter: ^0.0.13-beta
+```
+
+---
+
+## Quick Links
+
+- [Getting Started]({{ '/getting-started' | relative_url }}) - Installation and setup guides
+- [Guides]({{ '/guides' | relative_url }}) - Implementation guides
+- [API Reference]({{ '/api' | relative_url }}) - Detailed API documentation
+
+---
+
+## External Resources
+
+- [clerk_auth on pub.dev](https://pub.dev/packages/clerk_auth)
+- [clerk_flutter on pub.dev](https://pub.dev/packages/clerk_flutter)
+- [GitHub Repository](https://github.com/clerk/clerk-sdk-flutter)
+
diff --git a/docs/packages/clerk-auth.md b/docs/packages/clerk-auth.md
new file mode 100644
index 00000000..4c5a327a
--- /dev/null
+++ b/docs/packages/clerk-auth.md
@@ -0,0 +1,354 @@
+---
+layout: default
+title: clerk_auth
+parent: Packages
+nav_order: 1
+---
+
+# clerk_auth Package
+{: .no_toc }
+
+The official Clerk Dart SDK for backend and CLI applications.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+The `clerk_auth` package is a pure Dart SDK that provides authentication and user management capabilities for:
+
+- Backend Dart applications
+- CLI tools
+- Server-side applications
+- Any Dart environment
+
+**Package:** [clerk_auth on pub.dev](https://pub.dev/packages/clerk_auth)
+**Version:** 0.0.13-beta
+**Repository:** [GitHub](https://github.com/clerk/clerk-sdk-flutter/tree/main/packages/clerk_auth)
+
+---
+
+## Installation
+
+Add to your `pubspec.yaml`:
+
+```yaml
+dependencies:
+ clerk_auth: ^0.0.13-beta
+```
+
+Then run:
+
+```bash
+dart pub get
+```
+
+---
+
+## Requirements
+
+- Dart >= 3.6.2
+
+---
+
+## Core Classes
+
+### Auth
+
+The main class for managing authentication state.
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+final auth = Auth(
+ config: AuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ ),
+);
+
+await auth.initialize();
+```
+
+**Key Methods:**
+
+| Method | Description |
+|--------|-------------|
+| `initialize()` | Initialize the auth system |
+| `attemptSignIn()` | Start a sign-in attempt |
+| `attemptSignUp()` | Start a sign-up attempt |
+| `attemptSignInVerification()` | Verify a sign-in attempt |
+| `attemptSignUpVerification()` | Verify a sign-up attempt |
+| `signOut()` | Sign out the current user |
+| `signOutOf(Session)` | Sign out of a specific session |
+| `resetPassword()` | Request a password reset |
+| `terminate()` | Clean up resources |
+
+**Key Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `user` | `User?` | Current signed-in user |
+| `client` | `Client` | Client object with sessions |
+| `env` | `Environment` | Environment configuration |
+| `sessionTokenStream` | `Stream` | Stream of session tokens |
+
+---
+
+### AuthConfig
+
+Configuration for the Auth instance.
+
+```dart
+AuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ sessionTokenPolling: true, // Enable automatic token refresh
+ httpService: null, // Optional custom HTTP service
+)
+```
+
+**Properties:**
+
+| Property | Type | Default | Description |
+|----------|------|---------|-------------|
+| `publishableKey` | `String` | Required | Your Clerk publishable key |
+| `persistor` | `Persistor` | Required | Storage mechanism for auth state |
+| `sessionTokenPolling` | `bool` | `true` | Enable automatic token refresh |
+| `httpService` | `HttpService?` | `null` | Custom HTTP service |
+
+---
+
+### User
+
+Represents a user in your application.
+
+```dart
+final user = auth.user;
+
+if (user != null) {
+ print('User ID: ${user.id}');
+ print('Email: ${user.emailAddress}');
+ print('Name: ${user.firstName} ${user.lastName}');
+}
+```
+
+**Key Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `id` | `String` | Unique user identifier |
+| `firstName` | `String?` | First name |
+| `lastName` | `String?` | Last name |
+| `username` | `String?` | Username |
+| `emailAddress` | `String?` | Primary email |
+| `phoneNumber` | `String?` | Primary phone |
+| `imageUrl` | `String?` | Profile image URL |
+| `emailAddresses` | `List` | All email addresses |
+| `phoneNumbers` | `List` | All phone numbers |
+| `publicMetadata` | `Map` | Public metadata |
+| `unsafeMetadata` | `Map` | Unsafe metadata |
+
+**Key Methods:**
+
+| Method | Description |
+|--------|-------------|
+| `update()` | Update user profile |
+| `setProfileImage()` | Upload profile image |
+| `createEmailAddress()` | Add new email address |
+| `createPhoneNumber()` | Add new phone number |
+| `createTOTP()` | Enable MFA |
+
+---
+
+### Strategy
+
+Authentication strategies supported by Clerk.
+
+```dart
+// Password authentication
+Strategy.password
+
+// Email code (passwordless)
+Strategy.emailCode
+
+// Phone code (SMS)
+Strategy.phoneCode
+
+// OAuth
+Strategy.oauth(OAuthProvider.google)
+Strategy.oauth(OAuthProvider.github)
+
+// TOTP (MFA)
+Strategy.totp
+```
+
+---
+
+### Persistor
+
+Interface for persisting authentication state.
+
+**Built-in Persistors:**
+
+```dart
+// Default file-based persistor
+DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+)
+
+// No persistence (in-memory only)
+Persistor.none
+```
+
+**Custom Persistor:**
+
+```dart
+class MyCustomPersistor implements Persistor {
+ @override
+ Future write(String key, T value) async {
+ // Your storage logic
+ }
+
+ @override
+ Future read(String key) async {
+ // Your retrieval logic
+ }
+
+ @override
+ Future delete(String key) async {
+ // Your deletion logic
+ }
+}
+```
+
+---
+
+## Session Token Polling
+
+By default, `clerk_auth` automatically polls for session tokens and provides them via the `sessionTokenStream`.
+
+### Enable/Disable Polling
+
+```dart
+final auth = Auth(
+ config: AuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ sessionTokenPolling: true, // Enable (default)
+ // sessionTokenPolling: false, // Disable
+ ),
+);
+```
+
+### Listen to Session Tokens
+
+```dart
+auth.sessionTokenStream.listen((token) {
+ if (token != null) {
+ print('New session token: $token');
+ // Use for authenticated API requests
+ }
+});
+```
+
+---
+
+## Error Handling
+
+All authentication methods can throw `ClerkApiException`:
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+try {
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'password',
+ );
+} on ClerkApiException catch (e) {
+ print('Error: ${e.message}');
+ print('Status: ${e.status}');
+
+ // Check specific error codes
+ for (final error in e.errors) {
+ print('Code: ${error.code}');
+ print('Message: ${error.message}');
+ }
+}
+```
+
+---
+
+## Examples
+
+### Complete Sign-In Flow
+
+```dart
+import 'dart:io';
+import 'package:clerk_auth/clerk_auth.dart';
+
+Future main() async {
+ final auth = Auth(
+ config: AuthConfig(
+ publishableKey: Platform.environment['CLERK_PUBLISHABLE_KEY']!,
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => Directory.current,
+ ),
+ ),
+ );
+
+ await auth.initialize();
+
+ try {
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'password',
+ );
+
+ print('✅ Signed in as: ${auth.user?.emailAddress}');
+
+ // Use session token for API requests
+ auth.sessionTokenStream.listen((token) {
+ if (token != null) {
+ // Make authenticated requests
+ }
+ });
+
+ } catch (e) {
+ print('❌ Sign in failed: $e');
+ } finally {
+ auth.terminate();
+ }
+}
+```
+
+---
+
+## API Documentation
+
+For complete API documentation, see:
+
+- [pub.dev Documentation](https://pub.dev/documentation/clerk_auth/latest/)
+- [GitHub Repository](https://github.com/clerk/clerk-sdk-flutter/tree/main/packages/clerk_auth)
+
+---
+
+## Next Steps
+
+- [Dart Quickstart]({{ '/getting-started/quickstart-dart' | relative_url }})
+- [Authentication Guide]({{ '/guides/authentication' | relative_url }})
+- [User Management]({{ '/guides/user-management' | relative_url }})
+- [Session Tokens]({{ '/guides/session-tokens' | relative_url }})
+
diff --git a/docs/packages/clerk-flutter.md b/docs/packages/clerk-flutter.md
new file mode 100644
index 00000000..bc4998f6
--- /dev/null
+++ b/docs/packages/clerk-flutter.md
@@ -0,0 +1,434 @@
+---
+layout: default
+title: clerk_flutter
+parent: Packages
+nav_order: 2
+---
+
+# clerk_flutter Package
+{: .no_toc }
+
+The official Clerk Flutter SDK with pre-built UI components.
+{: .fs-6 .fw-300 }
+
+## Table of contents
+{: .no_toc .text-delta }
+
+1. TOC
+{:toc}
+
+---
+
+## Overview
+
+The `clerk_flutter` package provides a complete authentication solution for Flutter applications with:
+
+- Pre-built UI components
+- Material Design integration
+- Cross-platform support (iOS, Android, Web, Desktop)
+- Seamless Flutter integration
+
+**Package:** [clerk_flutter on pub.dev](https://pub.dev/packages/clerk_flutter)
+**Version:** 0.0.13-beta
+**Repository:** [GitHub](https://github.com/clerk/clerk-sdk-flutter/tree/main/packages/clerk_flutter)
+
+---
+
+## Installation
+
+Add to your `pubspec.yaml`:
+
+```yaml
+dependencies:
+ clerk_flutter: ^0.0.13-beta
+```
+
+Then run:
+
+```bash
+flutter pub get
+```
+
+---
+
+## Requirements
+
+- Flutter >= 3.27.4
+- Dart >= 3.6.2
+
+---
+
+## Core Widgets
+
+### ClerkAuth
+
+The root widget that initializes Clerk authentication.
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ ),
+ child: MaterialApp(
+ // Your app
+ ),
+)
+```
+
+**Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `config` | `ClerkAuthConfig` | Configuration object |
+| `child` | `Widget` | Your app widget |
+| `persistor` | `Persistor?` | Custom storage mechanism |
+| `httpService` | `HttpService?` | Custom HTTP service |
+
+---
+
+### ClerkAuthConfig
+
+Configuration for ClerkAuth.
+
+```dart
+ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ redirectionGenerator: (url) => Uri.parse('myapp://oauth'),
+ deepLinkStream: AppLinks().allUriLinkStream.map(
+ (uri) => ClerkDeepLink(uri: uri),
+ ),
+)
+```
+
+**Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `publishableKey` | `String` | Your Clerk publishable key |
+| `redirectionGenerator` | `Function?` | Generate OAuth redirect URLs |
+| `deepLinkStream` | `Stream?` | Handle OAuth callbacks |
+| `loading` | `Widget?` | Widget shown during initialization |
+
+---
+
+### ClerkAuthBuilder
+
+Build different UI based on authentication state.
+
+```dart
+ClerkAuthBuilder(
+ signedInBuilder: (context, authState) {
+ return Text('Welcome, ${authState.user?.firstName}!');
+ },
+ signedOutBuilder: (context, authState) {
+ return const ClerkAuthentication();
+ },
+)
+```
+
+**Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `signedInBuilder` | `AuthWidgetBuilder?` | Builder when user is signed in |
+| `signedOutBuilder` | `AuthWidgetBuilder?` | Builder when user is signed out |
+| `builder` | `AuthWidgetBuilder?` | Fallback builder |
+
+---
+
+### ClerkAuthentication
+
+Pre-built authentication UI with sign-in and sign-up.
+
+```dart
+const ClerkAuthentication()
+```
+
+Features:
+- Email/password sign-in and sign-up
+- OAuth provider buttons
+- Email verification
+- Password reset
+- Automatic error handling
+
+---
+
+### ClerkUserButton
+
+User menu with profile and sign-out options.
+
+```dart
+ClerkUserButton(
+ showName: true,
+ sessionActions: [
+ ClerkUserAction(
+ label: 'Settings',
+ icon: Icons.settings,
+ onPressed: (context, authState) {
+ // Handle action
+ },
+ ),
+ ],
+)
+```
+
+**Properties:**
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `showName` | `bool` | Show user's name |
+| `sessionActions` | `List?` | Custom session actions |
+| `additionalActions` | `List?` | Additional menu items |
+
+---
+
+### ClerkSignedIn / ClerkSignedOut
+
+Conditional rendering based on auth state.
+
+```dart
+ClerkSignedIn(
+ child: Text('Only visible when signed in'),
+)
+
+ClerkSignedOut(
+ child: Text('Only visible when signed out'),
+)
+```
+
+---
+
+### ClerkErrorListener
+
+Listens for authentication errors and displays them.
+
+```dart
+ClerkErrorListener(
+ child: YourWidget(),
+)
+```
+
+---
+
+### ClerkOrganizationList
+
+Display and manage organizations (if enabled).
+
+```dart
+const ClerkOrganizationList()
+```
+
+---
+
+## Accessing Auth State
+
+### Using ClerkAuth.of()
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ final authState = ClerkAuth.of(context);
+ final user = authState.user;
+
+ return Text('Hello, ${user?.firstName}!');
+ }
+}
+```
+
+### ClerkAuthState Properties
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `user` | `User?` | Current user |
+| `client` | `Client` | Client with sessions |
+| `env` | `Environment` | Environment config |
+| `isSignedIn` | `bool` | Whether user is signed in |
+| `sessionTokenStream` | `Stream` | Session token stream |
+
+### ClerkAuthState Methods
+
+| Method | Description |
+|--------|-------------|
+| `attemptSignIn()` | Start sign-in |
+| `attemptSignUp()` | Start sign-up |
+| `signOut()` | Sign out current user |
+| `signOutOf(Session)` | Sign out of specific session |
+
+---
+
+## Theming
+
+### Apply Custom Theme
+
+```dart
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+MaterialApp(
+ theme: ThemeData.light().copyWith(
+ extensions: [
+ ClerkTheme(
+ colors: ClerkColors.light(
+ primary: Colors.blue,
+ background: Colors.white,
+ ),
+ ),
+ ],
+ ),
+)
+```
+
+### ClerkTheme Properties
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `colors` | `ClerkColors` | Color scheme |
+| `typography` | `ClerkTypography?` | Text styles |
+
+---
+
+## Deep Links for OAuth
+
+### Setup Deep Links
+
+1. Add `app_links` package:
+
+```yaml
+dependencies:
+ app_links: ^3.5.1
+```
+
+2. Configure ClerkAuth:
+
+```dart
+import 'package:app_links/app_links.dart';
+
+ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ redirectionGenerator: (url) {
+ return Uri.parse('myapp://oauth-callback');
+ },
+ deepLinkStream: AppLinks().allUriLinkStream.map((uri) {
+ return ClerkDeepLink(uri: uri);
+ }),
+ ),
+ child: MaterialApp(/* ... */),
+)
+```
+
+3. Configure platform-specific deep links:
+
+**Android** (`android/app/src/main/AndroidManifest.xml`):
+```xml
+
+
+
+
+
+
+```
+
+**iOS** (`ios/Runner/Info.plist`):
+```xml
+CFBundleURLTypes
+
+
+ CFBundleURLSchemes
+
+ myapp
+
+
+
+```
+
+---
+
+## Examples
+
+### Complete App Example
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:clerk_flutter/clerk_flutter.dart';
+
+void main() {
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return ClerkAuth(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_xxxxxxxxxxxxx',
+ ),
+ child: MaterialApp(
+ title: 'Clerk Flutter Demo',
+ theme: ThemeData.light(),
+ home: const HomePage(),
+ ),
+ );
+ }
+}
+
+class HomePage extends StatelessWidget {
+ const HomePage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('My App')),
+ body: SafeArea(
+ child: ClerkErrorListener(
+ child: ClerkAuthBuilder(
+ signedInBuilder: (context, authState) {
+ return Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text('Welcome, ${authState.user?.firstName}!'),
+ const SizedBox(height: 20),
+ const ClerkUserButton(showName: true),
+ ],
+ ),
+ );
+ },
+ signedOutBuilder: (context, authState) {
+ return const Center(
+ child: ClerkAuthentication(),
+ );
+ },
+ ),
+ ),
+ ),
+ );
+ }
+}
+```
+
+---
+
+## API Documentation
+
+For complete API documentation, see:
+
+- [pub.dev Documentation](https://pub.dev/documentation/clerk_flutter/latest/)
+- [GitHub Repository](https://github.com/clerk/clerk-sdk-flutter/tree/main/packages/clerk_flutter)
+- [Example App](https://github.com/clerk/clerk-sdk-flutter/tree/main/packages/clerk_flutter/example)
+
+---
+
+## Next Steps
+
+- [Flutter Quickstart]({{ '/getting-started/quickstart-flutter' | relative_url }})
+- [Widget Reference]({{ '/api/widgets' | relative_url }})
+- [Customization Guide]({{ '/guides/customization' | relative_url }})
+- [Authentication Flows]({{ '/guides/authentication' | relative_url }})
+
diff --git a/packages/clerk_auth/README.md b/packages/clerk_auth/README.md
index 8a951f73..c1678cb4 100644
--- a/packages/clerk_auth/README.md
+++ b/packages/clerk_auth/README.md
@@ -10,12 +10,25 @@
[](https://clerk.com/docs)
[](https://twitter.com/intent/follow?screen_name=ClerkDev)
-> ### ⚠️ The Clerk Flutter SDK is in Beta ⚠️
+> ### ⚠️ The Clerk Dart SDK is in Beta ⚠️
> ❗️ Breaking changes should be expected until the first stable release (1.0.0) ❗️
**Clerk helps developers build user management. We provide streamlined user experiences
for your users to sign up, sign in, and manage their profile from your Dart code.**
+---
+
+## 📚 Documentation
+
+**[View Full Documentation →](https://clerk.github.io/clerk-sdk-flutter/packages/clerk-auth)**
+
+- 🚀 [Dart Quickstart](https://clerk.github.io/clerk-sdk-flutter/getting-started/quickstart-dart)
+- 📖 [API Reference](https://pub.dev/documentation/clerk_auth/latest/)
+- 🎯 [Authentication Guide](https://clerk.github.io/clerk-sdk-flutter/guides/authentication)
+- 👤 [User Management](https://clerk.github.io/clerk-sdk-flutter/guides/user-management)
+
+---
+
## Requirements
* Dart >= 3.6.2
@@ -68,7 +81,9 @@ Future main() async {
}
```
-For more details see [Clerk Auth object](https://pub.dev/documentation/clerk_auth/latest/clerk_auth/Auth-class.html)
+For more details see:
+- [Clerk Auth Documentation](https://clerk.github.io/clerk-sdk-flutter/packages/clerk-auth)
+- [API Reference](https://pub.dev/documentation/clerk_auth/latest/clerk_auth/Auth-class.html)
## Session Token Polling
@@ -97,6 +112,18 @@ polling off, enabling it via a `SessionTokenPollMode` object in the config. This
v0.0.13-beta: it is no longer used, and will be deleted in a future version. If you are using it, or relying on
the system defaulting to no polling, please review your code.
+---
+
+## 📖 Learn More
+
+- [Full Documentation](https://clerk.github.io/clerk-sdk-flutter/)
+- [Dart Quickstart](https://clerk.github.io/clerk-sdk-flutter/getting-started/quickstart-dart)
+- [Authentication Guide](https://clerk.github.io/clerk-sdk-flutter/guides/authentication)
+- [User Management](https://clerk.github.io/clerk-sdk-flutter/guides/user-management)
+- [Session Tokens](https://clerk.github.io/clerk-sdk-flutter/guides/session-tokens)
+
+---
+
## License
This SDK is licensed under the MIT license found in the [LICENSE](./LICENSE) file.
diff --git a/packages/clerk_flutter/README.md b/packages/clerk_flutter/README.md
index b54d1aec..64d25269 100644
--- a/packages/clerk_flutter/README.md
+++ b/packages/clerk_flutter/README.md
@@ -16,6 +16,20 @@
**Clerk helps developers build user management. We provide streamlined user experiences
for your users to sign up, sign in, and manage their profile from your Flutter code.**
+---
+
+## 📚 Documentation
+
+**[View Full Documentation →](https://clerk.github.io/clerk-sdk-flutter/packages/clerk-flutter)**
+
+- 🚀 [Flutter Quickstart](https://clerk.github.io/clerk-sdk-flutter/getting-started/quickstart-flutter)
+- 📖 [Widget Reference](https://clerk.github.io/clerk-sdk-flutter/api/widgets)
+- 🎨 [Customization Guide](https://clerk.github.io/clerk-sdk-flutter/guides/customization)
+- 🎯 [Authentication Flows](https://clerk.github.io/clerk-sdk-flutter/guides/authentication)
+- 👤 [User Management](https://clerk.github.io/clerk-sdk-flutter/guides/user-management)
+
+---
+
## Requirements
* Flutter >= 3.27.4
@@ -78,6 +92,19 @@ Add the following line to your `android/app/src/main/AndroidManifest.xml` file:
```
+---
+
+## 📖 Learn More
+
+- [Full Documentation](https://clerk.github.io/clerk-sdk-flutter/)
+- [Flutter Quickstart](https://clerk.github.io/clerk-sdk-flutter/getting-started/quickstart-flutter)
+- [Widget Reference](https://clerk.github.io/clerk-sdk-flutter/api/widgets)
+- [Customization Guide](https://clerk.github.io/clerk-sdk-flutter/guides/customization)
+- [Authentication Flows](https://clerk.github.io/clerk-sdk-flutter/guides/authentication)
+- [Example App](https://github.com/clerk/clerk-sdk-flutter/tree/main/packages/clerk_flutter/example)
+
+---
+
## License
This SDK is licensed under the MIT license found in the [LICENSE](./LICENSE) file.
From a8a2c852a40a3469f489aabe1bda705c59de772b Mon Sep 17 00:00:00 2001
From: Nic Ford
Date: Mon, 16 Mar 2026 17:03:58 +0000
Subject: [PATCH 02/27] fix: add documentation [#341]
---
docs/.gitignore | 8 -
docs/CONTRIBUTING.md | 279 ----
docs/DEPLOYMENT.md | 228 ---
docs/Gemfile | 35 -
docs/README.md | 308 ++--
docs/_config.yml | 78 -
docs/_config_production.yml | 7 -
docs/_sass/color_schemes/clerk.scss | 56 -
docs/_sass/custom/custom.scss | 167 --
docs/_sass/custom/syntax-highlighting.scss | 159 --
docs/api/_index.md | 40 -
docs/api/widgets.md | 304 ----
docs/assets/images/clerk-logo.svg | 7 -
docs/clerk_auth/README.md | 301 ++++
docs/clerk_auth/auth.md | 1447 +++++++++++++++++
docs/clerk_auth/auth_config.md | 520 ++++++
docs/clerk_auth/http_service.md | 657 ++++++++
docs/clerk_auth/persistor.md | 539 ++++++
docs/clerk_flutter/README.md | 525 ++++++
docs/clerk_flutter/clerk_auth.md | 506 ++++++
docs/clerk_flutter/clerk_auth_builder.md | 327 ++++
docs/clerk_flutter/clerk_auth_config.md | 229 +++
docs/clerk_flutter/clerk_authentication.md | 318 ++++
docs/clerk_flutter/clerk_error_listener.md | 277 ++++
docs/clerk_flutter/clerk_organization_list.md | 303 ++++
docs/clerk_flutter/clerk_signed_in.md | 231 +++
docs/clerk_flutter/clerk_signed_out.md | 171 ++
docs/clerk_flutter/clerk_theme.md | 267 +++
docs/clerk_flutter/clerk_user_button.md | 348 ++++
docs/getting-started.md | 133 --
docs/getting-started/quickstart-dart.md | 261 ---
docs/getting-started/quickstart-flutter.md | 390 -----
docs/guides/_index.md | 43 -
docs/guides/authentication.md | 370 -----
docs/guides/backend-integration.md | 567 -------
docs/guides/customization.md | 461 ------
docs/guides/error-handling.md | 481 ------
docs/guides/organizations.md | 411 -----
docs/guides/session-tokens.md | 331 ----
docs/guides/user-management.md | 456 ------
docs/index.md | 96 --
docs/packages/_index.md | 64 -
docs/packages/clerk-auth.md | 354 ----
docs/packages/clerk-flutter.md | 434 -----
44 files changed, 7157 insertions(+), 6337 deletions(-)
delete mode 100644 docs/.gitignore
delete mode 100644 docs/CONTRIBUTING.md
delete mode 100644 docs/DEPLOYMENT.md
delete mode 100644 docs/Gemfile
delete mode 100644 docs/_config.yml
delete mode 100644 docs/_config_production.yml
delete mode 100644 docs/_sass/color_schemes/clerk.scss
delete mode 100644 docs/_sass/custom/custom.scss
delete mode 100644 docs/_sass/custom/syntax-highlighting.scss
delete mode 100644 docs/api/_index.md
delete mode 100644 docs/api/widgets.md
delete mode 100644 docs/assets/images/clerk-logo.svg
create mode 100644 docs/clerk_auth/README.md
create mode 100644 docs/clerk_auth/auth.md
create mode 100644 docs/clerk_auth/auth_config.md
create mode 100644 docs/clerk_auth/http_service.md
create mode 100644 docs/clerk_auth/persistor.md
create mode 100644 docs/clerk_flutter/README.md
create mode 100644 docs/clerk_flutter/clerk_auth.md
create mode 100644 docs/clerk_flutter/clerk_auth_builder.md
create mode 100644 docs/clerk_flutter/clerk_auth_config.md
create mode 100644 docs/clerk_flutter/clerk_authentication.md
create mode 100644 docs/clerk_flutter/clerk_error_listener.md
create mode 100644 docs/clerk_flutter/clerk_organization_list.md
create mode 100644 docs/clerk_flutter/clerk_signed_in.md
create mode 100644 docs/clerk_flutter/clerk_signed_out.md
create mode 100644 docs/clerk_flutter/clerk_theme.md
create mode 100644 docs/clerk_flutter/clerk_user_button.md
delete mode 100644 docs/getting-started.md
delete mode 100644 docs/getting-started/quickstart-dart.md
delete mode 100644 docs/getting-started/quickstart-flutter.md
delete mode 100644 docs/guides/_index.md
delete mode 100644 docs/guides/authentication.md
delete mode 100644 docs/guides/backend-integration.md
delete mode 100644 docs/guides/customization.md
delete mode 100644 docs/guides/error-handling.md
delete mode 100644 docs/guides/organizations.md
delete mode 100644 docs/guides/session-tokens.md
delete mode 100644 docs/guides/user-management.md
delete mode 100644 docs/index.md
delete mode 100644 docs/packages/_index.md
delete mode 100644 docs/packages/clerk-auth.md
delete mode 100644 docs/packages/clerk-flutter.md
diff --git a/docs/.gitignore b/docs/.gitignore
deleted file mode 100644
index 1774ecf9..00000000
--- a/docs/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-_site/
-.sass-cache/
-.jekyll-cache/
-.jekyll-metadata
-vendor/
-.bundle/
-Gemfile.lock
-
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
deleted file mode 100644
index 2d522841..00000000
--- a/docs/CONTRIBUTING.md
+++ /dev/null
@@ -1,279 +0,0 @@
-# Contributing to Clerk Dart & Flutter Documentation
-
-Thank you for your interest in contributing to the Clerk Dart & Flutter SDK documentation! This guide will help you get started.
-
-## 📋 Table of Contents
-
-- [Getting Started](#getting-started)
-- [Documentation Structure](#documentation-structure)
-- [Writing Guidelines](#writing-guidelines)
-- [Local Development](#local-development)
-- [Submitting Changes](#submitting-changes)
-
----
-
-## Getting Started
-
-### Prerequisites
-
-- Ruby >= 3.1
-- Bundler
-- Git
-
-### Setup
-
-1. Fork the repository
-2. Clone your fork:
- ```bash
- git clone https://github.com/YOUR_USERNAME/clerk-sdk-flutter.git
- cd clerk-sdk-flutter/docs
- ```
-
-3. Install dependencies:
- ```bash
- bundle install
- ```
-
-4. Start the local server:
- ```bash
- bundle exec jekyll serve
- ```
-
-5. Open http://localhost:4000/clerk-sdk-flutter in your browser
-
----
-
-## Documentation Structure
-
-```
-docs/
-├── index.md # Homepage
-├── getting-started.md # Getting started overview
-├── getting-started/ # Quickstart guides
-│ ├── quickstart-dart.md
-│ └── quickstart-flutter.md
-├── guides/ # Comprehensive guides
-│ ├── authentication.md
-│ ├── user-management.md
-│ ├── customization.md
-│ └── ...
-├── packages/ # Package-specific docs
-│ ├── clerk-auth.md
-│ └── clerk-flutter.md
-├── api/ # API reference
-│ └── widgets.md
-└── assets/ # Images and static files
-```
-
----
-
-## Writing Guidelines
-
-### Front Matter
-
-Every page must include front matter at the top:
-
-```yaml
----
-layout: default
-title: Your Page Title
-parent: Parent Page (optional)
-nav_order: 1
----
-```
-
-### Front Matter Options
-
-| Option | Description | Required |
-|--------|-------------|----------|
-| `layout` | Page layout (usually `default`) | Yes |
-| `title` | Page title shown in navigation | Yes |
-| `parent` | Parent page for hierarchy | No |
-| `nav_order` | Order in navigation menu | No |
-| `has_children` | Set to `true` if page has children | No |
-| `permalink` | Custom URL path | No |
-
-### Markdown Style
-
-#### Headings
-
-Use ATX-style headings with proper hierarchy:
-
-```markdown
-# Page Title (H1 - only one per page)
-
-## Section (H2)
-
-### Subsection (H3)
-
-#### Detail (H4)
-```
-
-#### Code Blocks
-
-Always specify the language for syntax highlighting:
-
-````markdown
-```dart
-import 'package:clerk_flutter/clerk_flutter.dart';
-
-void main() {
- runApp(MyApp());
-}
-```
-````
-
-Supported languages: `dart`, `yaml`, `bash`, `json`, `xml`, `swift`, `kotlin`
-
-#### Tables
-
-Use tables for structured information:
-
-```markdown
-| Column 1 | Column 2 | Column 3 |
-|----------|----------|----------|
-| Value 1 | Value 2 | Value 3 |
-```
-
-#### Callouts
-
-Use callouts for important information:
-
-```markdown
-{: .note }
-> This is a note callout
-
-{: .warning }
-> This is a warning callout
-
-{: .tip }
-> This is a tip callout
-```
-
-#### Links
-
-- **Internal links:** Use relative paths: `[Link Text](/guides/authentication)`
-- **External links:** Use full URLs: `[Clerk Docs](https://clerk.com/docs)`
-- **API references:** Link to pub.dev for detailed API docs
-
-### Content Guidelines
-
-1. **Be Clear and Concise**
- - Use simple, direct language
- - Avoid jargon when possible
- - Explain technical terms when first used
-
-2. **Provide Examples**
- - Include code examples for all features
- - Show complete, working code when possible
- - Add comments to explain complex code
-
-3. **Be Consistent**
- - Use consistent terminology throughout
- - Follow the existing documentation style
- - Use the same code formatting conventions
-
-4. **Keep It Updated**
- - Ensure code examples work with the latest SDK version
- - Update version numbers when they change
- - Remove deprecated features
-
-5. **Think About the User**
- - Start with the most common use cases
- - Provide step-by-step instructions
- - Include troubleshooting tips
-
----
-
-## Local Development
-
-### Running the Site Locally
-
-```bash
-cd docs
-bundle exec jekyll serve
-```
-
-The site will be available at http://localhost:4000/clerk-sdk-flutter
-
-### Live Reload
-
-Jekyll automatically reloads when you save changes to Markdown files. Refresh your browser to see updates.
-
-### Building for Production
-
-```bash
-bundle exec jekyll build
-```
-
-The built site will be in `docs/_site/`.
-
----
-
-## Submitting Changes
-
-### Before Submitting
-
-1. **Test Locally**
- - Run the site locally and verify your changes
- - Check all links work correctly
- - Ensure code examples are correct
-
-2. **Check Formatting**
- - Use proper Markdown syntax
- - Include required front matter
- - Follow the style guidelines
-
-3. **Review Content**
- - Proofread for typos and grammar
- - Ensure technical accuracy
- - Verify code examples work
-
-### Pull Request Process
-
-1. Create a new branch:
- ```bash
- git checkout -b docs/your-feature-name
- ```
-
-2. Make your changes and commit:
- ```bash
- git add .
- git commit -m "docs: Add guide for X feature"
- ```
-
-3. Push to your fork:
- ```bash
- git push origin docs/your-feature-name
- ```
-
-4. Open a Pull Request on GitHub
-
-5. Fill out the PR template with:
- - Description of changes
- - Screenshots (if applicable)
- - Related issues
-
-### Commit Message Format
-
-Use conventional commits:
-
-- `docs: Add new guide for authentication`
-- `docs: Update Flutter quickstart`
-- `docs: Fix typo in user management guide`
-- `docs: Improve code examples in customization`
-
----
-
-## Questions?
-
-If you have questions about contributing to the documentation:
-
-- 💬 [Join our Discord](https://clerk.com/discord)
-- 🐛 [Open an issue](https://github.com/clerk/clerk-sdk-flutter/issues)
-- 📧 Email: support@clerk.com
-
----
-
-Thank you for contributing to Clerk's documentation! 🎉
-
diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md
deleted file mode 100644
index 13866b15..00000000
--- a/docs/DEPLOYMENT.md
+++ /dev/null
@@ -1,228 +0,0 @@
-# Documentation Deployment Guide
-
-This guide explains how the Clerk Dart & Flutter SDK documentation is deployed to GitHub Pages.
-
-## 🌐 Live Site
-
-The documentation is available at: **https://clerk.github.io/clerk-sdk-flutter/**
-
----
-
-## 📋 Deployment Overview
-
-The documentation uses:
-- **Jekyll** - Static site generator
-- **Just the Docs** - Documentation theme
-- **GitHub Actions** - Automated deployment
-- **GitHub Pages** - Hosting
-
----
-
-## 🚀 Automatic Deployment
-
-### Trigger Conditions
-
-The documentation is automatically deployed when:
-
-1. Changes are pushed to the `main` branch
-2. Changes affect files in the `docs/` directory
-3. Changes affect `.github/workflows/deploy-docs.yml`
-
-### Workflow Steps
-
-The deployment workflow (`.github/workflows/deploy-docs.yml`) performs:
-
-1. **Checkout** - Checks out the repository
-2. **Setup Ruby** - Installs Ruby 3.1 and dependencies
-3. **Setup Pages** - Configures GitHub Pages
-4. **Build** - Builds the Jekyll site
-5. **Upload** - Uploads the built site as an artifact
-6. **Deploy** - Deploys to GitHub Pages
-
-### Viewing Deployment Status
-
-1. Go to the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions)
-2. Look for "Deploy Documentation to GitHub Pages" workflow
-3. Click on a run to see details and logs
-
----
-
-## 🔧 Manual Deployment
-
-### Trigger Manual Deployment
-
-1. Go to the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions)
-2. Select "Deploy Documentation to GitHub Pages"
-3. Click "Run workflow"
-4. Select the `main` branch
-5. Click "Run workflow"
-
-### Local Build Test
-
-Before deploying, test the build locally:
-
-```bash
-cd docs
-bundle install
-bundle exec jekyll build --baseurl "/clerk-sdk-flutter"
-```
-
-The built site will be in `docs/_site/`.
-
----
-
-## ⚙️ GitHub Pages Configuration
-
-### Repository Settings
-
-To enable GitHub Pages for this repository:
-
-1. Go to **Settings** → **Pages**
-2. Under **Source**, select:
- - Source: **GitHub Actions**
-3. The site will be published to: `https://clerk.github.io/clerk-sdk-flutter/`
-
-### Custom Domain (Optional)
-
-To use a custom domain:
-
-1. Add a `CNAME` file to `docs/` with your domain
-2. Configure DNS settings with your domain provider
-3. Update `baseurl` in `docs/_config.yml`
-
----
-
-## 🐛 Troubleshooting
-
-### Build Failures
-
-If the build fails:
-
-1. Check the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions) for error logs
-2. Common issues:
- - **Jekyll build errors**: Check Markdown syntax and front matter
- - **Missing dependencies**: Ensure `Gemfile` is up to date
- - **Configuration errors**: Verify `_config.yml` syntax
-
-### Local Testing
-
-Always test locally before pushing:
-
-```bash
-cd docs
-bundle exec jekyll serve
-```
-
-Visit http://localhost:4000/clerk-sdk-flutter to preview.
-
-### Common Errors
-
-**Error: "Could not find gem"**
-```bash
-cd docs
-bundle install
-```
-
-**Error: "Permission denied"**
-- Check repository permissions
-- Ensure GitHub Actions has write access to Pages
-
-**Error: "404 Not Found" after deployment**
-- Verify `baseurl` in `_config.yml` is set to `/clerk-sdk-flutter`
-- Check that files are in the `docs/` directory
-- Ensure GitHub Pages is enabled in repository settings
-
----
-
-## 📝 Deployment Checklist
-
-Before deploying major changes:
-
-- [ ] Test locally with `bundle exec jekyll serve`
-- [ ] Verify all links work
-- [ ] Check code examples are correct
-- [ ] Review for typos and formatting
-- [ ] Ensure front matter is correct on all pages
-- [ ] Test responsive design (mobile/desktop)
-- [ ] Verify navigation hierarchy
-- [ ] Check that search works (if enabled)
-
----
-
-## 🔄 Rollback
-
-If you need to rollback a deployment:
-
-1. Go to the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions)
-2. Find the last successful deployment
-3. Click "Re-run all jobs"
-
-Or revert the commit:
-
-```bash
-git revert
-git push origin main
-```
-
----
-
-## 📊 Monitoring
-
-### Analytics
-
-To add Google Analytics:
-
-1. Add your tracking ID to `docs/_config.yml`:
- ```yaml
- google_analytics: UA-XXXXXXXXX-X
- ```
-
-2. The Just the Docs theme will automatically include the tracking code
-
-### Performance
-
-Monitor site performance:
-- Use [Google PageSpeed Insights](https://pagespeed.web.dev/)
-- Check [Lighthouse](https://developers.google.com/web/tools/lighthouse) scores
-- Monitor build times in GitHub Actions
-
----
-
-## 🔐 Security
-
-### Permissions
-
-The workflow requires these permissions:
-- `contents: read` - Read repository contents
-- `pages: write` - Write to GitHub Pages
-- `id-token: write` - Generate deployment token
-
-These are configured in `.github/workflows/deploy-docs.yml`.
-
-### Secrets
-
-No secrets are required for basic deployment. If you add custom features that need secrets:
-
-1. Go to **Settings** → **Secrets and variables** → **Actions**
-2. Add your secrets
-3. Reference them in the workflow with `${{ secrets.SECRET_NAME }}`
-
----
-
-## 📚 Additional Resources
-
-- [Jekyll Documentation](https://jekyllrb.com/docs/)
-- [Just the Docs Theme](https://just-the-docs.github.io/just-the-docs/)
-- [GitHub Pages Documentation](https://docs.github.com/en/pages)
-- [GitHub Actions Documentation](https://docs.github.com/en/actions)
-
----
-
-## 🆘 Support
-
-If you encounter issues with deployment:
-
-- 💬 [Join our Discord](https://clerk.com/discord)
-- 🐛 [Open an issue](https://github.com/clerk/clerk-sdk-flutter/issues)
-- 📧 Email: support@clerk.com
-
diff --git a/docs/Gemfile b/docs/Gemfile
deleted file mode 100644
index 72ed083d..00000000
--- a/docs/Gemfile
+++ /dev/null
@@ -1,35 +0,0 @@
-source "https://rubygems.org"
-
-gem "jekyll", "~> 4.3"
-gem "just-the-docs", "~> 0.10.0"
-
-# Pin sass-embedded to avoid deprecation warnings with older Sass
-gem "sass-embedded", "~> 1.69.0"
-
-# Required for Ruby 3.4+
-gem "bigdecimal"
-gem "csv"
-gem "base64"
-gem "fiddle"
-
-group :jekyll_plugins do
- gem "jekyll-seo-tag"
- gem "jekyll-github-metadata"
- gem "jekyll-include-cache"
- gem "jekyll-relative-links"
-end
-
-# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
-# and associated library.
-platforms :mingw, :x64_mingw, :mswin, :jruby do
- gem "tzinfo", ">= 1", "< 3"
- gem "tzinfo-data"
-end
-
-# Performance-booster for watching directories on Windows
-gem "wdm", "~> 0.1", :platforms => [:mingw, :x64_mingw, :mswin]
-
-# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
-# do not have a Java counterpart.
-gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
-
diff --git a/docs/README.md b/docs/README.md
index 546f0d83..01db3603 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,166 +1,240 @@
-# Clerk Dart & Flutter SDK Documentation
+# Clerk SDK Documentation
-This directory contains the documentation site for Clerk's Dart and Flutter SDKs, built with Jekyll and hosted on GitHub Pages.
+Welcome to the comprehensive documentation for the Clerk SDK for Flutter and Dart.
-## 🌐 Live Documentation
+## 📚 Documentation Structure
-Visit the live documentation at: **https://clerk.github.io/clerk-sdk-flutter/**
+This documentation is organized into two main sections:
-## 📁 Structure
+### 🎯 [clerk_auth](./clerk_auth/) - Core Dart SDK
-```
-docs/
-├── _config.yml # Jekyll configuration
-├── index.md # Homepage
-├── getting-started.md # Getting started overview
-├── getting-started/ # Quickstart guides
-│ ├── quickstart-dart.md
-│ └── quickstart-flutter.md
-├── guides/ # Comprehensive guides
-│ ├── authentication.md
-│ ├── user-management.md
-│ ├── customization.md
-│ └── ...
-├── packages/ # Package-specific documentation
-│ ├── clerk-auth.md
-│ └── clerk-flutter.md
-└── assets/ # Images and static assets
-```
-
-## 🚀 Local Development
+The foundational authentication library that works with any Dart application.
-### Prerequisites
+**Start here if you're:**
+- Building a Dart CLI application
+- Integrating Clerk into a non-Flutter Dart project
+- Understanding the core authentication logic
+- Implementing custom UI or integrations
-- Ruby >= 3.1
-- Bundler
+**Key Documentation:**
+- [**Auth API**](./clerk_auth/auth.md) - Complete authentication methods (sign-in, sign-up, OAuth, passkeys, sessions, etc.)
+- [**AuthConfig**](./clerk_auth/auth_config.md) - SDK configuration and initialization
+- [**Persistor**](./clerk_auth/persistor.md) - Custom storage implementations
+- [**HttpService**](./clerk_auth/http_service.md) - Custom HTTP client implementations
-### Setup
+### 🎨 [clerk_flutter](./clerk_flutter/) - Flutter Widgets
-1. Install dependencies:
+Pre-built Flutter widgets and UI components for rapid integration.
-```bash
-cd docs
-bundle install
-```
+**Start here if you're:**
+- Building a Flutter mobile or web application
+- Looking for pre-built authentication UI
+- Wanting quick integration with minimal code
+- Customizing the appearance of auth flows
-2. Run the local server:
+**Key Documentation:**
+- [**ClerkAuth**](./clerk_flutter/clerk_auth.md) - Root widget and state management
+- [**ClerkAuthentication**](./clerk_flutter/clerk_authentication.md) - Complete pre-built auth UI
+- [**ClerkUserButton**](./clerk_flutter/clerk_user_button.md) - User profile and session management
+- [**ClerkAuthBuilder**](./clerk_flutter/clerk_auth_builder.md) - Custom UI with builder pattern
+- [**ClerkTheme**](./clerk_flutter/clerk_theme.md) - Theming and customization
-```bash
-bundle exec jekyll serve
-```
+---
-3. Open http://localhost:4000/clerk-sdk-flutter in your browser
+## 🚀 Quick Start
+
+### For Flutter Applications
+
+1. **Add dependencies** to your `pubspec.yaml`:
+ ```yaml
+ dependencies:
+ clerk_flutter: ^0.0.14-beta
+ ```
+
+2. **Wrap your app** with `ClerkAuth`:
+ ```dart
+ MaterialApp(
+ builder: ClerkAuth.materialAppBuilder(
+ config: ClerkAuthConfig(
+ publishableKey: 'pk_test_...',
+ ),
+ ),
+ home: const HomePage(),
+ )
+ ```
+
+3. **Use pre-built UI** or build custom:
+ ```dart
+ // Pre-built UI
+ ClerkSignedOut(
+ child: const ClerkAuthentication(),
+ )
+
+ // Custom UI
+ ClerkAuthBuilder(
+ signedInBuilder: (context, authState) {
+ return Text('Welcome, ${authState.user?.fullName}!');
+ },
+ signedOutBuilder: (context, authState) {
+ return const ClerkAuthentication();
+ },
+ )
+ ```
+
+📖 **[Full Flutter Guide →](./clerk_flutter/README.md)**
+
+### For Dart Applications
+
+1. **Add dependency** to your `pubspec.yaml`:
+ ```yaml
+ dependencies:
+ clerk_auth: ^0.0.14-beta
+ ```
+
+2. **Initialize** the Auth instance:
+ ```dart
+ import 'package:clerk_auth/clerk_auth.dart';
+
+ final auth = Auth(
+ config: AuthConfig(publishableKey: 'pk_test_...'),
+ );
+ await auth.initialize();
+ ```
+
+3. **Authenticate** users:
+ ```dart
+ // Email + Password sign-in
+ await auth.attemptSignIn(identifier: 'user@example.com');
+ await auth.attemptSignIn(password: 'password123');
+
+ // Check auth state
+ if (auth.isSignedIn) {
+ print('User: ${auth.user?.fullName}');
+ }
+ ```
+
+📖 **[Full Dart Guide →](./clerk_auth/README.md)**
-{: .note }
-> The site uses the local `just-the-docs` gem for development and `remote_theme` for GitHub Pages deployment. This is configured automatically via `_config.yml` and `_config_production.yml`.
+---
-### Live Reload
+## 📖 Documentation Index
+
+### clerk_auth (Core SDK)
+
+| Document | Description |
+|----------|-------------|
+| [README](./clerk_auth/README.md) | Overview and getting started |
+| [Auth](./clerk_auth/auth.md) | Complete API reference for authentication methods |
+| [AuthConfig](./clerk_auth/auth_config.md) | Configuration options and initialization |
+| [Persistor](./clerk_auth/persistor.md) | Storage interface for sessions and tokens |
+| [HttpService](./clerk_auth/http_service.md) | HTTP client interface for custom networking |
+
+### clerk_flutter (Flutter Widgets)
+
+| Document | Description |
+|----------|-------------|
+| [README](./clerk_flutter/README.md) | Overview and getting started |
+| [ClerkAuth](./clerk_flutter/clerk_auth.md) | Root widget and state management |
+| [ClerkAuthBuilder](./clerk_flutter/clerk_auth_builder.md) | Builder pattern for custom UI |
+| [ClerkAuthentication](./clerk_flutter/clerk_authentication.md) | Pre-built authentication UI |
+| [ClerkUserButton](./clerk_flutter/clerk_user_button.md) | User profile button and menu |
+| [ClerkOrganizationList](./clerk_flutter/clerk_organization_list.md) | Organization management UI |
+| [ClerkSignedIn](./clerk_flutter/clerk_signed_in.md) | Conditional rendering (signed in) |
+| [ClerkSignedOut](./clerk_flutter/clerk_signed_out.md) | Conditional rendering (signed out) |
+| [ClerkErrorListener](./clerk_flutter/clerk_error_listener.md) | Error handling and display |
+| [ClerkAuthConfig](./clerk_flutter/clerk_auth_config.md) | Flutter-specific configuration |
+| [ClerkTheme](./clerk_flutter/clerk_theme.md) | Theming and customization |
-The server will automatically reload when you make changes to the documentation files.
+---
-## 📝 Writing Documentation
+## 🎯 Common Use Cases
-### Adding a New Page
+### Authentication Flows
-1. Create a new Markdown file in the appropriate directory
-2. Add front matter at the top:
+- **[Email + Password Sign-In](./clerk_auth/auth.md#email--password-sign-in)** - Traditional authentication
+- **[Email Code Sign-In](./clerk_auth/auth.md#email-code-sign-in)** - Passwordless with verification code
+- **[Phone Code Sign-In](./clerk_auth/auth.md#phone-code-sign-in)** - SMS-based authentication
+- **[OAuth Sign-In](./clerk_auth/auth.md#oauth-sign-in)** - Social login (Google, Apple, GitHub, etc.)
+- **[Passkey Authentication](./clerk_auth/auth.md#passkey-authentication)** - WebAuthn/FIDO2
+- **[Multi-Factor Authentication](./clerk_auth/auth.md#multi-factor-authentication)** - 2FA with SMS or TOTP
-```yaml
----
-layout: default
-title: Your Page Title
-parent: Parent Page (optional)
-nav_order: 1
----
-```
+### Session Management
-3. Write your content in Markdown
+- **[Session Handling](./clerk_auth/auth.md#session-management)** - Managing user sessions
+- **[Multi-Session Support](./clerk_auth/auth.md#multi-session-management)** - Multiple accounts
+- **[Token Management](./clerk_auth/auth.md#token-management)** - Access tokens and JWTs
-### Front Matter Options
+### User Management
-| Option | Description |
-|--------|-------------|
-| `layout` | Page layout (usually `default`) |
-| `title` | Page title |
-| `parent` | Parent page for navigation hierarchy |
-| `nav_order` | Order in navigation menu |
-| `has_children` | Set to `true` if page has child pages |
-| `permalink` | Custom URL path |
+- **[User Profile](./clerk_auth/auth.md#user-management)** - Updating user information
+- **[Email Management](./clerk_auth/auth.md#email-management)** - Adding/removing emails
+- **[Phone Management](./clerk_auth/auth.md#phone-management)** - Adding/removing phone numbers
+- **[External Accounts](./clerk_auth/auth.md#external-account-management)** - OAuth connections
-### Markdown Features
+### Organization Features
-The documentation supports:
+- **[Organization Management](./clerk_auth/auth.md#organization-management)** - Creating and managing orgs
+- **[Organization Switching](./clerk_auth/auth.md#switching-organizations)** - Multi-org support
+- **[Organization UI](./clerk_flutter/clerk_organization_list.md)** - Pre-built organization widgets
-- Standard Markdown syntax
-- Code blocks with syntax highlighting
-- Tables
-- Callouts (notes, warnings, etc.)
-- Table of contents
+---
-#### Code Blocks
+## 🔑 Key Concepts
-````markdown
-```dart
-import 'package:clerk_flutter/clerk_flutter.dart';
+### Re-entrant Authentication
-void main() {
- runApp(MyApp());
-}
-```
-````
+The `attemptSignIn()` and `attemptSignUp()` methods are **re-entrant**, meaning you call them multiple times with different parameters to progress through the authentication flow:
-#### Callouts
+```dart
+// Step 1: Provide identifier
+await auth.attemptSignIn(identifier: 'user@example.com');
-```markdown
-{: .note }
-> This is a note callout
+// Step 2: Provide password
+await auth.attemptSignIn(password: 'password123');
-{: .warning }
-> This is a warning callout
+// Step 3: If 2FA enabled, provide code
+await auth.attemptSignIn(code: '123456');
```
-## 🎨 Theme
-
-The documentation uses the [Just the Docs](https://just-the-docs.github.io/just-the-docs/) theme with custom Clerk branding.
-
-## 🚢 Deployment
+📖 **[Learn more about re-entrant flows →](./clerk_auth/auth.md#re-entrant-methods)**
-The documentation is automatically deployed to GitHub Pages when changes are pushed to the `main` branch.
+### Transfer Flow
-### GitHub Actions Workflow
+When using OAuth or ID token authentication, Clerk uses a "transfer flow" to securely complete authentication:
-The deployment is handled by `.github/workflows/deploy-docs.yml`:
+```dart
+// 1. Initiate OAuth
+final transfer = await auth.oauthSignIn(strategy: Strategy.oauth_google);
-1. Triggered on push to `main` branch (when `docs/**` files change)
-2. Builds the Jekyll site
-3. Deploys to GitHub Pages
+// 2. Open browser to transfer.authUrl
-### Manual Deployment
+// 3. Complete after redirect
+await auth.completeOAuthSignIn(transfer: transfer);
+```
-You can also trigger a manual deployment:
+📖 **[Learn more about transfer flow →](./clerk_auth/auth.md#transfer-flow)**
-1. Go to the [Actions tab](https://github.com/clerk/clerk-sdk-flutter/actions)
-2. Select "Deploy Documentation to GitHub Pages"
-3. Click "Run workflow"
+---
-## 📦 Dependencies
+## 💡 Best Practices
-- **Jekyll** - Static site generator
-- **just-the-docs** - Documentation theme
-- **jekyll-seo-tag** - SEO optimization
-- **jekyll-github-metadata** - GitHub integration
+1. **Use environment variables** for publishable keys
+2. **Handle errors** with `ClerkErrorListener` (Flutter) or try-catch blocks (Dart)
+3. **Respect re-entrant flows** - call `attemptSignIn`/`attemptSignUp` multiple times
+4. **Check auth state** before accessing user/session data
+5. **Implement proper loading states** during authentication
+6. **Test all authentication strategies** enabled in your Clerk Dashboard
+7. **Customize themes** to match your brand (Flutter)
-## 🤝 Contributing
+---
-To contribute to the documentation:
+## 🆘 Support
-1. Fork the [repository](https://github.com/clerk/clerk-sdk-flutter)
-2. Create a new branch for your changes
-3. Make your edits in the `docs/` directory
-4. Test locally with `bundle exec jekyll serve`
-5. Submit a pull request
+- **Clerk Dashboard**: [https://dashboard.clerk.com](https://dashboard.clerk.com)
+- **Clerk Documentation**: [https://clerk.com/docs](https://clerk.com/docs)
+- **GitHub Issues**: Report bugs and request features
-## 📄 License
+---
-This documentation is part of the Clerk Dart & Flutter SDK and is licensed under the MIT License.
+*Documentation generated for Clerk SDK version 0.0.14-beta*
diff --git a/docs/_config.yml b/docs/_config.yml
deleted file mode 100644
index 659aaccb..00000000
--- a/docs/_config.yml
+++ /dev/null
@@ -1,78 +0,0 @@
-# Clerk Dart & Flutter SDK Documentation
-title: Clerk Dart & Flutter SDK
-description: Official documentation for Clerk's Dart and Flutter SDKs
-baseurl: "/clerk-sdk-flutter"
-url: "https://clerk.github.io"
-
-# Theme
-theme: just-the-docs
-
-# Logo and branding
-logo: "/assets/images/clerk-logo.svg"
-# Custom Clerk color scheme
-color_scheme: clerk
-
-# Navigation
-nav_enabled: true
-nav_sort: case_insensitive
-
-# Search
-search_enabled: true
-search:
- heading_level: 2
- previews: 3
- preview_words_before: 5
- preview_words_after: 10
- tokenizer_separator: /[\s/]+/
- rel_url: true
- button: true
-
-# Enable relative URLs for all links
-aux_links_new_tab: false
-
-# Footer
-footer_content: "Copyright © 2026 Clerk, Inc. Licensed under the MIT License."
-
-# Aux links
-aux_links:
- "Clerk Dart & Flutter SDK on GitHub":
- - "https://github.com/clerk/clerk-sdk-flutter"
- "Clerk Documentation":
- - "https://clerk.com/docs"
- "Clerk Dashboard":
- - "https://dashboard.clerk.com"
-
-# Defaults
-defaults:
- - scope:
- path: ""
- values:
- layout: default
-
-# Plugins
-plugins:
- - jekyll-seo-tag
- - jekyll-github-metadata
- - jekyll-include-cache
- - jekyll-relative-links
-
-# Relative links configuration
-relative_links:
- enabled: true
- collections: true
-
-# Syntax highlighting
-kramdown:
- syntax_highlighter: rouge
- syntax_highlighter_opts:
- css_class: 'highlight'
- default_lang: dart
-
-# Exclude from processing
-exclude:
- - node_modules/
- - vendor/
- - Gemfile
- - Gemfile.lock
- - README.md
-
diff --git a/docs/_config_production.yml b/docs/_config_production.yml
deleted file mode 100644
index a4dbf458..00000000
--- a/docs/_config_production.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-# Production overrides for GitHub Pages deployment
-# This file is merged with _config.yml during GitHub Pages build
-
-# Use remote_theme for GitHub Pages
-remote_theme: just-the-docs/just-the-docs
-theme: null
-
diff --git a/docs/_sass/color_schemes/clerk.scss b/docs/_sass/color_schemes/clerk.scss
deleted file mode 100644
index 3f591631..00000000
--- a/docs/_sass/color_schemes/clerk.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-// Clerk color scheme - matching https://clerk.com/docs
-// Based on dark theme with Clerk brand colors
-
-// Background colors
-$body-background-color: #0F0F0F;
-$sidebar-color: #0F0F0F;
-$code-background-color: #1A1A1A;
-$table-background-color: #1A1A1A;
-$feedback-color: darken($sidebar-color, 3%);
-
-// Text colors
-$body-text-color: #E5E5E5;
-$body-heading-color: #FFFFFF;
-$nav-child-link-color: #A1A1A1;
-$link-color: #9B8FD9;
-$btn-primary-color: #6C47FF;
-$base-button-color: #6C47FF;
-
-// Border colors
-$border-color: #2A2A2A;
-
-// Code colors
-$code-linenumber-color: #6B6B6B;
-
-// Search
-$search-background-color: #1A1A1A;
-$search-result-preview-color: #A1A1A1;
-
-// Sidebar
-$sidebar-width: 264px;
-$sidebar-width-sm: 200px;
-
-// Navigation
-$nav-list-link-color: #E5E5E5;
-$nav-list-link-color-hover: #FFFFFF;
-$nav-list-link-color-active: #FFFFFF;
-$nav-list-expander-color: #6B6B6B;
-
-// Buttons
-$btn-primary-color: #6C47FF;
-
-// Base button (outline style)
-$base-button-color: transparent;
-
-// Feedback colors
-$label-green: #10B981;
-$label-blue: #3B82F6;
-$label-purple: #6C47FF;
-$label-red: #EF4444;
-$label-yellow: #F59E0B;
-
-// Callouts/Admonitions
-$note-color: #3B82F6;
-$warning-color: #F59E0B;
-$important-color: #EF4444;
-
diff --git a/docs/_sass/custom/custom.scss b/docs/_sass/custom/custom.scss
deleted file mode 100644
index 75db400e..00000000
--- a/docs/_sass/custom/custom.scss
+++ /dev/null
@@ -1,167 +0,0 @@
-// Import syntax highlighting
-@import "./syntax-highlighting";
-
-
-// Custom styles to match Clerk documentation
-
-// Smooth scrolling
-html {
- scroll-behavior: smooth;
-}
-
-// Logo styling
-.site-logo {
- max-height: 32px;
-}
-
-// Navigation improvements
-.site-nav {
- padding-top: 1.5rem;
-}
-
-.nav-list .nav-list-item {
- margin: 0.25rem 0;
-}
-
-.nav-list-link {
- border-radius: 6px;
- padding: 0.5rem 0.75rem;
- transition: all 0.2s ease;
-
- &:hover {
- background-color: rgba(108, 71, 255, 0.1);
- }
-
- &.active {
- background-color: rgba(108, 71, 255, 0.15);
- font-weight: 500;
- }
-}
-
-// Code blocks
-pre.highlight {
- border-radius: 8px;
- border: 1px solid #2A2A2A;
-}
-
-code {
- border-radius: 4px;
- padding: 0.2em 0.4em;
- font-size: 0.9em;
-}
-
-// Tables
-table {
- border-radius: 8px;
- overflow: hidden;
-
- th {
- background-color: #1A1A1A;
- font-weight: 600;
- }
-
- td, th {
- border-color: #2A2A2A;
- }
-}
-
-// Buttons
-.btn {
- border-radius: 6px;
- font-weight: 500;
- transition: all 0.2s ease;
- border: 1px solid #2A2A2A;
- background-color: transparent;
- color: #E5E5E5;
-
- &:hover {
- border-color: #6C47FF;
- background-color: rgba(108, 71, 255, 0.1);
- color: #FFFFFF;
- }
-}
-
-.btn-primary {
- background-color: #6C47FF;
- border-color: #6C47FF;
- color: #FFFFFF;
-
- &:hover {
- background-color: #5A38E6;
- border-color: #5A38E6;
- transform: translateY(-1px);
- box-shadow: 0 4px 12px rgba(108, 71, 255, 0.3);
- }
-}
-
-// Headings
-h1, h2, h3, h4, h5, h6 {
- font-weight: 600;
- letter-spacing: -0.02em;
-}
-
-// Links
-a {
- transition: color 0.2s ease;
-
- &:hover {
- color: #B5AAEB;
- }
-}
-
-// Search
-.search-input {
- border-radius: 8px;
- background-color: #1A1A1A;
- border: 1px solid #2A2A2A;
-
- &:focus {
- border-color: #6C47FF;
- box-shadow: 0 0 0 3px rgba(108, 71, 255, 0.1);
- }
-}
-
-// Callouts
-.label,
-.label-blue,
-.label-green,
-.label-purple,
-.label-red,
-.label-yellow {
- border-radius: 4px;
- font-weight: 500;
-}
-
-// Note/Warning boxes
-blockquote {
- border-left: 4px solid #6C47FF;
- background-color: rgba(108, 71, 255, 0.05);
- border-radius: 4px;
- padding: 1rem;
- margin: 1.5rem 0;
-}
-
-// Sidebar footer
-.site-footer {
- border-top: 1px solid #2A2A2A;
- padding: 1rem;
- font-size: 0.875rem;
- color: #6B6B6B;
-}
-
-// Main content area
-.main-content {
- max-width: 50rem;
-
- h1 {
- margin-bottom: 1.5rem;
- }
-
- h2 {
- margin-top: 2.5rem;
- margin-bottom: 1rem;
- padding-bottom: 0.5rem;
- border-bottom: 1px solid #2A2A2A;
- }
-}
-
diff --git a/docs/_sass/custom/syntax-highlighting.scss b/docs/_sass/custom/syntax-highlighting.scss
deleted file mode 100644
index 86229cda..00000000
--- a/docs/_sass/custom/syntax-highlighting.scss
+++ /dev/null
@@ -1,159 +0,0 @@
-// Dark theme syntax highlighting for code blocks
-// Based on GitHub Dark theme
-
-.highlight {
- background-color: #1A1A1A;
- color: #E5E5E5;
-
- // Comments
- .c, .cm, .c1, .cs {
- color: #8B949E;
- font-style: italic;
- }
-
- // Keywords
- .k, .kc, .kd, .kn, .kp, .kr, .kt {
- color: #FF7B72;
- }
-
- // Operators
- .o, .ow {
- color: #FF7B72;
- }
-
- // Strings
- .s, .s1, .s2, .sb, .sc, .sd, .se, .sh, .si, .sx {
- color: #A5D6FF;
- }
-
- // Numbers
- .m, .mf, .mh, .mi, .mo, .il {
- color: #79C0FF;
- }
-
- // Names
- .n, .na, .nb, .nc, .no, .nd, .ni, .ne, .nf, .nl, .nn, .nx, .py {
- color: #D2A8FF;
- }
-
- // Variables
- .nv, .vc, .vg, .vi {
- color: #FFA657;
- }
-
- // Built-ins
- .nb {
- color: #79C0FF;
- }
-
- // Functions
- .nf {
- color: #D2A8FF;
- }
-
- // Classes
- .nc {
- color: #FFA657;
- }
-
- // Booleans
- .bp {
- color: #79C0FF;
- }
-
- // Punctuation
- .p {
- color: #E5E5E5;
- }
-
- // Generic
- .gd {
- color: #FF7B72;
- background-color: #3F1F1F;
- }
-
- .gi {
- color: #7EE787;
- background-color: #1F3F1F;
- }
-
- .ge {
- font-style: italic;
- }
-
- .gs {
- font-weight: bold;
- }
-
- // Line numbers
- .lineno {
- color: #6B6B6B;
- user-select: none;
- padding-right: 1em;
- border-right: 1px solid #2A2A2A;
- margin-right: 1em;
- }
-
- // Dart-specific
- .kd {
- color: #FF7B72; // class, void, var, final, const
- }
-
- .kt {
- color: #79C0FF; // int, String, bool, etc.
- }
-
- // YAML-specific
- .l-Scalar-Plain {
- color: #A5D6FF;
- }
-
- .na {
- color: #79C0FF; // YAML keys
- }
-
- // JSON-specific
- .s2 {
- color: #A5D6FF; // JSON strings
- }
-
- // Bash/Shell
- .nv {
- color: #79C0FF; // environment variables
- }
-
- .nb {
- color: #D2A8FF; // built-in commands
- }
-}
-
-// Inline code
-code {
- background-color: #1A1A1A;
- color: #E5E5E5;
- border: 1px solid #2A2A2A;
-}
-
-// Code blocks
-pre {
- background-color: #1A1A1A;
- border: 1px solid #2A2A2A;
-
- code {
- background-color: transparent;
- border: none;
- color: #E5E5E5;
- }
-}
-
-// Highlighted lines in code blocks
-.highlight .hll {
- background-color: #2A2A2A;
-}
-
-// Error highlighting
-.highlight .err {
- color: #FF7B72;
- background-color: transparent;
-}
-
diff --git a/docs/api/_index.md b/docs/api/_index.md
deleted file mode 100644
index e85256f5..00000000
--- a/docs/api/_index.md
+++ /dev/null
@@ -1,40 +0,0 @@
----
-layout: default
-title: API Reference
-nav_order: 5
-has_children: true
-permalink: /api
----
-
-# API Reference
-
-Detailed API documentation for Clerk's Dart and Flutter SDKs.
-
-## Available References
-
-### [Widget Reference]({{ '/api/widgets' | relative_url }})
-Complete reference for all Clerk Flutter widgets including ClerkAuth, ClerkAuthentication, ClerkUserButton, and more.
-
-### [clerk_auth Package]({{ '/packages/clerk-auth' | relative_url }})
-API documentation for the Dart SDK including Auth, User, Session, and configuration classes.
-
-### [clerk_flutter Package]({{ '/packages/clerk-flutter' | relative_url }})
-API documentation for the Flutter SDK including widgets, themes, and Flutter-specific features.
-
----
-
-## External API Documentation
-
-For detailed API documentation generated from source code:
-
-- **[clerk_auth on pub.dev](https://pub.dev/documentation/clerk_auth/latest/)** - Complete Dart API reference
-- **[clerk_flutter on pub.dev](https://pub.dev/documentation/clerk_flutter/latest/)** - Complete Flutter API reference
-
----
-
-## Quick Links
-
-- [Getting Started](/getting-started)
-- [Guides](/guides)
-- [GitHub Repository](https://github.com/clerk/clerk-sdk-flutter)
-
diff --git a/docs/api/widgets.md b/docs/api/widgets.md
deleted file mode 100644
index b8592628..00000000
--- a/docs/api/widgets.md
+++ /dev/null
@@ -1,304 +0,0 @@
----
-layout: default
-title: Widget Reference
-parent: API Reference
-nav_order: 1
----
-
-# Widget Reference
-{: .no_toc }
-
-Complete reference for all Clerk Flutter widgets.
-{: .fs-6 .fw-300 }
-
-## Table of contents
-{: .no_toc .text-delta }
-
-1. TOC
-{:toc}
-
----
-
-## Control Widgets
-
-### ClerkAuth
-
-The root widget that initializes and provides Clerk authentication to your app.
-
-```dart
-ClerkAuth(
- config: ClerkAuthConfig(
- publishableKey: 'pk_test_xxxxxxxxxxxxx',
- ),
- child: MaterialApp(/* ... */),
-)
-```
-
-**Properties:**
-
-| Name | Type | Required | Description |
-|------|------|----------|-------------|
-| `config` | `ClerkAuthConfig` | Yes | Configuration object |
-| `child` | `Widget` | Yes | Your app widget |
-| `persistor` | `Persistor?` | No | Custom storage mechanism |
-| `httpService` | `HttpService?` | No | Custom HTTP service |
-| `authState` | `ClerkAuthState?` | No | Pre-initialized auth state |
-
----
-
-### ClerkAuthBuilder
-
-Builds different UI based on authentication state.
-
-```dart
-ClerkAuthBuilder(
- signedInBuilder: (context, authState) => SignedInWidget(),
- signedOutBuilder: (context, authState) => SignedOutWidget(),
-)
-```
-
-**Properties:**
-
-| Name | Type | Required | Description |
-|------|------|----------|-------------|
-| `signedInBuilder` | `AuthWidgetBuilder?` | No | Builder when user is signed in |
-| `signedOutBuilder` | `AuthWidgetBuilder?` | No | Builder when user is signed out |
-| `builder` | `AuthWidgetBuilder?` | No | Fallback builder |
-
----
-
-### ClerkSignedIn
-
-Only renders its child when a user is signed in.
-
-```dart
-ClerkSignedIn(
- child: Text('Protected content'),
-)
-```
-
-**Properties:**
-
-| Name | Type | Required | Description |
-|------|------|----------|-------------|
-| `child` | `Widget` | Yes | Widget to show when signed in |
-
----
-
-### ClerkSignedOut
-
-Only renders its child when no user is signed in.
-
-```dart
-ClerkSignedOut(
- child: Text('Please sign in'),
-)
-```
-
-**Properties:**
-
-| Name | Type | Required | Description |
-|------|------|----------|-------------|
-| `child` | `Widget` | Yes | Widget to show when signed out |
-
----
-
-### ClerkErrorListener
-
-Listens for authentication errors and displays them.
-
-```dart
-ClerkErrorListener(
- child: YourWidget(),
-)
-```
-
-**Properties:**
-
-| Name | Type | Required | Description |
-|------|------|----------|-------------|
-| `child` | `Widget` | Yes | Child widget |
-
----
-
-## Authentication Widgets
-
-### ClerkAuthentication
-
-Pre-built authentication UI with sign-in and sign-up flows.
-
-```dart
-const ClerkAuthentication()
-```
-
-**Features:**
-- Email/password authentication
-- OAuth provider buttons
-- Email verification
-- Password reset
-- Automatic error handling
-- Responsive design
-
----
-
-## User Widgets
-
-### ClerkUserButton
-
-User menu button with profile and sign-out options.
-
-```dart
-ClerkUserButton(
- showName: true,
- sessionActions: [
- ClerkUserAction(
- label: 'Settings',
- icon: Icons.settings,
- onPressed: (context, authState) {
- // Handle action
- },
- ),
- ],
-)
-```
-
-**Properties:**
-
-| Name | Type | Required | Default | Description |
-|------|------|----------|---------|-------------|
-| `showName` | `bool` | No | `true` | Show user's name next to avatar |
-| `sessionActions` | `List?` | No | `null` | Custom actions for session row |
-| `additionalActions` | `List?` | No | `null` | Additional menu items |
-
----
-
-### ClerkUserAction
-
-Defines a custom action for the user menu.
-
-```dart
-ClerkUserAction(
- label: 'Settings',
- icon: Icons.settings,
- onPressed: (context, authState) {
- Navigator.push(
- context,
- MaterialPageRoute(builder: (_) => SettingsPage()),
- );
- },
-)
-```
-
-**Properties:**
-
-| Name | Type | Required | Description |
-|------|------|----------|-------------|
-| `label` | `String` | Yes | Action label text |
-| `icon` | `IconData` | Yes | Action icon |
-| `onPressed` | `Function(BuildContext, ClerkAuthState)` | Yes | Callback when pressed |
-
----
-
-## Organization Widgets
-
-### ClerkOrganizationList
-
-Display and manage organizations (if enabled in your Clerk instance).
-
-```dart
-const ClerkOrganizationList()
-```
-
-**Features:**
-- List all user's organizations
-- Create new organizations
-- Switch active organization
-- Manage organization settings
-
----
-
-## Accessing ClerkAuth
-
-### ClerkAuth.of()
-
-Access the ClerkAuthState from anywhere in your widget tree.
-
-```dart
-final authState = ClerkAuth.of(context);
-final user = authState.user;
-```
-
-**Parameters:**
-
-| Name | Type | Required | Default | Description |
-|------|------|----------|---------|-------------|
-| `context` | `BuildContext` | Yes | - | Build context |
-| `listen` | `bool` | No | `true` | Whether to rebuild on changes |
-
-**Returns:** `ClerkAuthState`
-
----
-
-## ClerkAuthState
-
-The main state object for Clerk authentication.
-
-### Properties
-
-| Name | Type | Description |
-|------|------|-------------|
-| `user` | `User?` | Current signed-in user |
-| `client` | `Client` | Client object with sessions |
-| `env` | `Environment` | Environment configuration |
-| `isSignedIn` | `bool` | Whether a user is signed in |
-| `sessionTokenStream` | `Stream` | Stream of session tokens |
-
-### Methods
-
-| Method | Description |
-|--------|-------------|
-| `attemptSignIn()` | Start a sign-in attempt |
-| `attemptSignUp()` | Start a sign-up attempt |
-| `attemptSignInVerification()` | Verify a sign-in attempt |
-| `attemptSignUpVerification()` | Verify a sign-up attempt |
-| `signOut()` | Sign out the current user |
-| `signOutOf(Session)` | Sign out of a specific session |
-| `safelyCall()` | Execute async operation with error handling |
-
----
-
-## Configuration
-
-### ClerkAuthConfig
-
-Configuration object for ClerkAuth.
-
-```dart
-ClerkAuthConfig(
- publishableKey: 'pk_test_xxxxxxxxxxxxx',
- redirectionGenerator: (url) => Uri.parse('myapp://oauth'),
- deepLinkStream: AppLinks().allUriLinkStream.map(
- (uri) => ClerkDeepLink(uri: uri),
- ),
- loading: CircularProgressIndicator(),
-)
-```
-
-**Properties:**
-
-| Name | Type | Required | Description |
-|------|------|----------|-------------|
-| `publishableKey` | `String` | Yes | Your Clerk publishable key |
-| `redirectionGenerator` | `Function(String)?` | No | Generate OAuth redirect URLs |
-| `deepLinkStream` | `Stream?` | No | Handle OAuth callbacks |
-| `loading` | `Widget?` | No | Widget shown during initialization |
-
----
-
-## Next Steps
-
-- [Customization Guide]({{ '/guides/customization' | relative_url }}) - Theme and style your widgets
-- [Flutter Quickstart]({{ '/getting-started/quickstart-flutter' | relative_url }}) - Get started quickly
-- [Authentication Flows]({{ '/guides/authentication' | relative_url }}) - Implement auth flows
-- [User Management]({{ '/guides/user-management' | relative_url }}) - Manage user profiles
-
diff --git a/docs/assets/images/clerk-logo.svg b/docs/assets/images/clerk-logo.svg
deleted file mode 100644
index 0d7dd8cc..00000000
--- a/docs/assets/images/clerk-logo.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
diff --git a/docs/clerk_auth/README.md b/docs/clerk_auth/README.md
new file mode 100644
index 00000000..8609a7f1
--- /dev/null
+++ b/docs/clerk_auth/README.md
@@ -0,0 +1,301 @@
+# Clerk Auth Documentation
+
+Welcome to the comprehensive documentation for the `clerk_auth` package. This documentation covers all public APIs and provides detailed usage examples.
+
+## Documentation Index
+
+### Core Classes
+
+1. **[Auth](auth.md)** - The main authentication class
+ - All authentication methods (sign in, sign up, OAuth, passkeys)
+ - Session management
+ - User management
+ - Organization management
+ - **Special focus on re-entrant methods**: `attemptSignIn()` and `attemptSignUp()`
+
+2. **[AuthConfig](auth_config.md)** - Configuration for the Auth class
+ - Required and optional parameters
+ - Polling and refresh settings
+ - Telemetry configuration
+ - Complete configuration examples
+
+3. **[Persistor](persistor.md)** - Persistence interface for authentication state
+ - Abstract interface definition
+ - Built-in implementations (`Persistor.none`, `DefaultPersistor`)
+ - Custom implementation examples
+ - Storage keys used by Clerk
+
+4. **[HttpService](http_service.md)** - HTTP communication interface
+ - Abstract interface definition
+ - Default implementation
+ - Custom implementation examples (logging, retry, mocking)
+ - HTTP methods and request handling
+
+---
+
+## Quick Start
+
+### Basic Setup
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+import 'package:path_provider/path_provider.dart';
+
+Future main() async {
+ // Create configuration
+ final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: DefaultPersistor(
+ getCacheDirectory: getApplicationDocumentsDirectory,
+ ),
+ );
+
+ // Create and initialize Auth
+ final auth = Auth(config: config);
+ await auth.initialize();
+
+ // Use auth for authentication
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'password123',
+ );
+
+ if (auth.isSignedIn) {
+ print('Welcome, ${auth.user?.fullName}!');
+ }
+}
+```
+
+---
+
+## Key Concepts
+
+### Re-entrant Authentication Methods
+
+The `attemptSignIn()` and `attemptSignUp()` methods are designed to be **re-entrant**, meaning they can be called multiple times with different parameters as the user progresses through the authentication flow.
+
+**Example: Multi-step Sign In**
+```dart
+// Step 1: Start with email
+await auth.attemptSignIn(
+ strategy: Strategy.emailCode,
+ identifier: 'user@example.com',
+);
+
+// Step 2: Submit verification code
+await auth.attemptSignIn(
+ strategy: Strategy.emailCode,
+ code: '123456',
+);
+
+// Step 3: If 2FA required, submit 2FA code
+if (auth.signIn?.needsSecondFactor == true) {
+ await auth.attemptSignIn(
+ strategy: Strategy.totp,
+ code: '654321',
+ );
+}
+```
+
+### Transfer Flow
+
+When using OAuth or ID token authentication, users may need to "transfer" between sign-in and sign-up flows:
+
+```dart
+// Try sign in with Apple
+await auth.idTokenSignIn(
+ provider: IdTokenProvider.apple,
+ idToken: credential.identityToken!,
+);
+
+// If user doesn't exist, transfer to sign up
+if (auth.signIn?.isTransferable == true) {
+ await auth.transfer();
+}
+```
+
+### State Management
+
+The Auth class maintains state through the `Client` object:
+- `client.signIn` - Active sign-in flow
+- `client.signUp` - Active sign-up flow
+- `client.sessions` - Active sessions
+- `session.user` - Current user
+
+---
+
+## Common Use Cases
+
+### Email + Password Authentication
+
+```dart
+// Sign up
+await auth.attemptSignUp(
+ strategy: Strategy.emailCode,
+ emailAddress: 'user@example.com',
+ password: 'SecurePass123!',
+ passwordConfirmation: 'SecurePass123!',
+ firstName: 'John',
+ lastName: 'Doe',
+);
+
+// Verify email
+await auth.attemptSignUp(
+ strategy: Strategy.emailCode,
+ code: '123456',
+);
+
+// Sign in
+await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'SecurePass123!',
+);
+```
+
+### OAuth Authentication
+
+```dart
+// Google Sign In
+await auth.oauthSignIn(
+ strategy: Strategy.oauthGoogle,
+ redirect: Uri.parse('myapp://oauth-callback'),
+);
+
+// After redirect, complete sign in
+await auth.completeOAuthSignIn(token: rotatingTokenNonce);
+```
+
+### Passkey Authentication
+
+```dart
+// Create passkey
+final passkey = await auth.createPasskey();
+// ... use passkey library to register ...
+await auth.attemptPasskeyVerification(passkey!, credentialJson);
+
+// Sign in with passkey
+await auth.attemptSignIn(strategy: Strategy.passkey);
+// ... use passkey library to authenticate ...
+await auth.attemptSignIn(
+ strategy: Strategy.passkey,
+ passkeyCredential: credentialJson,
+);
+```
+
+### Session Management
+
+```dart
+// Get session token
+final token = await auth.sessionToken();
+print('JWT: ${token.jwt}');
+
+// Listen to token updates
+auth.sessionTokenStream.listen((token) {
+ // Update your API client with new token
+});
+
+// Switch sessions
+await auth.activate(anotherSession);
+
+// Sign out
+await auth.signOut();
+```
+
+---
+
+## Architecture
+
+```
+┌─────────────────────────────────────────────────────────┐
+│ Auth │
+│ - Main authentication logic │
+│ - State management │
+│ - Public API │
+└─────────────────┬───────────────────────────────────────┘
+ │
+ │ uses
+ │
+ ┌─────────────┴─────────────┐
+ │ │
+ ▼ ▼
+┌─────────────┐ ┌─────────────┐
+│ AuthConfig │ │ Api │
+│ │ │ (internal) │
+└──────┬──────┘ └─────────────┘
+ │
+ │ contains
+ │
+ ┌───┴────┬──────────┐
+ │ │ │
+ ▼ ▼ ▼
+┌──────┐ ┌────────┐ ┌─────────────┐
+│Persis│ │ Http │ │ Retry │
+│ tor │ │Service │ │ Options │
+└──────┘ └────────┘ └─────────────┘
+```
+
+---
+
+## Best Practices
+
+1. **Always initialize before use**: Call `auth.initialize()` before any other operations
+2. **Use appropriate persistor**: `DefaultPersistor` for production, `Persistor.none` for testing
+3. **Handle errors gracefully**: Wrap auth calls in try-catch or override `handleError()`
+4. **Leverage re-entrant methods**: Call `attemptSignIn()`/`attemptSignUp()` multiple times as needed
+5. **Check transfer status**: After OAuth/ID token auth, check `isTransferable` and call `transfer()`
+6. **Clean up resources**: Call `auth.terminate()` when disposing
+7. **Monitor session tokens**: Use `sessionTokenStream` to keep tokens fresh
+
+---
+
+## Testing
+
+### Unit Testing
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ test('sign in test', () async {
+ final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: Persistor.none,
+ sessionTokenPolling: false,
+ clientRefreshPeriod: Duration.zero,
+ telemetryPeriod: Duration.zero,
+ );
+
+ final auth = Auth(config: config);
+ await auth.initialize();
+
+ // Test authentication flows
+
+ auth.terminate();
+ });
+}
+```
+
+---
+
+## Additional Resources
+
+- [Clerk Dashboard](https://dashboard.clerk.com/)
+- [Clerk API Reference](https://clerk.com/docs/reference/backend-api)
+- [Flutter SDK Guide](https://clerk.com/docs/quickstarts/flutter)
+- [clerk_auth on pub.dev](https://pub.dev/packages/clerk_auth)
+
+---
+
+## Version
+
+*Documentation generated for clerk_auth version 0.0.14-beta*
+
+---
+
+## Contributing
+
+Found an issue or want to improve the documentation? Please open an issue or pull request on the [GitHub repository](https://github.com/clerk/clerk-sdk-flutter).
+
diff --git a/docs/clerk_auth/auth.md b/docs/clerk_auth/auth.md
new file mode 100644
index 00000000..818545df
--- /dev/null
+++ b/docs/clerk_auth/auth.md
@@ -0,0 +1,1447 @@
+# Clerk Auth API Documentation
+
+This document provides comprehensive documentation for all public methods in the `Auth` class from `clerk_auth/lib/src/clerk_auth/auth.dart`.
+
+## Overview
+
+The `Auth` class is the core of the Clerk authentication system for Dart/Flutter applications. It provides a high-level API for managing user authentication, sessions, and user data.
+
+### Key Concepts
+
+**Re-entrant Methods**: The `attemptSignIn()` and `attemptSignUp()` methods are designed to be **re-entrant**, meaning they can be called multiple times with different parameters as the user progresses through the authentication flow. This design allows for flexible, step-by-step authentication processes.
+
+**State Management**: The Auth class maintains the current authentication state through the `Client` object, which contains:
+- `SignIn` object (during sign-in flow)
+- `SignUp` object (during sign-up flow)
+- `User` object (when signed in)
+- `Session` objects (active sessions)
+
+**Transfer Flow**: When using OAuth or ID token authentication, users may need to "transfer" between sign-in and sign-up flows if they don't exist yet (or already exist). Use the `transfer()` method to handle this seamlessly.
+
+## Table of Contents
+
+- [Initialization & Lifecycle](#initialization--lifecycle)
+- [Authentication State](#authentication-state)
+- [Sign In Methods](#sign-in-methods)
+- [Sign Up Methods](#sign-up-methods)
+- [OAuth Methods](#oauth-methods)
+- [Passkey Methods](#passkey-methods)
+- [Session Management](#session-management)
+- [User Management](#user-management)
+- [Organization Management](#organization-management)
+- [Password Management](#password-management)
+- [Advanced Methods](#advanced-methods)
+
+---
+
+## Initialization & Lifecycle
+
+### `initialize()`
+
+Initializes the Auth object. **Must be called before any other Auth methods.**
+
+```dart
+Future initialize()
+```
+
+**Example:**
+```dart
+final auth = Auth(config: AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: Persistor.none,
+));
+await auth.initialize();
+```
+
+**Behavior:**
+- Loads persisted client and environment data
+- Sets up periodic client refresh (if configured)
+- Starts session token polling (if enabled)
+- Retries fetching client/environment if initial fetch fails
+
+---
+
+### `terminate()`
+
+Disposes of the Auth object and cleans up resources.
+
+```dart
+void terminate()
+```
+
+**Example:**
+```dart
+auth.terminate();
+```
+
+**Behavior:**
+- Cancels all timers (polling, refresh, etc.)
+- Closes stream controllers
+- Terminates telemetry and API connections
+
+---
+
+## Authentication State
+
+### `isSignedIn`
+
+Returns whether a user is currently signed in.
+
+```dart
+bool get isSignedIn
+```
+
+**Example:**
+```dart
+if (auth.isSignedIn) {
+ print('User: ${auth.user?.fullName}');
+}
+```
+
+---
+
+### `isSigningIn`
+
+Returns whether a sign-in flow is currently in progress.
+
+```dart
+bool get isSigningIn
+```
+
+---
+
+### `isSigningUp`
+
+Returns whether a sign-up flow is currently in progress.
+
+```dart
+bool get isSigningUp
+```
+
+---
+
+### `client`
+
+The current Client object containing authentication state.
+
+```dart
+Client get client
+```
+
+**Example:**
+```dart
+final client = auth.client;
+print('Active sessions: ${client.sessions.length}');
+```
+
+---
+
+### `user`
+
+The currently signed-in User, or null if not signed in.
+
+```dart
+User? get user
+```
+
+---
+
+### `session`
+
+The current active Session, or null.
+
+```dart
+Session? get session
+```
+
+---
+
+### `signIn`
+
+The current SignIn object, or null.
+
+```dart
+SignIn? get signIn
+```
+
+---
+
+### `signUp`
+
+The current SignUp object, or null.
+
+```dart
+SignUp? get signUp
+```
+
+---
+
+### `organization`
+
+The current active Organization, or null.
+
+```dart
+Organization? get organization
+```
+
+---
+
+### `env`
+
+The Environment object containing Clerk account configuration.
+
+```dart
+Environment get env
+```
+
+---
+
+### `isNotAvailable`
+
+Returns whether the Auth object is not yet initialized.
+
+```dart
+bool get isNotAvailable
+```
+
+**Example:**
+```dart
+if (auth.isNotAvailable) {
+ print('Auth is still initializing...');
+}
+```
+
+---
+
+### `handleError()`
+
+Handles ClerkError exceptions when they occur. Override this method to customize error handling.
+
+```dart
+void handleError(Object error)
+```
+
+**Default Behavior:**
+- Throws the error
+
+**Example (Custom Error Handling):**
+```dart
+class MyAuth extends Auth {
+ MyAuth({required super.config});
+
+ @override
+ void handleError(Object error) {
+ if (error is ClerkError) {
+ // Log error instead of throwing
+ print('Clerk error: ${error.message}');
+ // Show user-friendly message
+ showErrorToUser(error.message);
+ } else {
+ // Re-throw non-Clerk errors
+ super.handleError(error);
+ }
+ }
+}
+```
+
+---
+
+### `update()`
+
+A method to be overridden by extension classes to handle state updates. Called automatically after most Auth operations.
+
+```dart
+void update()
+```
+
+**Example:**
+```dart
+class MyAuth extends Auth with ChangeNotifier {
+ MyAuth({required super.config});
+
+ @override
+ void update() {
+ super.update();
+ notifyListeners(); // Notify UI of changes
+ }
+}
+```
+
+---
+
+## Sign In Methods
+
+### `attemptSignIn()`
+
+**Re-entrant method** for progressively signing in a user. Can be called multiple times with updated parameters until sign-in is complete.
+
+```dart
+Future attemptSignIn({
+ required Strategy strategy,
+ String? identifier,
+ String? password,
+ String? code,
+ String? token,
+ String? redirectUrl,
+ String? passkeyCredential,
+})
+```
+
+**Parameters:**
+- `strategy`: The authentication strategy (e.g., `Strategy.emailCode`, `Strategy.password`)
+- `identifier`: Email, phone, or username
+- `password`: User's password (for password-based auth)
+- `code`: Verification code (for code-based strategies)
+- `token`: OAuth or ID token
+- `redirectUrl`: Redirect URL for email link strategy
+- `passkeyCredential`: Passkey credential JSON string
+
+**Example 1: Email + Password Sign In**
+```dart
+// Initial call with identifier and password
+await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'SecurePass123!',
+);
+
+// If 2FA is required, call again with the code
+if (auth.signIn?.needsSecondFactor == true) {
+ await auth.attemptSignIn(
+ strategy: Strategy.emailCode,
+ code: '123456',
+ );
+}
+```
+
+**Example 2: Email Code Sign In (Re-entrant)**
+```dart
+// Step 1: Start sign-in with email
+await auth.attemptSignIn(
+ strategy: Strategy.emailCode,
+ identifier: 'user@example.com',
+);
+
+// Step 2: User receives code, submit it
+await auth.attemptSignIn(
+ strategy: Strategy.emailCode,
+ code: '123456',
+);
+```
+
+**Example 3: Password Reset**
+```dart
+// Step 1: Initiate password reset
+await auth.initiatePasswordReset(
+ identifier: 'user@example.com',
+ strategy: Strategy.resetPasswordEmailCode,
+);
+
+// Step 2: Submit code and new password
+await auth.attemptSignIn(
+ strategy: Strategy.resetPasswordEmailCode,
+ code: '123456',
+ password: 'NewSecurePass123!',
+);
+```
+
+**Example 4: Passkey Sign In**
+```dart
+// Step 1: Prepare passkey sign-in
+await auth.attemptSignIn(strategy: Strategy.passkey);
+
+// Step 2: Get passkey credential from authenticator
+final nonce = auth.signIn?.firstFactorVerification?.nonce;
+// ... use passkey library to get credential ...
+
+// Step 3: Complete sign-in with credential
+await auth.attemptSignIn(
+ strategy: Strategy.passkey,
+ passkeyCredential: credentialJson,
+);
+```
+
+**Re-entrant Behavior:**
+- The method intelligently handles the current state of the sign-in flow
+- Can be called multiple times as the user progresses through authentication steps
+- Automatically creates a SignIn object if one doesn't exist
+- Handles preparation and attempt phases based on the strategy and current state
+
+---
+
+### `initiatePasswordReset()`
+
+Initiates a password reset flow.
+
+```dart
+Future initiatePasswordReset({
+ required String identifier,
+ required Strategy strategy,
+})
+```
+
+**Example:**
+```dart
+await auth.initiatePasswordReset(
+ identifier: 'user@example.com',
+ strategy: Strategy.resetPasswordEmailCode,
+);
+```
+
+---
+
+### `idTokenSignIn()`
+
+Sign in with an ID token from a provider (e.g., Apple, Google).
+
+```dart
+Future idTokenSignIn({
+ required IdTokenProvider provider,
+ required String idToken,
+})
+```
+
+**Example:**
+```dart
+// Apple Sign In
+await auth.idTokenSignIn(
+ provider: IdTokenProvider.apple,
+ idToken: credential.identityToken!,
+);
+
+// Check if transfer needed (user doesn't exist)
+if (auth.signIn?.isTransferable == true) {
+ await auth.transfer(); // Switch to sign-up flow
+}
+```
+
+**Transfer Flow:**
+If the user doesn't exist, the verification status will be `transferable`. Call `transfer()` to switch to the sign-up flow.
+
+---
+
+## Sign Up Methods
+
+### `attemptSignUp()`
+
+**Re-entrant method** for progressively signing up a new user. Can be called multiple times with updated parameters until sign-up is complete.
+
+```dart
+Future attemptSignUp({
+ required Strategy strategy,
+ String? firstName,
+ String? lastName,
+ String? username,
+ String? emailAddress,
+ String? phoneNumber,
+ String? password,
+ String? passwordConfirmation,
+ String? code,
+ String? token,
+ String? signature,
+ String? redirectUrl,
+ Map? metadata,
+ bool? legalAccepted,
+})
+```
+
+**Parameters:**
+- `strategy`: The authentication strategy
+- `firstName`, `lastName`, `username`: User profile information
+- `emailAddress`, `phoneNumber`: Contact identifiers
+- `password`, `passwordConfirmation`: Password (must match)
+- `code`: Verification code
+- `token`: OAuth or ID token
+- `signature`: Email link signature
+- `redirectUrl`: Redirect URL for email link strategy
+- `metadata`: Custom metadata to attach to the user
+- `legalAccepted`: Legal consent acceptance (required if enabled in settings)
+
+**Example 1: Email + Password Sign Up (Re-entrant)**
+```dart
+// Step 1: Create sign-up with initial data
+await auth.attemptSignUp(
+ strategy: Strategy.emailCode,
+ emailAddress: 'newuser@example.com',
+ password: 'SecurePass123!',
+ passwordConfirmation: 'SecurePass123!',
+ firstName: 'John',
+ lastName: 'Doe',
+);
+
+// Step 2: Verify email with code
+await auth.attemptSignUp(
+ strategy: Strategy.emailCode,
+ code: '123456',
+);
+```
+
+**Example 2: Phone Number Sign Up**
+```dart
+// Step 1: Create sign-up
+await auth.attemptSignUp(
+ strategy: Strategy.phoneCode,
+ phoneNumber: '+1234567890',
+ firstName: 'Jane',
+ lastName: 'Smith',
+);
+
+// Step 2: Verify phone
+await auth.attemptSignUp(
+ strategy: Strategy.phoneCode,
+ code: '123456',
+);
+```
+
+**Example 3: Sign Up with Metadata**
+```dart
+await auth.attemptSignUp(
+ strategy: Strategy.emailCode,
+ emailAddress: 'user@example.com',
+ password: 'SecurePass123!',
+ passwordConfirmation: 'SecurePass123!',
+ metadata: {
+ 'referralCode': 'ABC123',
+ 'source': 'mobile_app',
+ },
+);
+```
+
+**Example 4: Sign Up with Legal Consent**
+```dart
+await auth.attemptSignUp(
+ strategy: Strategy.emailCode,
+ emailAddress: 'user@example.com',
+ password: 'SecurePass123!',
+ passwordConfirmation: 'SecurePass123!',
+ legalAccepted: true, // Required if legal consent is enabled
+);
+```
+
+**Re-entrant Behavior:**
+- Can be called multiple times to update sign-up data
+- Automatically handles verification preparation and attempts
+- Updates existing SignUp object if one exists
+- Creates new SignUp object on first call
+- Validates password confirmation matches password
+
+**Throws:**
+- `ClerkError` with code `passwordMatchError` if passwords don't match
+- `ClerkError` with code `legalAcceptanceRequired` if legal consent is required but not provided
+
+---
+
+### `idTokenSignUp()`
+
+Sign up with an ID token from a provider (e.g., Apple, Google).
+
+```dart
+Future idTokenSignUp({
+ required IdTokenProvider provider,
+ required String idToken,
+ String? firstName,
+ String? lastName,
+})
+```
+
+**Example:**
+```dart
+// Apple Sign Up
+await auth.idTokenSignUp(
+ provider: IdTokenProvider.apple,
+ idToken: credential.identityToken!,
+ firstName: credential.givenName,
+ lastName: credential.familyName,
+);
+
+// Check if transfer needed (user already exists)
+if (auth.signUp?.isTransferable == true) {
+ await auth.transfer(); // Switch to sign-in flow
+}
+```
+
+**Transfer Flow:**
+If the user already exists, the verification status will be `transferable`. Call `transfer()` to switch to the sign-in flow.
+
+---
+
+### `resendCode()`
+
+Resends a verification code for the given strategy.
+
+```dart
+Future resendCode(Strategy strategy)
+```
+
+**Example:**
+```dart
+// During sign-up or sign-in
+await auth.resendCode(Strategy.emailCode);
+```
+
+**Throws:**
+- `ClerkError` with code `noInitialCodeHasBeenSetUpToResend` if no code flow is active
+
+---
+
+## OAuth Methods
+
+### `oauthSignIn()`
+
+Prepares for sign-in via an OAuth provider.
+
+```dart
+Future oauthSignIn({
+ required Strategy strategy,
+ required Uri? redirect,
+})
+```
+
+**Example:**
+```dart
+await auth.oauthSignIn(
+ strategy: Strategy.oauthGoogle,
+ redirect: Uri.parse('myapp://oauth-callback'),
+);
+
+// The user will be redirected to the OAuth provider
+// After authentication, complete the flow with completeOAuthSignIn()
+```
+
+---
+
+### `completeOAuthSignIn()`
+
+Completes OAuth sign-in by presenting the token.
+
+```dart
+Future completeOAuthSignIn({
+ required String token,
+})
+```
+
+**Example:**
+```dart
+// After OAuth redirect
+await auth.completeOAuthSignIn(token: rotatingTokenNonce);
+```
+
+---
+
+### `oauthConnect()`
+
+Connects an external account via an OAuth provider to the current user.
+
+```dart
+Future oauthConnect({
+ required Strategy strategy,
+ required Uri? redirect,
+})
+```
+
+**Example:**
+```dart
+// Connect Google account to existing user
+await auth.oauthConnect(
+ strategy: Strategy.oauthGoogle,
+ redirect: Uri.parse('myapp://oauth-callback'),
+);
+```
+
+---
+
+### `deleteExternalAccount()`
+
+Deletes an external account connection.
+
+```dart
+Future deleteExternalAccount({
+ required ExternalAccount account,
+})
+```
+
+**Example:**
+```dart
+final googleAccount = auth.user?.externalAccounts
+ ?.firstWhere((acc) => acc.provider == 'google');
+if (googleAccount != null) {
+ await auth.deleteExternalAccount(account: googleAccount);
+}
+```
+
+---
+
+## Passkey Methods
+
+### `createPasskey()`
+
+Creates an unverified passkey for the current user.
+
+```dart
+Future createPasskey()
+```
+
+**Example:**
+```dart
+final passkey = await auth.createPasskey();
+if (passkey?.verification?.nonce case VerificationNonce nonce) {
+ // Use passkey library to register
+ final authenticator = PasskeyAuthenticator();
+ final challenge = RegisterRequestType(
+ challenge: nonce.challenge,
+ relyingParty: nonce.relyingParty.toRelyingPartyType(),
+ user: nonce.user!.toUserType(),
+ excludeCredentials: const [],
+ timeout: nonce.timeout,
+ );
+ final credential = await authenticator.register(challenge);
+
+ // Verify the passkey
+ await auth.attemptPasskeyVerification(passkey!, credential.toJsonString());
+}
+```
+
+---
+
+### `attemptPasskeyVerification()`
+
+Verifies a passkey with the provided credential.
+
+```dart
+Future attemptPasskeyVerification(
+ Passkey passkey,
+ String credential,
+)
+```
+
+**Example:**
+```dart
+await auth.attemptPasskeyVerification(passkey, credentialJson);
+```
+
+---
+
+## Session Management
+
+### `sessionToken()`
+
+Gets the current session token for an organization.
+
+```dart
+Future sessionToken({
+ Organization? organization,
+ String? templateName,
+})
+```
+
+**Example:**
+```dart
+// Get default session token
+final token = await auth.sessionToken();
+print('JWT: ${token.jwt}');
+
+// Get token for specific organization
+final orgToken = await auth.sessionToken(
+ organization: myOrganization,
+);
+
+// Get token with custom template
+final customToken = await auth.sessionToken(
+ templateName: 'my_custom_template',
+);
+```
+
+**Throws:**
+- `ClerkError` with code `noSessionTokenRetrieved` if token cannot be retrieved
+
+---
+
+### `sessionTokenStream`
+
+Stream of SessionTokens as they renew.
+
+```dart
+Stream get sessionTokenStream
+```
+
+**Example:**
+```dart
+auth.sessionTokenStream.listen((token) {
+ print('New token: ${token.jwt}');
+ // Update your API client with new token
+});
+```
+
+---
+
+### `activate()`
+
+Activates the given session.
+
+```dart
+Future activate(Session session)
+```
+
+**Example:**
+```dart
+final sessions = auth.client.sessions;
+if (sessions.length > 1) {
+ await auth.activate(sessions[1]); // Switch to another session
+}
+```
+
+---
+
+### `signOut()`
+
+Signs out of all sessions and deletes the current client.
+
+```dart
+Future signOut()
+```
+
+**Example:**
+```dart
+await auth.signOut();
+```
+
+---
+
+### `signOutOf()`
+
+Signs out of a specific session.
+
+```dart
+Future signOutOf(Session session)
+```
+
+**Example:**
+```dart
+await auth.signOutOf(auth.session!);
+```
+
+---
+
+### `transfer()`
+
+Transfers an OAuth authentication into a User (handles sign-in/sign-up transfer flow).
+
+```dart
+Future transfer()
+```
+
+**Example:**
+```dart
+// After OAuth or ID token authentication
+if (auth.signIn?.isTransferable == true) {
+ await auth.transfer(); // Switch to sign-up
+} else if (auth.signUp?.isTransferable == true) {
+ await auth.transfer(); // Switch to sign-in
+}
+```
+
+---
+
+## User Management
+
+### `updateUser()`
+
+Updates the current user's profile information.
+
+```dart
+Future updateUser({
+ String? username,
+ String? firstName,
+ String? lastName,
+ String? primaryEmailAddressId,
+ String? primaryPhoneNumberId,
+ String? primaryWeb3WalletId,
+ Map? metadata,
+ File? avatar,
+})
+```
+
+**Example:**
+```dart
+await auth.updateUser(
+ firstName: 'John',
+ lastName: 'Doe',
+ username: 'johndoe',
+ metadata: {'theme': 'dark'},
+);
+```
+
+---
+
+### `deleteUser()`
+
+Deletes the current user.
+
+```dart
+Future deleteUser()
+```
+
+**Example:**
+```dart
+if (auth.env.user.actions.deleteSelf) {
+ await auth.deleteUser();
+}
+```
+
+**Throws:**
+- `ClerkError` with code `cannotDeleteSelf` if user is not authorized to delete themselves
+
+---
+
+### `updateUserImage()`
+
+Updates the user's avatar.
+
+```dart
+Future updateUserImage(File file)
+```
+
+**Example:**
+```dart
+final imageFile = File('/path/to/avatar.jpg');
+await auth.updateUserImage(imageFile);
+```
+
+---
+
+### `deleteUserImage()`
+
+Deletes the user's avatar.
+
+```dart
+Future deleteUserImage()
+```
+
+**Example:**
+```dart
+await auth.deleteUserImage();
+```
+
+---
+
+### `addIdentifyingData()`
+
+Adds an email, phone number, or other identifier to the current user.
+
+```dart
+Future addIdentifyingData(
+ String identifier,
+ IdentifierType type,
+)
+```
+
+**Example:**
+```dart
+// Add email address
+await auth.addIdentifyingData(
+ 'newemail@example.com',
+ IdentifierType.emailAddress,
+);
+
+// Add phone number
+await auth.addIdentifyingData(
+ '+1234567890',
+ IdentifierType.phoneNumber,
+);
+```
+
+---
+
+### `verifyIdentifyingData()`
+
+Verifies user identifying data with a code.
+
+```dart
+Future verifyIdentifyingData(
+ UserIdentifyingData uid,
+ String code,
+)
+```
+
+**Example:**
+```dart
+final email = auth.user?.emailAddresses
+ ?.firstWhere((e) => e.emailAddress == 'newemail@example.com');
+if (email != null) {
+ await auth.verifyIdentifyingData(email, '123456');
+}
+```
+
+---
+
+### `deleteIdentifyingData()`
+
+Deletes user identifying data.
+
+```dart
+Future deleteIdentifyingData(
+ UserIdentifyingData uid,
+)
+```
+
+**Example:**
+```dart
+final email = auth.user?.emailAddresses?.first;
+if (email != null) {
+ await auth.deleteIdentifyingData(email);
+}
+```
+
+---
+
+## Password Management
+
+### `updateUserPassword()`
+
+Updates the current user's password.
+
+```dart
+Future updateUserPassword(
+ String currentPassword,
+ String newPassword, {
+ bool signOut = true,
+})
+```
+
+**Example:**
+```dart
+await auth.updateUserPassword(
+ 'OldPassword123!',
+ 'NewPassword456!',
+ signOut: false, // Keep user signed in
+);
+```
+
+---
+
+### `deleteUserPassword()`
+
+Deletes the current user's password.
+
+```dart
+Future deleteUserPassword(String currentPassword)
+```
+
+**Example:**
+```dart
+await auth.deleteUserPassword('CurrentPassword123!');
+```
+
+---
+
+## Organization Management
+
+### `createOrganization()`
+
+Creates a new organization.
+
+```dart
+Future createOrganization({
+ required String name,
+ String? slug,
+ File? logo,
+})
+```
+
+**Example:**
+```dart
+await auth.createOrganization(
+ name: 'Acme Corp',
+ slug: 'acme-corp',
+ logo: File('/path/to/logo.png'),
+);
+```
+
+---
+
+### `updateOrganization()`
+
+Updates an organization.
+
+```dart
+Future updateOrganization({
+ required Organization organization,
+ String? name,
+ File? logo,
+})
+```
+
+**Example:**
+```dart
+await auth.updateOrganization(
+ organization: auth.organization!,
+ name: 'New Name',
+ logo: File('/path/to/new-logo.png'),
+);
+```
+
+---
+
+### `setActiveOrganization()`
+
+Makes an organization active.
+
+```dart
+Future setActiveOrganization(Organization organization)
+```
+
+**Example:**
+```dart
+final orgs = auth.user?.organizationMemberships;
+if (orgs != null && orgs.isNotEmpty) {
+ await auth.setActiveOrganization(orgs.first.organization);
+}
+```
+
+---
+
+### `leaveOrganization()`
+
+Leaves an organization.
+
+```dart
+Future leaveOrganization({
+ required Organization organization,
+ Session? session,
+})
+```
+
+**Example:**
+```dart
+final success = await auth.leaveOrganization(
+ organization: auth.organization!,
+);
+```
+
+---
+
+### `fetchOrganizationInvitations()`
+
+Fetches all organization invitations for the user.
+
+```dart
+Future> fetchOrganizationInvitations()
+```
+
+**Example:**
+```dart
+final invitations = await auth.fetchOrganizationInvitations();
+for (final invitation in invitations) {
+ print('Invited to: ${invitation.organizationName}');
+}
+```
+
+---
+
+### `acceptOrganizationInvitation()`
+
+Accepts an organization invitation.
+
+```dart
+Future acceptOrganizationInvitation(
+ OrganizationInvitation invitation,
+)
+```
+
+**Example:**
+```dart
+final invitations = await auth.fetchOrganizationInvitations();
+if (invitations.isNotEmpty) {
+ await auth.acceptOrganizationInvitation(invitations.first);
+}
+```
+
+---
+
+### `fetchOrganizationDomains()`
+
+Fetches all domains for an organization.
+
+```dart
+Future> fetchOrganizationDomains({
+ required Organization organization,
+})
+```
+
+**Example:**
+```dart
+final domains = await auth.fetchOrganizationDomains(
+ organization: auth.organization!,
+);
+```
+
+---
+
+### `createDomain()`
+
+Creates a new domain within an organization.
+
+```dart
+Future createDomain({
+ required Organization organization,
+ required String name,
+ required EnrollmentMode mode,
+})
+```
+
+**Example:**
+```dart
+await auth.createDomain(
+ organization: auth.organization!,
+ name: 'example.com',
+ mode: EnrollmentMode.automaticInvitation,
+);
+```
+
+---
+
+## Advanced Methods
+
+### `refreshClient()`
+
+Refreshes the current client from the server.
+
+```dart
+Future refreshClient()
+```
+
+**Example:**
+```dart
+await auth.refreshClient();
+```
+
+---
+
+### `resetClient()`
+
+Resets the current client, clearing any SignUp or SignIn objects.
+
+```dart
+Future resetClient()
+```
+
+**Example:**
+```dart
+await auth.resetClient();
+```
+
+---
+
+### `refreshEnvironment()`
+
+Refreshes the current environment from the server.
+
+```dart
+Future refreshEnvironment()
+```
+
+**Example:**
+```dart
+await auth.refreshEnvironment();
+```
+
+---
+
+### `fetchApiResponse()`
+
+Low-level access to the Clerk API.
+
+```dart
+Future fetchApiResponse(
+ String url, {
+ HttpMethod method = HttpMethod.post,
+ Map? headers,
+ Map? params,
+ Map? nullableParams,
+ bool withSession = false,
+})
+```
+
+**Example:**
+```dart
+final response = await auth.fetchApiResponse(
+ '/users/me/custom_endpoint',
+ method: HttpMethod.get,
+ withSession: true,
+);
+```
+
+**Note:** This method will be deprecated in a future version. Use only for advanced use cases not covered by other methods.
+
+---
+
+## Error Handling
+
+All methods may throw `ClerkError` exceptions. Use try-catch blocks or override the `handleError` method to handle errors.
+
+**Example:**
+```dart
+try {
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: 'user@example.com',
+ password: 'wrong_password',
+ );
+} on ClerkError catch (error) {
+ print('Error: ${error.message}');
+ print('Code: ${error.code}');
+}
+```
+
+**Custom Error Handling:**
+```dart
+class MyAuth extends Auth {
+ MyAuth({required super.config});
+
+ @override
+ void handleError(Object error) {
+ // Custom error handling
+ if (error is ClerkError) {
+ print('Clerk error: ${error.message}');
+ }
+ // Don't call super.handleError() to prevent throwing
+ }
+}
+```
+
+---
+
+## Common Patterns
+
+### Complete Sign-In Flow
+
+```dart
+// Email + Password with optional 2FA
+Future signInUser(String email, String password) async {
+ await auth.attemptSignIn(
+ strategy: Strategy.password,
+ identifier: email,
+ password: password,
+ );
+
+ // Check if 2FA is required
+ if (auth.signIn?.needsSecondFactor == true) {
+ // Prompt user for 2FA code
+ final code = await promptUserFor2FACode();
+ await auth.attemptSignIn(
+ strategy: Strategy.emailCode,
+ code: code,
+ );
+ }
+
+ // User is now signed in
+ print('Welcome, ${auth.user?.fullName}!');
+}
+```
+
+### Complete Sign-Up Flow
+
+```dart
+// Email + Password sign-up with verification
+Future signUpUser({
+ required String email,
+ required String password,
+ required String firstName,
+ required String lastName,
+}) async {
+ // Step 1: Create sign-up
+ await auth.attemptSignUp(
+ strategy: Strategy.emailCode,
+ emailAddress: email,
+ password: password,
+ passwordConfirmation: password,
+ firstName: firstName,
+ lastName: lastName,
+ );
+
+ // Step 2: Verify email
+ final code = await promptUserForEmailCode();
+ await auth.attemptSignUp(
+ strategy: Strategy.emailCode,
+ code: code,
+ );
+
+ // User is now signed up and signed in
+ print('Welcome, ${auth.user?.fullName}!');
+}
+```
+
+### OAuth Sign-In with Transfer
+
+```dart
+// Apple Sign In with automatic transfer
+Future appleSignIn(String idToken, {String? firstName, String? lastName}) async {
+ // Try sign-in first
+ await auth.idTokenSignIn(
+ provider: IdTokenProvider.apple,
+ idToken: idToken,
+ );
+
+ // If user doesn't exist, transfer to sign-up
+ if (auth.signIn?.isTransferable == true) {
+ await auth.transfer();
+
+ // Update with additional info if available
+ if (firstName != null || lastName != null) {
+ await auth.attemptSignUp(
+ strategy: Strategy.oauthTokenApple,
+ firstName: firstName,
+ lastName: lastName,
+ );
+ }
+ }
+
+ print('Signed in: ${auth.user?.fullName}');
+}
+```
+
+### Multi-Session Management
+
+```dart
+// Switch between multiple sessions
+Future switchSession(int sessionIndex) async {
+ final sessions = auth.client.sessions;
+ if (sessionIndex < sessions.length) {
+ await auth.activate(sessions[sessionIndex]);
+ print('Switched to: ${auth.user?.fullName}');
+ }
+}
+
+// Sign out of specific session
+Future signOutSession(Session session) async {
+ await auth.signOutOf(session);
+ print('Signed out of session: ${session.id}');
+}
+```
+
+---
+
+## Best Practices
+
+1. **Always initialize before use**: Call `initialize()` before any other Auth methods
+2. **Handle errors gracefully**: Wrap Auth calls in try-catch blocks or override `handleError()`
+3. **Use re-entrant methods correctly**: `attemptSignIn()` and `attemptSignUp()` are designed to be called multiple times
+4. **Check transfer status**: After OAuth/ID token auth, check `isTransferable` and call `transfer()` if needed
+5. **Clean up resources**: Call `terminate()` when disposing of the Auth object
+6. **Monitor session tokens**: Use `sessionTokenStream` to keep your API client updated with fresh tokens
+7. **Validate passwords**: Ensure password and passwordConfirmation match before calling `attemptSignUp()`
+8. **Check environment settings**: Use `env` to check what features are enabled before attempting operations
+
+---
+
+## Related Documentation
+
+- [Clerk Dashboard](https://dashboard.clerk.com/)
+- [Clerk API Reference](https://clerk.com/docs/reference/backend-api)
+- [Flutter SDK Guide](https://clerk.com/docs/quickstarts/flutter)
+
+---
+
+*Generated for clerk_auth version 0.0.14-beta*
+
+
diff --git a/docs/clerk_auth/auth_config.md b/docs/clerk_auth/auth_config.md
new file mode 100644
index 00000000..9a466c29
--- /dev/null
+++ b/docs/clerk_auth/auth_config.md
@@ -0,0 +1,520 @@
+# AuthConfig Documentation
+
+This document provides comprehensive documentation for the `AuthConfig` class from `clerk_auth/lib/src/clerk_auth/auth_config.dart`.
+
+## Overview
+
+The `AuthConfig` class holds all configurable items required for the `Auth` class, with sensible defaults. It is the primary configuration object for initializing Clerk authentication in your application.
+
+## Class Definition
+
+```dart
+class AuthConfig {
+ const AuthConfig({
+ required this.publishableKey,
+ required this.persistor,
+ this.flags = const SdkFlags(),
+ this.sessionTokenPolling = true,
+ this.retryOptions = const RetryOptions(),
+ this.defaultSessionTokenTemplate,
+ LocalesLookup? localesLookup,
+ bool? isTestMode,
+ String? telemetryEndpoint,
+ Duration? telemetryPeriod,
+ Duration? clientRefreshPeriod,
+ Duration? httpConnectionTimeout,
+ HttpService? httpService,
+ });
+}
+```
+
+---
+
+## Required Parameters
+
+### `publishableKey`
+
+**Type:** `String`
+
+The publishable key from your Clerk dashboard that identifies your auth service account.
+
+**Example:**
+```dart
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+);
+```
+
+**Where to find it:**
+1. Go to [Clerk Dashboard](https://dashboard.clerk.com/)
+2. Select your application
+3. Navigate to API Keys
+4. Copy the "Publishable Key"
+
+---
+
+### `persistor`
+
+**Type:** `Persistor`
+
+The persistor used for storing authentication state between app sessions.
+
+**Example:**
+```dart
+// Using DefaultPersistor
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: DefaultPersistor(
+ getCacheDirectory: () => getApplicationDocumentsDirectory(),
+ ),
+);
+
+// Using no persistence (testing only)
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: Persistor.none,
+);
+```
+
+**See also:** [Persistor Documentation](persistor.md)
+
+---
+
+## Optional Parameters
+
+### `flags`
+
+**Type:** `SdkFlags`
+**Default:** `const SdkFlags()`
+
+Flags used to affect SDK behavior. Extended by `clerk_flutter` for Flutter-specific flags.
+
+**Example:**
+```dart
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ flags: const SdkFlags(),
+);
+```
+
+---
+
+### `sessionTokenPolling`
+
+**Type:** `bool`
+**Default:** `true`
+
+Whether to regularly poll for new session tokens. When enabled, the SDK automatically refreshes session tokens before they expire.
+
+**Example:**
+```dart
+// Enable automatic token refresh (default)
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ sessionTokenPolling: true,
+);
+
+// Disable automatic token refresh
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ sessionTokenPolling: false,
+);
+```
+
+**When to disable:**
+- Testing scenarios where you want manual control
+- Applications that don't need long-lived sessions
+
+---
+
+### `retryOptions`
+
+**Type:** `RetryOptions`
+**Default:** `const RetryOptions()`
+
+Options for retrying failed HTTP requests. Uses the `retry` package.
+
+**Example:**
+```dart
+import 'package:retry/retry.dart';
+
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ retryOptions: RetryOptions(
+ maxAttempts: 5,
+ delayFactor: Duration(milliseconds: 200),
+ maxDelay: Duration(seconds: 10),
+ ),
+);
+```
+
+**RetryOptions properties:**
+- `maxAttempts`: Maximum number of retry attempts (default: 8)
+- `delayFactor`: Initial delay between retries (default: 200ms)
+- `maxDelay`: Maximum delay between retries (default: 30s)
+- `randomizationFactor`: Randomization factor for delays (default: 0.25)
+
+---
+
+### `defaultSessionTokenTemplate`
+
+**Type:** `String?`
+**Default:** `null`
+
+Default template name for session token retrieval. Useful when using custom JWT templates.
+
+**Example:**
+```dart
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ defaultSessionTokenTemplate: 'my_custom_template',
+);
+```
+
+**Use case:**
+When you have custom claims or need specific JWT structure for your backend API.
+
+---
+
+### `localesLookup`
+
+**Type:** `LocalesLookup` (function: `List Function()`)
+**Default:** `Auth.defaultLocalesLookup` (returns `['en']`)
+
+Function to return the current user's locale preferences for translations.
+
+**Example:**
+```dart
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ localesLookup: () {
+ // Return user's preferred locales
+ return ['es', 'en']; // Spanish first, English fallback
+ },
+);
+```
+
+---
+
+### `isTestMode`
+
+**Type:** `bool`
+**Default:** `false`
+
+Whether the SDK is running in test mode.
+
+**Example:**
+```dart
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ isTestMode: true,
+);
+```
+
+---
+
+### `telemetryEndpoint`
+
+**Type:** `String`
+**Default:** `'https://clerk-telemetry.com/v1/event'`
+
+The endpoint to send telemetry data to.
+
+**Example:**
+```dart
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ telemetryEndpoint: 'https://my-custom-telemetry.com/events',
+);
+```
+
+---
+
+### `telemetryPeriod`
+
+**Type:** `Duration`
+**Default:** `Duration(milliseconds: 29300)` (~30 seconds)
+
+The duration between sends of telemetry data. Set to `Duration.zero` to disable telemetry.
+
+**Example:**
+```dart
+// Custom telemetry interval
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ telemetryPeriod: Duration(minutes: 1),
+);
+
+// Disable telemetry
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ telemetryPeriod: Duration.zero,
+);
+```
+
+**Note:** The default is slightly offset from 30s to avoid repeated clashes with other regular tasks.
+
+---
+
+### `clientRefreshPeriod`
+
+**Type:** `Duration`
+**Default:** `Duration(milliseconds: 9700)` (~10 seconds)
+
+The duration between calls to refresh the client object. Set to `Duration.zero` to disable automatic client refresh.
+
+**Example:**
+```dart
+// Custom refresh interval
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ clientRefreshPeriod: Duration(seconds: 30),
+);
+
+// Disable automatic refresh
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ clientRefreshPeriod: Duration.zero,
+);
+```
+
+**Note:** The default is slightly offset from 10s to avoid repeated clashes with other regular tasks.
+
+**When to adjust:**
+- Increase for battery-sensitive applications
+- Decrease for applications requiring real-time updates
+- Disable for complete manual control
+
+---
+
+### `httpConnectionTimeout`
+
+**Type:** `Duration`
+**Default:** `Duration(milliseconds: 500)`
+
+The duration to wait for HTTP connectivity before timing out in a connectivity test.
+
+**Example:**
+```dart
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ httpConnectionTimeout: Duration(seconds: 2),
+);
+```
+
+---
+
+### `httpService`
+
+**Type:** `HttpService`
+**Default:** `DefaultHttpService()`
+
+The HTTP service used to communicate with the Clerk backend.
+
+**Example:**
+```dart
+// Using default HTTP service
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ httpService: DefaultHttpService(),
+);
+
+// Using custom HTTP service
+class MyHttpService implements HttpService {
+ // ... implement interface
+}
+
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ httpService: MyHttpService(),
+);
+```
+
+**See also:** [HttpService Documentation](http_service.md)
+
+---
+
+## Methods
+
+### `initialize()`
+
+Initializes the configuration by initializing the persistor and HTTP service.
+
+```dart
+Future initialize()
+```
+
+**Example:**
+```dart
+final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+);
+await config.initialize();
+```
+
+**Note:** This is typically called automatically by `Auth.initialize()`.
+
+---
+
+### `terminate()`
+
+Terminates the configuration by terminating the HTTP service and persistor.
+
+```dart
+void terminate()
+```
+
+**Example:**
+```dart
+config.terminate();
+```
+
+**Note:** This is typically called automatically by `Auth.terminate()`.
+
+---
+
+## Complete Examples
+
+### Basic Configuration
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+import 'package:path_provider/path_provider.dart';
+
+Future createBasicConfig() async {
+ return AuthConfig(
+ publishableKey: 'pk_test_Y2xlcmsuZXhhbXBsZS5jb20k',
+ persistor: DefaultPersistor(
+ getCacheDirectory: getApplicationDocumentsDirectory,
+ ),
+ );
+}
+```
+
+### Production Configuration
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:retry/retry.dart';
+
+Future createProductionConfig() async {
+ return AuthConfig(
+ publishableKey: 'pk_live_...',
+ persistor: DefaultPersistor(
+ getCacheDirectory: getApplicationDocumentsDirectory,
+ ),
+ sessionTokenPolling: true,
+ retryOptions: RetryOptions(
+ maxAttempts: 5,
+ delayFactor: Duration(milliseconds: 200),
+ ),
+ clientRefreshPeriod: Duration(seconds: 15),
+ telemetryPeriod: Duration(seconds: 60),
+ );
+}
+```
+
+### Testing Configuration
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+AuthConfig createTestConfig() {
+ return AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: Persistor.none, // No persistence in tests
+ isTestMode: true,
+ sessionTokenPolling: false,
+ clientRefreshPeriod: Duration.zero,
+ telemetryPeriod: Duration.zero,
+ );
+}
+```
+
+### Custom Locale Configuration
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+import 'package:flutter/material.dart';
+
+AuthConfig createLocalizedConfig(BuildContext context) {
+ return AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ localesLookup: () {
+ final locale = Localizations.localeOf(context);
+ return [locale.languageCode, 'en']; // User's locale + English fallback
+ },
+ );
+}
+```
+
+### Performance-Optimized Configuration
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+AuthConfig createOptimizedConfig() {
+ return AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: myPersistor,
+ // Reduce polling frequency for battery savings
+ clientRefreshPeriod: Duration(seconds: 30),
+ telemetryPeriod: Duration(minutes: 5),
+ // Faster timeout for better UX
+ httpConnectionTimeout: Duration(milliseconds: 300),
+ );
+}
+```
+
+---
+
+## Best Practices
+
+1. **Always use a Persistor in production**: Use `DefaultPersistor` or a custom implementation. Only use `Persistor.none` for testing.
+
+2. **Secure your publishable key**: Store it in environment variables or secure configuration, not hardcoded in source.
+
+3. **Adjust polling based on use case**:
+ - Real-time apps: Shorter `clientRefreshPeriod`
+ - Battery-sensitive apps: Longer periods or disable polling
+ - Background apps: Disable polling and refresh manually
+
+4. **Configure retry options for reliability**: Adjust based on your network conditions and user experience requirements.
+
+5. **Use custom session token templates**: When you need specific JWT claims for your backend API.
+
+6. **Disable telemetry in development**: Set `telemetryPeriod` to `Duration.zero` during development if desired.
+
+7. **Test with different configurations**: Create separate configs for development, staging, and production.
+
+---
+
+## Related Documentation
+
+- [Auth Documentation](auth.md)
+- [Persistor Documentation](persistor.md)
+- [HttpService Documentation](http_service.md)
+- [Clerk Dashboard](https://dashboard.clerk.com/)
+
+---
+
+*Generated for clerk_auth version 0.0.14-beta*
diff --git a/docs/clerk_auth/http_service.md b/docs/clerk_auth/http_service.md
new file mode 100644
index 00000000..b6785e44
--- /dev/null
+++ b/docs/clerk_auth/http_service.md
@@ -0,0 +1,657 @@
+# HttpService Documentation
+
+This document provides comprehensive documentation for the `HttpService` interface and its implementations from `clerk_auth/lib/src/clerk_auth/http_service.dart`.
+
+## Overview
+
+The `HttpService` abstract interface defines how the Clerk SDK communicates with the Clerk backend over HTTP. It provides methods for sending requests, uploading files, and checking connectivity.
+
+## HttpMethod Enum
+
+```dart
+enum HttpMethod {
+ delete,
+ get,
+ patch,
+ post,
+ put,
+}
+```
+
+**Methods:**
+- `delete`: HTTP DELETE
+- `get`: HTTP GET
+- `patch`: HTTP PATCH
+- `post`: HTTP POST
+- `put`: HTTP PUT
+
+**Properties:**
+- `isGet`: Returns `true` if method is GET
+- `isNotGet`: Returns `true` if method is not GET
+- `toString()`: Returns uppercase method name (e.g., "GET", "POST")
+
+**Example:**
+```dart
+final method = HttpMethod.post;
+print(method.toString()); // "POST"
+print(method.isGet); // false
+print(method.isNotGet); // true
+```
+
+---
+
+## Abstract Interface
+
+```dart
+abstract interface class HttpService {
+ const HttpService();
+
+ Future initialize();
+ void terminate();
+ Future ping(Uri uri, {required Duration timeout});
+ Future send(
+ HttpMethod method,
+ Uri uri, {
+ Map? headers,
+ Map? params,
+ String? body,
+ });
+ Future sendByteStream(
+ HttpMethod method,
+ Uri uri,
+ http.ByteStream byteStream,
+ int length,
+ Map headers,
+ );
+}
+```
+
+---
+
+## Methods
+
+### `initialize()`
+
+Initializes the HTTP service. May be called multiple times and must handle that gracefully.
+
+```dart
+Future initialize()
+```
+
+**Example:**
+```dart
+final httpService = DefaultHttpService();
+await httpService.initialize();
+```
+
+**Note:** The default implementation is a no-op.
+
+---
+
+### `terminate()`
+
+Terminates the HTTP service and cleans up resources. May be called multiple times and must handle that gracefully.
+
+```dart
+void terminate()
+```
+
+**Example:**
+```dart
+httpService.terminate();
+```
+
+---
+
+### `ping()`
+
+Checks that connectivity to an endpoint is available.
+
+```dart
+Future ping(Uri uri, {required Duration timeout})
+```
+
+**Parameters:**
+- `uri`: The endpoint to ping
+- `timeout`: Maximum time to wait for response
+
+**Returns:**
+- `true` if endpoint is reachable and returns 200 status
+- `false` otherwise
+
+**Example:**
+```dart
+final isReachable = await httpService.ping(
+ Uri.parse('https://api.clerk.com'),
+ timeout: Duration(seconds: 5),
+);
+if (isReachable) {
+ print('API is reachable');
+}
+```
+
+---
+
+### `send()`
+
+Sends an HTTP request to the backend and receives a response.
+
+```dart
+Future send(
+ HttpMethod method,
+ Uri uri, {
+ Map? headers,
+ Map? params,
+ String? body,
+})
+```
+
+**Parameters:**
+- `method`: The HTTP method to use
+- `uri`: The endpoint URI
+- `headers`: Optional HTTP headers
+- `params`: Optional form parameters (converted to body fields)
+- `body`: Optional request body (raw string)
+
+**Returns:**
+- `http.Response` from the server
+
+**Example:**
+```dart
+final response = await httpService.send(
+ HttpMethod.post,
+ Uri.parse('https://api.clerk.com/v1/client'),
+ headers: {
+ 'Authorization': 'Bearer token',
+ 'Content-Type': 'application/json',
+ },
+ body: jsonEncode({'key': 'value'}),
+);
+
+print('Status: ${response.statusCode}');
+print('Body: ${response.body}');
+```
+
+**With params:**
+```dart
+final response = await httpService.send(
+ HttpMethod.post,
+ Uri.parse('https://api.clerk.com/v1/sign_in'),
+ params: {
+ 'identifier': 'user@example.com',
+ 'password': 'password123',
+ },
+);
+```
+
+---
+
+### `sendByteStream()`
+
+Uploads a file to the backend using a multipart request.
+
+```dart
+Future sendByteStream(
+ HttpMethod method,
+ Uri uri,
+ http.ByteStream byteStream,
+ int length,
+ Map headers,
+)
+```
+
+**Parameters:**
+- `method`: The HTTP method to use
+- `uri`: The endpoint URI
+- `byteStream`: The file data as a byte stream
+- `length`: The length of the byte stream
+- `headers`: HTTP headers
+
+**Returns:**
+- `http.Response` from the server
+
+**Example:**
+```dart
+import 'dart:io';
+import 'package:http/http.dart' as http;
+
+final file = File('/path/to/avatar.jpg');
+final byteStream = http.ByteStream(file.openRead());
+final length = await file.length();
+
+final response = await httpService.sendByteStream(
+ HttpMethod.post,
+ Uri.parse('https://api.clerk.com/v1/me/profile_image'),
+ byteStream,
+ length,
+ {
+ 'Authorization': 'Bearer token',
+ },
+);
+```
+
+---
+
+## DefaultHttpService
+
+The default implementation of `HttpService` using the `http` package.
+
+### Constructor
+
+```dart
+const DefaultHttpService()
+```
+
+**Example:**
+```dart
+final httpService = DefaultHttpService();
+```
+
+### Behavior
+
+- Uses a single `http.Client` instance per `DefaultHttpService` instance
+- Automatically manages client lifecycle
+- Cleans up client on `terminate()`
+- Thread-safe client management
+
+### Implementation Details
+
+**Client Management:**
+```dart
+static final _clients = {};
+http.Client get _client => _clients[this] ??= http.Client();
+```
+
+**Ping Implementation:**
+- Uses HTTP HEAD request
+- Returns `true` only if status code is 200
+- Catches all exceptions and returns `false`
+
+**Send Implementation:**
+- Creates `http.Request` with method and URI
+- Adds headers if provided
+- Converts params to body fields if provided
+- Sets body if provided
+- Sends request and converts streamed response to regular response
+
+**SendByteStream Implementation:**
+- Creates `http.MultipartRequest`
+- Adds file as multipart file with field name "file"
+- Uses hash code as filename
+- Sends request and converts streamed response
+
+---
+
+## Custom Implementation
+
+You can create custom HTTP service implementations for specific requirements.
+
+### Example: Logging HTTP Service
+
+```dart
+class LoggingHttpService implements HttpService {
+ final HttpService _delegate;
+
+ LoggingHttpService(this._delegate);
+
+ @override
+ Future initialize() => _delegate.initialize();
+
+ @override
+ void terminate() => _delegate.terminate();
+
+ @override
+ Future ping(Uri uri, {required Duration timeout}) async {
+ print('Pinging: $uri');
+ final result = await _delegate.ping(uri, timeout: timeout);
+ print('Ping result: $result');
+ return result;
+ }
+
+ @override
+ Future send(
+ HttpMethod method,
+ Uri uri, {
+ Map? headers,
+ Map? params,
+ String? body,
+ }) async {
+ print('Sending $method to $uri');
+ final response = await _delegate.send(
+ method,
+ uri,
+ headers: headers,
+ params: params,
+ body: body,
+ );
+ print('Response: ${response.statusCode}');
+ return response;
+ }
+
+ @override
+ Future sendByteStream(
+ HttpMethod method,
+ Uri uri,
+ http.ByteStream byteStream,
+ int length,
+ Map headers,
+ ) async {
+ print('Uploading file to $uri (${length} bytes)');
+ final response = await _delegate.sendByteStream(
+ method,
+ uri,
+ byteStream,
+ length,
+ headers,
+ );
+ print('Upload response: ${response.statusCode}');
+ return response;
+ }
+}
+```
+
+### Example: Retry HTTP Service
+
+```dart
+import 'package:retry/retry.dart';
+
+class RetryHttpService implements HttpService {
+ final HttpService _delegate;
+ final RetryOptions _retryOptions;
+
+ RetryHttpService(this._delegate, {
+ RetryOptions? retryOptions,
+ }) : _retryOptions = retryOptions ?? const RetryOptions();
+
+ @override
+ Future initialize() => _delegate.initialize();
+
+ @override
+ void terminate() => _delegate.terminate();
+
+ @override
+ Future ping(Uri uri, {required Duration timeout}) {
+ return _delegate.ping(uri, timeout: timeout);
+ }
+
+ @override
+ Future send(
+ HttpMethod method,
+ Uri uri, {
+ Map? headers,
+ Map? params,
+ String? body,
+ }) async {
+ return _retryOptions.retry(
+ () => _delegate.send(
+ method,
+ uri,
+ headers: headers,
+ params: params,
+ body: body,
+ ),
+ retryIf: (e) => e is SocketException || e is TimeoutException,
+ );
+ }
+
+ @override
+ Future sendByteStream(
+ HttpMethod method,
+ Uri uri,
+ http.ByteStream byteStream,
+ int length,
+ Map headers,
+ ) async {
+ return _retryOptions.retry(
+ () => _delegate.sendByteStream(
+ method,
+ uri,
+ byteStream,
+ length,
+ headers,
+ ),
+ retryIf: (e) => e is SocketException || e is TimeoutException,
+ );
+ }
+}
+```
+
+### Example: Mock HTTP Service (Testing)
+
+```dart
+class MockHttpService implements HttpService {
+ final Map _mockResponses = {};
+ bool _initialized = false;
+
+ void addMockResponse(String key, http.Response response) {
+ _mockResponses[key] = response;
+ }
+
+ @override
+ Future initialize() async {
+ _initialized = true;
+ }
+
+ @override
+ void terminate() {
+ _initialized = false;
+ _mockResponses.clear();
+ }
+
+ @override
+ Future ping(Uri uri, {required Duration timeout}) async {
+ return true; // Always return true in tests
+ }
+
+ @override
+ Future send(
+ HttpMethod method,
+ Uri uri, {
+ Map? headers,
+ Map? params,
+ String? body,
+ }) async {
+ final key = '${method}_${uri.path}';
+ if (_mockResponses.containsKey(key)) {
+ return _mockResponses[key]!;
+ }
+ return http.Response('{}', 200);
+ }
+
+ @override
+ Future sendByteStream(
+ HttpMethod method,
+ Uri uri,
+ http.ByteStream byteStream,
+ int length,
+ Map headers,
+ ) async {
+ return http.Response('{"uploaded": true}', 200);
+ }
+}
+```
+
+---
+
+## Complete Examples
+
+### Basic Usage
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+void main() async {
+ final httpService = DefaultHttpService();
+ await httpService.initialize();
+
+ final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: Persistor.none,
+ httpService: httpService,
+ );
+
+ final auth = Auth(config: config);
+ await auth.initialize();
+
+ // Use auth...
+
+ auth.terminate();
+ httpService.terminate();
+}
+```
+
+### With Logging
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+
+void main() async {
+ final baseService = DefaultHttpService();
+ final loggingService = LoggingHttpService(baseService);
+ await loggingService.initialize();
+
+ final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: Persistor.none,
+ httpService: loggingService,
+ );
+
+ final auth = Auth(config: config);
+ await auth.initialize();
+
+ // All HTTP requests will be logged
+}
+```
+
+### Testing Setup
+
+```dart
+import 'package:clerk_auth/clerk_auth.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:http/http.dart' as http;
+
+void main() {
+ test('auth test with mock HTTP', () async {
+ final mockHttp = MockHttpService();
+ mockHttp.addMockResponse(
+ 'POST_/v1/client',
+ http.Response('{"client": {}}', 200),
+ );
+
+ final config = AuthConfig(
+ publishableKey: 'pk_test_...',
+ persistor: Persistor.none,
+ httpService: mockHttp,
+ );
+
+ final auth = Auth(config: config);
+ await auth.initialize();
+
+ // Test with mocked responses
+ });
+}
+```
+
+---
+
+## Best Practices
+
+1. **Use DefaultHttpService for most cases**: It's well-tested and handles common scenarios.
+
+2. **Implement custom services for specific needs**:
+ - Logging/debugging
+ - Custom retry logic
+ - Request/response transformation
+ - Testing with mocks
+
+3. **Handle initialization properly**:
+ - Always call `initialize()` before use
+ - Handle multiple initialization calls gracefully
+ - Clean up in `terminate()`
+
+4. **Manage client lifecycle**:
+ - Create clients in `initialize()`
+ - Close clients in `terminate()`
+ - Reuse clients when possible
+
+5. **Error handling**:
+ - Catch and handle network exceptions
+ - Implement retry logic for transient failures
+ - Log errors for debugging
+
+6. **Testing**:
+ - Use mock implementations in tests
+ - Test error scenarios
+ - Verify request/response handling
+
+7. **Performance**:
+ - Reuse HTTP clients
+ - Implement connection pooling
+ - Set appropriate timeouts
+
+---
+
+## Troubleshooting
+
+### Connection Timeouts
+
+**Problem:** Requests timeout frequently.
+
+**Solutions:**
+- Increase `httpConnectionTimeout` in `AuthConfig`
+- Check network connectivity
+- Verify API endpoint is reachable
+- Implement retry logic
+
+### SSL/TLS Errors
+
+**Problem:** Certificate verification failures.
+
+**Solutions:**
+- Ensure system certificates are up to date
+- Check for man-in-the-middle proxies
+- Verify API endpoint uses valid certificate
+- Don't disable certificate validation in production
+
+### Memory Leaks
+
+**Problem:** HTTP clients not being cleaned up.
+
+**Solutions:**
+- Always call `terminate()` when done
+- Ensure clients are closed properly
+- Use `DefaultHttpService` which manages lifecycle
+- Profile memory usage
+
+### Request Failures
+
+**Problem:** Requests fail with various errors.
+
+**Solutions:**
+- Check request parameters and headers
+- Verify API endpoint and method
+- Implement logging to debug requests
+- Use retry logic for transient failures
+
+---
+
+## Related Documentation
+
+- [AuthConfig Documentation](auth_config.md)
+- [Auth Documentation](auth.md)
+- [Persistor Documentation](persistor.md)
+
+---
+
+## Additional Resources
+
+- [http package](https://pub.dev/packages/http)
+- [retry package](https://pub.dev/packages/retry)
+- [Clerk API Reference](https://clerk.com/docs/reference/backend-api)
+
+---
+
+*Generated for clerk_auth version 0.0.14-beta*
+
+
+
diff --git a/docs/clerk_auth/persistor.md b/docs/clerk_auth/persistor.md
new file mode 100644
index 00000000..0dc5a373
--- /dev/null
+++ b/docs/clerk_auth/persistor.md
@@ -0,0 +1,539 @@
+# Persistor Documentation
+
+This document provides comprehensive documentation for the `Persistor` abstract class and its implementations from `clerk_auth/lib/src/clerk_auth/persistor.dart`.
+
+## Overview
+
+The `Persistor` abstract class defines the persistence interface for storing authentication state between app sessions. It allows the Clerk SDK to maintain user sessions across app restarts.
+
+## Abstract Class
+
+```dart
+abstract class Persistor {
+ Future initialize();
+ void terminate();
+ FutureOr read(String key);
+ FutureOr write(String key, T value);
+ FutureOr delete(String key);
+}
+```
+
+---
+
+## Methods
+
+### `initialize()`
+
+Initializes the persistor service. Called once when the Auth object is initialized.
+
+```dart
+Future initialize()
+```
+
+**Example:**
+```dart
+final persistor = DefaultPersistor(
+ getCacheDirectory: getApplicationDocumentsDirectory,
+);
+await persistor.initialize();
+```
+
+---
+
+### `terminate()`
+
+Terminates the persistor service. Called when the Auth object is terminated.
+
+```dart
+void terminate()
+```
+
+**Example:**
+```dart
+persistor.terminate();
+```
+
+---
+
+### `read()`
+
+Reads a value from storage by key.
+
+```dart
+FutureOr read(String key)
+```
+
+**Parameters:**
+- `key`: The storage key to read from
+
+**Returns:**
+- The stored value of type `T`, or `null` if not found
+
+**Example:**
+```dart
+final clientData = await persistor.read