DEV Community

Cover image for Shorebird: Deploy Flutter Updates Without App Store Review (Step-by-Step Guide)
George Ikwegbu Chinedu
George Ikwegbu Chinedu

Posted on

Shorebird: Deploy Flutter Updates Without App Store Review (Step-by-Step Guide)

Table of Contents

  1. What is Shorebird?
  2. Why You Need It
  3. Prerequisites
  4. Installation
  5. Setup & Configuration
  6. Creating Your First Release
  7. Deploying Patches
  8. CI/CD Integration
  9. Best Practices
  10. Troubleshooting

What is Shorebird?

Shorebird is a code push solution for Flutter that lets you update your app's Dart code without going through the Apple App Store or Google Play Store review process.

Think of it as hotfix superpowers for production apps. Bug in production? Deploy a patch in minutes instead of waiting days for app store approval.

Key Capabilities:

  • ✅ Push Dart code updates instantly
  • ✅ Bypass app store review cycles
  • ✅ Automated rollback on crashes
  • ✅ Staged rollouts (release to 5%, then 50%, then 100%)
  • ✅ Detailed analytics on patch adoption
  • ✅ Works with Flutter's native capabilities

Why You Need It

Scenario: It's Friday evening. Your production app has a critical bug affecting checkout. Users are losing money.

Without Shorebird:

  • Submit fix to Apple App Store
  • Wait 24-48 hours for review
  • Users suffer the entire time
  • Potential revenue loss

With Shorebird:

  • Deploy fix in 5 minutes
  • Users get the patch immediately
  • Crisis averted

Real-World Benefits:

  • Reduce Time-to-Market: Deploy hotfixes without waiting for store approval
  • Better User Experience: Critical bugs fixed instantly
  • Cost Savings: Fewer production incidents = fewer support tickets
  • Faster Iteration: Deploy A/B tests and feature toggles in real-time
  • CI/CD Integration: Automate patch deployment through your pipeline

Prerequisites

Before starting, ensure you have:

  1. Flutter Project: An existing Flutter app (or create one)
   flutter create my_app
   cd my_app
Enter fullscreen mode Exit fullscreen mode
  1. Shorebird Account: Sign up at shorebird.dev

  2. Flutter SDK: Version 3.0 or higher

   flutter --version
Enter fullscreen mode Exit fullscreen mode
  1. Git: For version control
   git --version
Enter fullscreen mode Exit fullscreen mode
  1. Platform Requirements:
    • iOS: Xcode 14+
    • Android: Android SDK 21+

Installation

Step 1: Install Shorebird CLI

# On macOS/Linux
curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/shorebird/main/scripts/install.sh | bash

# On Windows (PowerShell)
iwr https://raw.githubusercontent.com/shorebirdtech/shorebird/main/scripts/install.ps1 -UseBasicParsing | iex
Enter fullscreen mode Exit fullscreen mode

Step 2: Verify Installation

shorebird --version
Enter fullscreen mode Exit fullscreen mode

Expected output:

Shorebird 0.x.x
Enter fullscreen mode Exit fullscreen mode

Step 3: Initialize Shorebird in Your Project

cd your_flutter_project
shorebird init
Enter fullscreen mode Exit fullscreen mode

This creates:

  • .shorebird/config.yaml - Shorebird configuration
  • Updates pubspec.yaml with dependencies

Setup & Configuration

Step 1: Authenticate with Shorebird

shorebird login
Enter fullscreen mode Exit fullscreen mode

This opens a browser window for authentication. Sign in with your Shorebird account.

Step 2: Review shorebird.yaml

Located in your project root:

app_id: "your-app-id-here"
flavors:
  - name: production
    app_id: "prod-app-id"
Enter fullscreen mode Exit fullscreen mode

Step 3: Update Your App Version

In pubspec.yaml:

version: 1.0.0+1  # version+build_number
Enter fullscreen mode Exit fullscreen mode

Important: Increment the build number for each Shorebird release.

Step 4: Configure Your App

In lib/main.dart, ensure your app can handle code updates:

import 'package:shorebird_code_push/shorebird_code_push.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Optional: Check for updates on app start
  final codePush = ShorebirdsCodePush();
  await codePush.checkForUpdates();

  runApp(const MyApp());
}
Enter fullscreen mode Exit fullscreen mode

Creating Your First Release

Step 1: Build for Release

Before creating a Shorebird release, build your app for both platforms.

For Android:

shorebird build apk --release
Enter fullscreen mode Exit fullscreen mode

For iOS:

shorebird build ipa --release
Enter fullscreen mode Exit fullscreen mode

Step 2: Review Build Output

Successful output looks like:

✓ Built APK: build/app/outputs/flutter-app-release.apk
✓ Built IPA: build/ios/ipa/MyApp.ipa
Enter fullscreen mode Exit fullscreen mode

Step 3: Submit to App Stores

Google Play Store:

fastlane supply --apk build/app/outputs/flutter-app-release.apk
Enter fullscreen mode Exit fullscreen mode

Or upload manually via Google Play Console.

Apple App Store:

fastlane pilot upload --ipa build/ios/ipa/MyApp.ipa
Enter fullscreen mode Exit fullscreen mode

Or use Xcode/Transporter.

Step 4: Create a Release in Shorebird

Once your app is live on stores:

shorebird release
Enter fullscreen mode Exit fullscreen mode

This captures the current code state as your baseline release.


Deploying Patches

Scenario: You have a bug fix ready

Step 1: Make Your Code Changes

Fix the bug in your Dart code:

// Before
class LoginScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // BUG: Email validation broken
    return TextField(
      onChanged: (value) => emailValidation(value),
    );
  }
}

// After
class LoginScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // FIXED: Proper email validation
    return TextField(
      onChanged: (value) => _validateEmail(value),
    );
  }

  void _validateEmail(String email) {
    final regex = RegExp(r'^[^@]+@[^@]+\.[^@]+');
    return regex.hasMatch(email);
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Bump the Build Number

In pubspec.yaml:

# Before
version: 1.0.0+1

# After
version: 1.0.0+2
Enter fullscreen mode Exit fullscreen mode

Step 3: Create a Patch

shorebird patch
Enter fullscreen mode Exit fullscreen mode

Shorebird will:

  • Build the patched code
  • Compare it to the release baseline
  • Create a minimal delta package
  • Upload it to Shorebird servers

Step 4: Monitor Patch Status

shorebird patch status
Enter fullscreen mode Exit fullscreen mode

Output shows:

  • Patch creation status
  • Percentage of devices updated
  • Any errors or rollbacks

Step 5: Staged Rollout (Optional)

Deploy to a small percentage first:

shorebird patch --staged-rollout 0.05
# Deploys to 5% of users
Enter fullscreen mode Exit fullscreen mode

Monitor for 24 hours, then increase:

shorebird patch --staged-rollout 0.5
# Deploys to 50% of users
Enter fullscreen mode Exit fullscreen mode

Finally, roll out to everyone:

shorebird patch --staged-rollout 1.0
# 100% rollout
Enter fullscreen mode Exit fullscreen mode

CI/CD Integration

GitHub Actions Example

Create .github/workflows/shorebird-patch.yml:

name: Shorebird Patch Deployment

on:
  workflow_dispatch:
    inputs:
      staged_rollout:
        description: 'Staged rollout percentage (0.0-1.0)'
        required: false
        default: '1.0'

jobs:
  patch:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.x'

      - name: Install Shorebird
        run: |
          curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/shorebird/main/scripts/install.sh | bash

      - name: Authenticate Shorebird
        run: shorebird login --token ${{ secrets.SHOREBIRD_TOKEN }}

      - name: Create Patch
        run: shorebird patch --staged-rollout ${{ github.event.inputs.staged_rollout || '1.0' }}

      - name: Notify Slack
        uses: slackapi/slack-github-action@v1
        with:
          webhook-url: ${{ secrets.SLACK_WEBHOOK }}
          payload: |
            {
              "text": "✅ Shorebird patch deployed successfully!",
              "blocks": [
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "Shorebird Patch Deployed\nRollout: ${{ github.event.inputs.staged_rollout || '100%' }}\nRef: ${{ github.ref }}"
                  }
                }
              ]
            }
Enter fullscreen mode Exit fullscreen mode

GitLab CI Example

Create .gitlab-ci.yml:

patch:shorebird:
  stage: deploy
  image: google/flutter:latest

  script:
    - curl --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/shorebirdtech/shorebird/main/scripts/install.sh | bash
    - shorebird login --token $SHOREBIRD_TOKEN
    - shorebird patch --staged-rollout 0.5

  only:
    - main

  when: manual
Enter fullscreen mode Exit fullscreen mode

Best Practices

1. Test Before Patching

Always test your code locally and in staging:

flutter test
flutter analyze
flutter run --release
Enter fullscreen mode Exit fullscreen mode

2. Use Semantic Versioning

# Major.Minor.Patch+BuildNumber
version: 1.2.3+45
Enter fullscreen mode Exit fullscreen mode

3. Document Your Patches

Create a CHANGELOG:

## [1.2.3] - 2024-06-07

### Fixed
- Fixed email validation bug in login screen
- Corrected typo in onboarding flow
- Resolved memory leak in metrics tracker

### Changed
- Improved error messages for better UX
Enter fullscreen mode Exit fullscreen mode

4. Staged Rollouts for Critical Patches

Never roll out 100% immediately:

# Day 1: 5%
shorebird patch --staged-rollout 0.05

# Day 2: 25%
shorebird patch --staged-rollout 0.25

# Day 3: 100%
shorebird patch --staged-rollout 1.0
Enter fullscreen mode Exit fullscreen mode

5. Monitor Metrics

Check adoption and error rates:

shorebird patch status --verbose
Enter fullscreen mode Exit fullscreen mode

6. Have a Rollback Plan

If a patch causes issues:

shorebird patch rollback
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

Issue: "App ID not found"

Solution:

shorebird init  # Re-initialize
shorebird login  # Re-authenticate
Enter fullscreen mode Exit fullscreen mode

Issue: "Patch failed: No changes detected"

Cause: No Dart code changes since last release.

Solution:

# Ensure build number is incremented
version: 1.0.0+2  # Changed from +1
Enter fullscreen mode Exit fullscreen mode

Issue: "Users not receiving patch"

Cause: App not checking for updates.

Solution: Add to main.dart:

final codePush = ShorebirdsCodePush();
await codePush.checkForUpdates();
Enter fullscreen mode Exit fullscreen mode

Issue: "Staged rollout stuck at X%"

Solution:

shorebird patch status --verbose
shorebird patch resume  # Resume rollout
Enter fullscreen mode Exit fullscreen mode

Issue: "Build fails on iOS"

Solution:

cd ios
pod repo update
pod install
cd ..
flutter clean
shorebird build ipa --release
Enter fullscreen mode Exit fullscreen mode

Summary

Shorebird transforms how you deploy Flutter apps:

Feature Without Shorebird With Shorebird
Hotfix Time 24-48 hours 5 minutes
User Experience Bugs persist Instant fixes
A/B Testing Requires app update Real-time
Rollback Requires new submission Instant
Cost High (support tickets) Low (automated)

Next Steps

  1. Visit: https://shorebird.dev/
  2. Read: Shorebird documentation
  3. Try: Create your first patch
  4. Integrate: Add to your CI/CD pipeline
  5. Deploy: Ship faster, update smarter

Resources


Happy patching! 🚀

Top comments (0)