ISR-Ready Architecture with Full Static Fallback
Context
Incremental Static Regeneration (ISR) is a Next.js feature that allows static pages to be revalidated after deployment without a full rebuild. For a portfolio with infrequently changing content, ISR could eliminate the rebuild-redeploy cycle for content updates — pages would regenerate in the background when stale. However, ISR introduces runtime complexity: it requires a serverless function layer (Vercel Functions) that runs on-demand, adds a stale-while-revalidate caching behavior that can serve outdated content during regeneration, and creates a dependency on Vercel's ISR infrastructure availability. If ISR fails silently, pages could serve stale data indefinitely. The site must function correctly with pure static generation as the baseline.
Decision
Design the data-fetching architecture to be ISR-compatible but deploy with full static generation as the default. All getStaticProps functions are structured to accept a revalidate parameter that is currently commented out. The data-fetching patterns use standard HTTP requests that work identically whether called at build time (SSG) or at revalidation time (ISR). No getStaticProps function depends on build-time-only context (like environment variables that differ between build and runtime). The architecture is ready to enable ISR by uncommenting a single revalidate property per page — but currently runs as pure SSG with zero serverless function invocations.
Consequences
Positive: The site operates with maximum resilience — static HTML served from CDN edge with no runtime dependencies. If Vercel's serverless infrastructure experiences issues, the site is unaffected because no serverless functions are invoked. When content freshness becomes a priority (e.g., frequent portfolio updates), ISR can be enabled per-page by adding `revalidate: 3600` to any getStaticProps — no architectural changes required. The cost is zero serverless function invocations on the current plan. Negative: Content updates require a manual redeploy, adding ~90 seconds of latency between publishing content and it appearing on the site. The commented-out revalidate properties are a form of dead code that could confuse future contributors. The ISR-ready constraint means getStaticProps cannot use any build-time-only APIs or file system operations that wouldn't be available in the serverless runtime. This is a resilience-first architecture: the site trades content freshness for operational simplicity and infrastructure independence.
Predictions at Decision Time
Expected the ISR-ready constraint to be cost-free — predicted that no getStaticProps function would need build-time-only context. Predicted ISR would eventually be activated when content updates became frequent enough to justify it (estimated threshold: daily updates). Assumed the commented-out revalidate parameters would serve as clear documentation of ISR-readiness.
Measured Outcomes
The ISR-ready constraint has been cost-free as predicted — no getStaticProps function needed build-time-only context, and the local JSON import for ADRs (ADR-008) works identically in SSG and ISR modes. ISR has not been activated because content update frequency has not reached the daily threshold — updates cluster in bursts (multiple per day during active development, then weeks of stability). The commented-out revalidate parameters exist in API-fetching pages but are less relevant for the ADR pages that use local imports. The 90-second redeploy cycle remains acceptable. The unexpected outcome: the discipline of ISR-readiness prevented a potential architectural mistake when adding local JSON imports — the pattern is explicitly compatible with both SSG and ISR, not just SSG.
Unknowns at Decision Time
Did not know whether Next.js would introduce a better alternative to ISR. Next.js 15's App Router with server components represents a different paradigm entirely — one where the SSG/SSR/ISR distinction is less relevant. If the site migrates to App Router, the ISR-ready constraint becomes moot. Also unknown: whether Vercel would introduce usage-based pricing changes that make ISR's serverless invocations a cost concern. The zero-cost guarantee of pure SSG is a financial hedge that ISR cannot match.
Reversibility Classification
Activating ISR requires uncommenting revalidate properties in getStaticProps — a one-line change per page. Deactivating ISR requires re-commenting them. The entire toggle between SSG and ISR is a configuration change with zero code modifications. Estimated effort to activate: 30 minutes for all pages plus testing. Estimated effort to deactivate: 15 minutes. This is the most reversible decision in the entire architecture.
Strongest Counter-Argument
The ISR-ready architecture adds invisible complexity: future developers must understand why getStaticProps functions are written in a specific way (no build-time-only context) without the constraint being visible in the code. The commented-out revalidate parameters are dead code by any linting standard. A simpler approach: build with pure SSG, no ISR considerations, and refactor when ISR is actually needed. The refactoring cost is low (each page is independent), so the pre-optimization is arguably YAGNI. The counter-counter: the constraint is not a cost — it's a discipline that prevents architectural drift and keeps future options open at zero marginal effort.
Technical Context
- No build-time-only dependencies in getStaticProps
- Pure static as default
- ISR activation requires only config change