Complete guide for deploying Grex web app to various hosting platforms.
- Flutter SDK with web support enabled
- Node.js and npm (for some hosting platforms)
- Account on hosting platform of choice
flutter build web \
--dart-define=ENVIRONMENT=development \
--dart-define=BASE_URL=http://localhost:3000flutter build web \
--release \
--dart-define=ENVIRONMENT=production \
--dart-define=BASE_URL=https://api.example.com \
--web-renderer canvaskitBuild Output: build/web/
--web-renderer canvaskit: Better compatibility, larger bundle--web-renderer html: Smaller bundle, better performance (experimental)--base-href /: Set base URL for deployment
flutter run -d chrome --web-port=8080# Python
cd build/web
python3 -m http.server 8080
# Node.js
npx http-server build/web -p 8080
# PHP
cd build/web
php -S localhost:8080Visit http://localhost:8080 to test.
Best for: Quick setup, CDN, custom domains, SSL
Best for: Git-based deployments, preview deployments, forms
Best for: Next.js-like experience, edge functions, analytics
Best for: Free hosting, simple setup, public repos
Best for: AWS integration, CI/CD, advanced features
Best for: Full control, existing infrastructure
- Install Firebase CLI:
npm install -g firebase-tools- Login:
firebase login- Initialize Firebase:
firebase init hostingSelect:
- Use existing project or create new
- Public directory:
build/web - Single-page app: Yes
- Set up automatic builds: Yes (optional)
Create firebase.json:
{
"hosting": {
"public": "build/web",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [
{
"source": "**/*.@(js|css|woff|woff2|ttf|otf|eot)",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=31536000"
}
]
}
]
}
}# Build first
flutter build web --release
# Deploy
firebase deploy --only hosting- Go to Firebase Console → Hosting
- Click "Add custom domain"
- Follow DNS configuration instructions
- SSL certificate automatically provisioned
- Install Netlify CLI:
npm install -g netlify-cli- Login:
netlify loginCreate netlify.toml:
[build]
publish = "build/web"
command = "flutter build web --release"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
[build.environment]
FLUTTER_VERSION = "stable"# Build and deploy
netlify deploy --prod
# Or connect to Git for automatic deployments
netlify init- Go to Netlify Dashboard
- Add new site → Import from Git
- Connect repository
- Configure build settings:
- Build command:
flutter build web --release - Publish directory:
build/web
- Build command:
- Deploy automatically on push
- Install Vercel CLI:
npm install -g vercel- Login:
vercel loginCreate vercel.json:
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": {
"distDir": "build/web"
}
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/index.html"
}
]
}Create package.json (if not exists):
{
"name": "grex",
"version": "1.0.0",
"scripts": {
"build": "flutter build web --release"
}
}vercel --prod- Go to Vercel Dashboard
- Import Git Repository
- Configure project:
- Framework Preset: Other
- Build Command:
flutter build web --release - Output Directory:
build/web
- Deploy automatically on push
- Build web app:
flutter build web --release --base-href /grex/- Push to GitHub:
git subtree push --prefix build/web origin gh-pagesCreate .github/workflows/deploy-web.yml:
name: Deploy Web
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: subosito/flutter-action@v2
with:
flutter-version: 'stable'
- run: flutter pub get
- run: flutter build web --release --base-href /grex/
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build/web- Go to Repository Settings → Pages
- Source: Deploy from branch
- Branch:
gh-pages/root - Save
Your app will be available at:
https://<username>.github.io/<repository-name>/
- Go to AWS Amplify Console
- New app → Host web app
- Connect repository or deploy without Git
Create amplify.yml:
version: 1
frontend:
phases:
preBuild:
commands:
- echo "Installing Flutter..."
- curl -o flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.x.x-stable.tar.xz
- tar xf flutter.tar.xz
- export PATH="$PATH:`pwd`/flutter/bin"
- flutter --version
- flutter pub get
build:
commands:
- flutter build web --release
artifacts:
baseDirectory: build/web
files:
- '**/*'
cache:
paths:
- .dart_tool/pub-cache/**Create /etc/nginx/sites-available/grex:
server {
listen 80;
server_name your-domain.com;
root /var/www/grex/build/web;
index index.html;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# SPA routing
location / {
try_files $uri $uri/ /index.html;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
}# Build
flutter build web --release
# Copy to server
scp -r build/web/* user@server:/var/www/grex/build/web/
# Reload Nginx
ssh user@server "sudo nginx -t && sudo systemctl reload nginx"Use --dart-define for environment-specific builds:
flutter build web --release \
--dart-define=ENVIRONMENT=production \
--dart-define=BASE_URL=https://api.example.com \
--dart-define=ENABLE_ANALYTICS=trueFor runtime configuration, use a config file:
// lib/core/config/runtime_config.dart
class RuntimeConfig {
static Future<void> load() async {
final response = await http.get(Uri.parse('/config.json'));
final config = jsonDecode(response.body);
// Apply configuration
}
}Create web/config.json:
{
"environment": "production",
"baseUrl": "https://api.example.com",
"enableAnalytics": true
}Flutter web automatically splits code. For manual control:
// Use deferred imports
import 'package:my_package/my_package.dart' deferred as myPackage;
Future<void> loadFeature() async {
await myPackage.loadLibrary();
myPackage.useFeature();
}- Compress images: Use WebP format
- Lazy load: Load assets on demand
- CDN: Use CDN for static assets
# Use HTML renderer for smaller bundle
flutter build web --release --web-renderer html
# Or optimize CanvasKit
flutter build web --release --web-renderer canvaskit --dart-define=FLUTTER_WEB_USE_SKIA=false404 on refresh:
- Configure server to serve
index.htmlfor all routes - Use
--base-hrefflag for subdirectory deployments
API requests blocked:
- Configure CORS on backend
- Or use proxy in hosting configuration
Slow loading:
- Enable gzip compression
- Use CDN for assets
- Optimize images
- Consider code splitting
- Always use HTTPS: Required for many web APIs
- Set proper cache headers: Improve performance
- Monitor performance: Use Lighthouse, WebPageTest
- Test on multiple browsers: Chrome, Firefox, Safari, Edge
- Responsive design: Test on mobile devices
- SEO optimization: Add meta tags, structured data
- Error handling: Graceful degradation for unsupported features