Comprehensive guide for deploying the Blend Design System documentation (Ascent) and Storybook to Firebase Hosting.
# Deploy to staging
npm run deploy:dev
# Deploy to production
npm run deploy:prodURLs:
- 📚 Production Docs: https://juspay.design
- 📖 Production Storybook: https://juspay.design/storybook
- 📚 Staging Docs: https://blend-staging.web.app
- 📖 Staging Storybook: https://blend-staging.web.app/storybook
┌─────────────────┐ ┌──────────────────┐
│ Documentation │ │ Storybook │
│ (Ascent) │ │ (Storybook 8) │
│ Next.js │ │ │
└────────┬────────┘ └────────┬─────────┘
│ │
└───────────┬───────────┘
│
┌──────▼──────┐
│ Firebase │
│ Hosting │
└─────────────┘
- Single Firebase Project:
storybook-452807 - Path-based Routing:
/→ Ascent documentation/storybook/*→ Storybook
- Static Export: Both apps are built as static sites
- Client-side Search: No server required
| Environment | Target | URL | Purpose |
|---|---|---|---|
| Production | blend-prod |
https://juspay.design | Live Site |
| Staging | blend-staging |
https://blend-staging.web.app | Testing & Review |
-
Install Dependencies
# Install pnpm if not already installed npm install -g pnpm # Install project dependencies pnpm install # Install Firebase CLI npm install -g firebase-tools
-
Firebase Login
firebase login
The project uses two environment files:
.env.dev- Staging environment configuration.env.prod- Production environment configuration
These files contain:
# Example .env.dev
FIREBASE_PROJECT_ID=storybook-452807
FIREBASE_HOSTING_TARGET=blend-staging
DEPLOY_URL=https://blend-staging.web.app
# Example .env.prod
FIREBASE_PROJECT_ID=storybook-452807
FIREBASE_HOSTING_TARGET=blend-prod
DEPLOY_URL=https://juspay.design# Ascent documentation development
npm run ascent:dev
# Storybook development
npm run storybook
# Build everything
npm run build:all
# Build specific apps
npm run build:ascent
npm run build:storybookThe deployment process uses a unified script (deploy.sh) that:
- Loads environment variables from
.env.devor.env.prod - Builds Ascent documentation (with search index generation)
- Builds Storybook
- Combines both builds into a single
dist/directory - Deploys to Firebase Hosting
# Deploy to staging
npm run deploy:dev
# Deploy to production
npm run deploy:prod-
Ascent Documentation (
/)- Next.js static export
- MDX documentation pages
- Client-side search with pre-built index
- Component examples and previews
-
Storybook (
/storybook)- Component stories
- Interactive playground
- Design tokens
- Usage examples
-
Static Assets
- Fonts
- Images
- Search index (
search-index.json)
-
Create MDX File
# Create new component doc touch apps/ascent/app/docs/content/components/NewComponent.mdx -
MDX Format
--- title: Component Name description: Brief description for search category: Components tags: [tag1, tag2] --- # Component Name Component description and usage. ## Usage ```jsx import { Component } from 'blend-v1' ;<Component prop="value" /> ``` ## Props <DocsTypeTable>...props documentation...</DocsTypeTable>
-
Update Navigation
Edit
apps/ascent/app/docs/content/config.jsonto add your new component to the navigation.
The search system uses a build-time generated index:
- What's Indexed: All MDX content including titles, headings, content, and tags
- When: At build time via
prebuildscript - How: Static JSON file loaded client-side
- Script:
apps/ascent/scripts/generate-search-index.mjs
All deployments include comprehensive security headers configured in firebase.json:
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Strict-Transport-Security: max-age=31536000; includeSubDomains (production only)
Content-Security-Policy: [configured for your needs]
- Never commit
.env.devor.env.prodfiles (they're gitignored) - Store secrets in GitHub Secrets for CI/CD
- Rotate credentials regularly
| Resource | Staging | Production |
|---|---|---|
| HTML | No cache | No cache |
| JS/CSS | 1 hour | 1 year |
| Images | 1 day | 1 week |
| Fonts | 1 week | 1 year |
# Clean everything and try again
npm run clean
pnpm install
npm run build:allThe search index is generated at build time. If search isn't working:
- Check if
apps/ascent/public/search-index.jsonexists after build - Ensure the
prebuildscript runs:node scripts/generate-search-index.mjs - Verify MDX files have proper frontmatter
If you encounter "window is not defined" errors during build:
- Preview components use dynamic imports with
ssr: falseviaPreviewWrapper - All preview components are wrapped to prevent SSR issues
- The
PreviewWrappercomponent handles client-side rendering
firebase login --reauth
firebase projects:list- Check Firebase Console for quota limits
- Ensure
.env.devand.env.prodfiles exist - Verify Firebase hosting targets are configured
- Make sure
deploy.shis executable:chmod +x deploy.sh
# Check Firebase project
firebase projects:list
# Check hosting targets
firebase target:list
# Test builds locally
npm run build:ascent
npm run build:storybook
# View Firebase hosting releases
firebase hosting:releases:list --site blend-staging
firebase hosting:releases:list --site blend-prodblend-design-system/
├── deploy.sh # Unified deployment script
├── .env.dev # Staging environment config
├── .env.prod # Production environment config
├── dist/ # Combined deployment directory
│ ├── index.html # Ascent root
│ ├── search-index.json # Search index
│ ├── [ascent files] # All Ascent static files
│ └── storybook/ # Storybook subdirectory
│ └── index.html # Storybook root
└── apps/
├── ascent/ # Main documentation
│ ├── out/ # Next.js build output
│ └── scripts/ # Build scripts
│ └── generate-search-index.mjs
└── storybook/ # Component library
└── storybook-static/ # Storybook build output
.firebaserc
{
"projects": {
"default": "storybook-452807"
},
"targets": {
"storybook-452807": {
"hosting": {
"blend-staging": ["blend-staging"],
"blend-prod": ["blend-prod"]
}
}
}
}firebase.json
- Configures rewrites for path-based routing
- Sets security headers
- Defines cache policies
- Handles
/storybookpath routing
{
"scripts": {
// Development
"ascent:dev": "cd apps/ascent && npm run dev",
"storybook": "cd apps/storybook && pnpm dev",
// Building
"build:ascent": "cd apps/ascent && npm run build",
"build:storybook": "cd apps/storybook && pnpm build-storybook",
"build:all": "npm run build:ascent && npm run build:storybook",
// Deployment
"deploy:dev": "./deploy.sh dev",
"deploy:prod": "./deploy.sh prod",
// Utilities
"clean": "turbo run clean && rm -rf node_modules dist apps/ascent/out apps/storybook/storybook-static"
}
}The production deployment is configured with the custom domain juspay.design. The DNS configuration and SSL certificates are managed through Firebase Hosting.
Last updated: January 2025