Overview
The Restaurant Reservation System uses Firebase for authentication, database, and email services. This guide covers the complete Firebase setup process.
Prerequisites
- A Firebase account
- Flutter SDK installed
- FlutterFire CLI installed:
dart pub global activate flutterfire_cli
Firebase Project Setup
Create Firebase Project
- Go to Firebase Console
- Click “Add project”
- Enter your project name (e.g.,
software-restaurante-59030)
- Disable Google Analytics (optional for this project)
- Click “Create project”
Register Your App
Web App
- In Firebase Console, click the Web icon (
</>)
- Register app with a nickname
- Enable Firebase Hosting (recommended)
- Copy the configuration values
Android/iOS (Optional)
Run FlutterFire CLI to automatically configure:Configure Firebase in Flutter
Create lib/firebase_options.dart with your Firebase credentials:lib/firebase_options.dart
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
default:
throw UnsupportedError('Platform not supported');
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'YOUR_API_KEY',
appId: 'YOUR_APP_ID',
messagingSenderId: 'YOUR_SENDER_ID',
projectId: 'your-project-id',
authDomain: 'your-project-id.firebaseapp.com',
storageBucket: 'your-project-id.firebasestorage.app',
measurementId: 'YOUR_MEASUREMENT_ID',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'YOUR_ANDROID_API_KEY',
appId: 'YOUR_ANDROID_APP_ID',
messagingSenderId: 'YOUR_SENDER_ID',
projectId: 'your-project-id',
storageBucket: 'your-project-id.firebasestorage.app',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'YOUR_IOS_API_KEY',
appId: 'YOUR_IOS_APP_ID',
messagingSenderId: 'YOUR_SENDER_ID',
projectId: 'your-project-id',
storageBucket: 'your-project-id.firebasestorage.app',
iosBundleId: 'com.example.appRestaurante',
);
}
Never commit real API keys to public repositories. Use environment variables for production.
Firebase Authentication Setup
Enable Authentication Methods
- In Firebase Console, go to Authentication → Sign-in method
- Enable Email/Password authentication
- Enable Google authentication
- Configure authorized domains for production
Configure Google Sign-In
Web Configuration
- Go to Authentication → Sign-in method → Google
- Add your domain to authorized domains
- Copy the Web Client ID for OAuth
Implementation
The app uses ServicioAutenticacion to handle authentication:// Initialize authentication service
final auth = ServicioAutenticacion();
// Sign in with Google
final credential = await auth.iniciarSesionConGoogle();
// Sign in with Email/Password
final credential = await auth.iniciarSesionConEmail(
email: '[email protected]',
password: 'password123',
);
The service automatically forces account selection on web (prompt: select_account) to prevent auto-login issues.
Phone Authentication (Optional)
For SMS verification:
- Enable Phone authentication in Firebase Console
- Configure reCAPTCHA (required for web)
- Use the built-in phone verification methods:
await auth.enviarCodigoSMS(
numeroTelefono: '+5491112345678',
onCodeSent: (message) => print(message),
onError: (error) => print(error),
onAutoVerified: () => print('Auto-verified'),
);
await auth.verificarCodigoSMS(codigo: '123456');
Firestore Database Setup
Create Firestore Database
- Go to Firestore Database in Firebase Console
- Click Create database
- Start in Production mode (we’ll add rules next)
- Select a location close to your users
Configure Security Rules
Create firestore.rules with appropriate security:rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Negocios (businesses) - read by all, write by owner
match /negocios/{negocioId} {
allow read: if true;
allow write: if request.auth != null && request.auth.uid == resource.data.ownerId;
}
// Mesas (tables) - read by all, write by business owner
match /mesas/{mesaId} {
allow read: if true;
allow write: if request.auth != null;
}
// Reservas (reservations) - read/write with authentication
match /reservas/{reservaId} {
allow read: if request.auth != null;
allow create: if request.auth != null;
allow update: if request.auth != null;
allow delete: if request.auth != null;
}
// Horarios (schedules) - read by all, write by owner
match /horarios/{horarioId} {
allow read: if true;
allow write: if request.auth != null;
}
// Historia (restaurant history) - read by all
match /historia/{historiaId} {
allow read: if true;
allow write: if request.auth != null;
}
// Mail queue (for Trigger Email extension)
match /mail/{mailId} {
allow read, write: if false; // Only Firebase Extensions can write
}
}
}
Deploy rules:firebase deploy --only firestore:rules
Initialize Firestore Collections
The app uses these Firestore collections:| Collection | Purpose | Key Fields |
|---|
negocios | Restaurant businesses | nombre, email, duracionPromedioMinutos |
mesas | Restaurant tables | nombre, capacidad, zona, negocioId |
reservas | Customer reservations | mesaId, fechaHora, estado, contactoCliente |
horarios | Opening hours | negocioId, dias, horaInicio, horaFin |
historia | Restaurant story | negocioId, titulo, descripcion |
mail | Email queue (auto-managed) | to, message, delivery |
Collections are created automatically when you add the first document. No manual setup needed!
Initialize Firebase in Your App
In lib/main.dart, initialize Firebase before running the app:
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'service_locator.dart';
void main() async {
// Ensure Flutter bindings are initialized
WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase
try {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
} catch (e) {
// Handle duplicate initialization during hot restart
if (e.toString().contains('already exists')) {
// Ignore - already initialized
} else {
rethrow;
}
}
// Initialize dependency injection
setupServiceLocator();
runApp(const MyApp());
}
Firebase Hosting Setup
Install Firebase CLI
npm install -g firebase-tools
Login and Initialize
firebase login
firebase init hosting
When prompted:
- Select your existing Firebase project
- Set public directory:
build/web
- Configure as single-page app: Yes
- Set up automatic builds with GitHub: Optional
Configure firebase.json
{
"firestore": {
"rules": "firestore.rules"
},
"hosting": {
"public": "build/web",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Build and Deploy
# Build Flutter web app
flutter build web
# Deploy to Firebase Hosting
firebase deploy --only hosting
Your app will be live at: https://your-project-id.web.app
Dependencies
Add these Firebase packages to pubspec.yaml:
dependencies:
# Firebase Core
firebase_core: ^3.3.0
# Firebase Authentication
firebase_auth: ^5.1.0
google_sign_in: ^6.2.1
# Cloud Firestore
cloud_firestore: ^5.6.12
Then run:
Verification
Test your Firebase setup:
- Authentication: Try signing in with Google and Email/Password
- Firestore: Check that data appears in Firebase Console when creating reservations
- Hosting: Visit your deployed URL and verify the app loads
Always test security rules in Firebase Console’s Rules Playground before deploying to production.
Troubleshooting
”Firebase already initialized” error
This happens during hot restart. The code already handles this:
try {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
} catch (e) {
if (e.toString().contains('already exists')) {
// Safe to ignore
}
}
Google Sign-In not working on web
Ensure your domain is in Authorized domains in Firebase Console → Authentication → Settings.
Firestore permission denied
Check your security rules. For development, you can temporarily use:
allow read, write: if request.auth != null;
Next Steps