-
Notifications
You must be signed in to change notification settings - Fork 2
Build Pipeline
360Ghar has three build tracks:
| Track | Command | When | Wall clock target |
|---|---|---|---|
| Deploy preview |
npm run build:preview (BUILD_FAST=1) |
Every Netlify deploy preview / branch deploy | few seconds |
| Production deploy |
npm run build:full (FULL_BUILD=1) |
GitHub Actions content-build.yml
|
several minutes (Puppeteer + API) |
| Content precompute | npm run build:content |
Scheduled precompute-content.yml
|
many minutes (API + images) |
Netlify preview builds do not install Chrome, scrape competitor sitemaps, crawl the property API, prerender 244 routes, or run heavy Vite plugins. Production deploys are built in GitHub Actions and uploaded via netlify-cli. The precompute-content.yml job refreshes vendored sitemaps, RSS, localities, and optimized images so those steps can be skipped on fast builds.
| File | Role |
|---|---|
scripts/build.mjs |
Orchestrator (fast vs FULL_BUILD=1, SKIP_PRECOMPUTE=1) |
scripts/build-content.mjs |
Precompute-only orchestrator (no Vite/Puppeteer) |
package.json |
build, build:full, build:content, build:preview, sub-scripts |
netlify.toml |
Deploy command = npm run build:preview; production builds ignored |
.github/workflows/content-build.yml |
main push + nightly full build + Netlify CLI deploy |
.github/workflows/precompute-content.yml |
Nightly content precompute + commit to main
|
vite.config.js |
Vite build (esbuild minify; BUILD_FAST disables PWA/compression) |
scripts/optimize-images.mjs |
WebP/AVIF variants with content-hash manifest |
scripts/prerender-pages.mjs |
Puppeteer prerender (full build only) |
scripts/lib/prerenderCache.mjs |
Prerender HTML cache (full build only) |
"build": "node scripts/build.mjs",
"build:full": "FULL_BUILD=1 node scripts/build.mjs",
"build:content": "node scripts/build-content.mjs",
"build:preview": "BUILD_FAST=1 npm run build:ai-discovery && BUILD_FAST=1 node scripts/generate-og-image.mjs && BUILD_FAST=1 vite build"flowchart TD
A[ai-discovery] --> B[OG image]
B --> C[vite build esbuild]
C --> D[dist/]
Steps:
-
build:ai-discovery+ OG image. -
vite build— esbuild minify, no gzip/brotli, no PWA, no image re-processing.BUILD_FAST=1disables heavy plugins.
Skipped on deploy preview: Chrome install, entity scrape, sitemap/RSS generation, image optimization, Puppeteer prerender, CSS purge, IndexNow, PWA, compression.
flowchart TD
C1[entities scrape] --> C2[sitemaps API + static]
C2 --> C3[RSS]
C3 --> C4[images + OG]
C4 --> C5[vite build]
C5 --> C6[CSS purge]
C6 --> C7[Chrome install]
C7 --> C8[prerender 244 routes]
C8 --> C9[bootstrap purge]
C9 --> C10[IndexNow]
C10 --> Dist[dist/]
Same stages as the historical production pipeline: entities, full sitemaps (including dynamic property crawl), RSS, images, vite, CSS purge, Chrome install, concurrent Puppeteer prerender (~244 routes), IndexNow.
When SKIP_PRECOMPUTE=1 is set, the entities/sitemaps/RSS/images/OG/AI-discovery steps are skipped and the vendored artifacts from main are reused. This is used by the content-build.yml push trigger.
The precompute-content.yml job commits these so preview builds and content-build.yml push builds can skip regeneration:
-
src/data/localities.json,src/data/localities-index.json -
public/sitemap*.xml(static, landing, localities, datahub, properties, blog, projects) -
public/rss.xml,public/rss/* -
public/.well-known/ai.txt,public/.well-known/api-catalog -
public/llms.txt,public/llms-full.txt,public/data/llm-feed.json public/og-image-home.jpg-
public/assets/images/**/*.webpand**/*.avif scripts/image-optimization-manifest.json
- Concurrency:
PRERENDER_CONCURRENCY(default 5, max 8). - Cache dir:
PRERENDER_CACHE_DIR(defaultnode_modules/.cache/prerender-html). - Cache keys include vite asset hash + bulk-data hash — any code or live listing change tends to cold-miss. Do not rely on this cache to make deploys fast; keep prerender off the deploy path instead.
- Bulk data:
fetch-prerender-data.mjs→dist/prerender-data.json.
[build]
publish = "dist"
command = "npm run build:preview"
[build.environment]
NODE_VERSION = "20"
VITE_API_SERVER = "https://api.360ghar.com"
VITE_API_BASE_URL = "https://api.360ghar.com/api/v1"
SKIP_BROTLI = "1"
[context.production]
ignore = "echo 'Production built by GitHub Actions' && exit 0"Netlify only builds deploy previews and branch deploys. Production deploys are uploaded from GitHub Actions.
- Triggers:
pushtomain, nightly cron (~00:00 IST),workflow_dispatch - Runs
npm run build:full(withSKIP_PRECOMPUTE=1onpushto reuse vendored artifacts) - Deploys with
netlify-cliwhen secretsNETLIFY_AUTH_TOKENandNETLIFY_SITE_IDare set
- Triggers: nightly cron (~30 minutes before
content-build.yml),workflow_dispatch - Runs
npm run build:contentand commits the vendored artifacts tomainwith[skip ci] - Keeps
public/,src/data/, andscripts/image-optimization-manifest.jsonup to date so preview builds can skip heavy work
Scrapes Magicbricks / SquareYards / NoBroker / CommonFloor; writes localities.json + index + locality sitemap.
write-ai-discovery.mjs → ai.txt, api-catalog, llms.txt, llm-feed.json.
Static, landing, localities, datahub (API), dynamic properties/blog (API).
Blog + properties + localities feeds.
optimize-images.mjs — WebP/AVIF (+ responsive widths for heroes). Idempotent.
esbuild minify; PurgeCSS on entry CSS and Bootstrap.
Route manifest → bulk API data → Puppeteer capture to dist/**/*.html.
Submit same-host sitemap URLs after full build.
Unchanged: netlify/edge-functions/ (markdown-negotiation.js, soft-404-guard.js). Soft-404 still covers SPA routes that are not prerendered on fast deploys.
- Production treated every deploy as a full content build.
- Chrome + 244 Puppeteer routes dominated wall time.
- API property crawls + competitor entity scrapes added more network minutes.
- Vite re-optimized images already processed by Sharp; terser minify was slower than esbuild.
- Prerender cache almost always missed (global bulk-data hash + per-deploy asset hash).
- Node >= 18 (Netlify pins 20).
-
Puppeteer only required for
build:full. -
sharp for
optimize-images.mjs. - ESLint stays on major 9 (peer constraint with
eslint-plugin-react).
- SEO & Programmatic
- Internationalization
- Authentication — prerender skips auth init
- Analytics — prerender skips PostHog