Analog on Launch
Analog.js is an open-source meta-framework built on Angular, designed to deliver modern, server-first, highly performant applications. It provides support for hybrid rendering, API routes, file-based routing, content hydration, and seamless integration with server runtimes.
Supported Features in Contentstack Launch
Rendering Strategies
Analog.js supports multiple rendering modes including Server-Side Rendering (SSR), Static Rendering, ISR (Incremental Static Regeneration), and API Routes. All of these modes are compatible with Contentstack Launch.
Server-Side Rendering (SSR)
Analog.js supports server-side rendering using Analog's server build.
Launch supports Analog's SSR model, enabling dynamic, per-request rendering.
To enable SSR, configure Analog in the vite.config.ts file:
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
export default defineConfig({
plugins: [
analog({
ssr: true, // Enable server-side rendering
nitro: {
routeRules: {
// Configure route-specific SSR and caching
},
},
}),
],
});Additional Resource: Refer to the Quick Start Guide with Analog documentation for a step-by-step walkthrough to deploy an Analog Starter on Launch as an SSR-based application.
Static Rendering (Pre-rendering)
Analog.js supports static HTML generation for pages that do not require runtime data.
Launch serves these assets directly from the global CDN.
To pre-render a route, define it in vite.config.ts:
export default defineConfig({
plugins: [
analog({
ssr: true,
prerender: {
routes: [
'/',
'/about-us'
]
},
}),
],
});These pages are pre-rendered at build time by Analog’s Nitro-based prerenderer and cached at the edge.
Incremental Static Regeneration (ISR)
Launch supports ISR for Analog.js using HTTP caching headers configured via Nitro route rules.
Analog.js pages can define Cache-Control headers in vite.config.ts to define the revalidation interval:
analog({
ssr: true,
nitro: {
routeRules: {
'/isr': {
ssr: true,
headers: {
'Cache-Control': 'public, s-maxage=40, stale-while-revalidate=60',
},
},
},
},
})API Routes
Analog.js supports creating API routes using the Nitro server framework with h3. API routes are defined in the src/server/routes/api directory and are automatically exposed under the /api prefix.
Creating an API Route
API routes use defineEventHandler from h3 to handle requests. The file structure maps directly to the URL path:
// src/server/routes/api/test.ts → /api/test
import { defineEventHandler } from 'h3';
export default defineEventHandler(() => ({
message: 'Test API endpoint',
status: 'success',
timestamp: new Date().toISOString(),
}));HTTP Method-specific Routes
Create method-specific handlers by suffixing the filename (for example, test.post.ts, test.put.ts, test.delete.ts):
// src/server/routes/api/test.post.ts
import { defineEventHandler, readBody, createError } from 'h3';
export default defineEventHandler(async (event) => {
const body = await readBody(event);
if (!body.message) {
throw createError({ statusCode: 400, statusMessage: 'Missing required fields' });
}
return { success: true, data: body };
});Sitemap Generation
Analog.js supports automatic sitemap generation. Analog generates a sitemap in the dist/analog/public directory when running a build if a sitemap configuration is provided.
Note: Since the sitemap is generated at build time, only prerendered routes are included; SSR and client-side–only pages are excluded.
Sitemap generation is configured in the vite.config.ts file:
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
export default defineConfig({
plugins: [
analog({
ssr: true,
prerender: {
routes: async () => ['/', '/blog'],
sitemap: {
host: 'https://your-domain.com',
},
},
}),
],
});Customizing Sitemap Entries
You can customize individual sitemap entries by defining changefreq, priority, and lastmod for each prerendered route.
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
export default defineConfig({
plugins: [
analog({
ssr: true,
prerender: {
routes: async () => [
{
route: '/',
sitemap: {
changefreq: 'daily',
priority: '1.0',
},
},
{
route: '/about-us',
sitemap: {
changefreq: 'monthly',
priority: '0.8',
},
},
],
sitemap: {
host: 'https://your-domain.com',
},
},
}),
],
});Sitemap Options:
- changefreq: How frequently the page changes ("always", "hourly", "daily", "weekly", "monthly", "yearly", "never").
- priority: URL priority relative to other URLs ("0.0" to "1.0", default: "0.5").
- lastmod: Last modification date of the page (optional).
Additionally, the host value must be provided at the prerender sitemap level to define the base URL of the site.
Content Routes (Analog.js)
Analog.js allows you to use Markdown files as routes, creating content-driven pages without manually writing Angular components. Frontmatter metadata in .md files can define titles, descriptions, and other page info. (analogjs.org)
Setup
Enable content in your app.config.ts:
import { ApplicationConfig } from '@angular/core';
import { provideContent, withMarkdownRenderer } from '@analogjs/content';
export const appConfig: ApplicationConfig = {
providers: [
provideContent(withMarkdownRenderer()),
],
};Enable content support in vite.config.ts:
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
export default defineConfig({
plugins: [
analog({
content: {
highlighter: 'prism', // optional: for code highlighting
},
}),
],
});Defining Content Routes
Place .md files in src/app/pages; the filename defines the route:
src/app/pages/about.md → /aboutExample for about.md:
---
title: About
---
## About Our Project
Welcome to our documentation site!Defining Content Files (Analog.js)
In Analog.js, you can define flexible content outside of route components by placing Markdown content files in a dedicated folder. This is especially useful for blog posts, articles, and other markdown-based content that isn’t tied directly to a routed page file.
Where to Put Content Files
Create a src/content directory in your project root:
src/
└── content/
├── post1.md
├── post2.md
└── ...Files in this folder are treated as content sources rather than page routes, giving you the flexibility to load and display them anywhere in your app.
What a Content File Looks Like
Each Markdown file should include frontmatter metadata to describe the content. For example:
---
title: My First Post
slug: 2022-12-27-my-first-post
description: A short summary of this post
coverImage: https://example.com/my-image.jpg
---
Hello World!The slug and other fields help you identify and organize content when you render it or generate lists of posts.
Launch Analog Server Configuration
Refer to the Server Configuration document to learn about the Analog server configuration.
Caching in Analog on Launch
By default, all the pages are cached on Launch’s CDN when you deploy Analog as SSR. This means that the subsequent requests to the same page are cached, and the page is not regenerated.
API Routes Caching
By default, API routes are not cached. You can configure caching for specific API routes using Nitro route rules in vite.config.ts as given below:
nitro: {
routeRules: {
'/api/test': {
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=30',
},
},
},
}You can override caching behavior per route using Nitro route rules in vite.config.ts:
Disable caching
nitro: {
routeRules: {
'/ssr': {
headers: {
'Cache-Control': 'no-store',
},
},
},
}Static Assets Caching
nitro: {
routeRules: {
// Static assets with content hashes (immutable)
'/assets/**': {
headers: {
'Cache-Control': 'public, s-maxage=31536000, immutable',
},
},
// CSS files
'/*.css': {
headers: {
'Cache-Control': 'public, s-maxage=31536000',
},
},
// JavaScript files
'/*.js': {
headers: {
'Cache-Control': 'public, s-maxage=31536000',
},
},
},
}Cache with Tags (for Cache Purging)
Use cache tags to enable selective cache invalidation:
nitro: {
routeRules: {
'/cache-purge': {
ssr: true,
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=30',
'Cache-Tag': 'cachetest',
},
},
},
}Additional Resource: Refer to the Caching Guide for Contentstack Launch for more information.
Cache-Revalidation Strategies
Analog.js supports two cache revalidation strategies: time-based revalidation and on-demand revalidation. For detailed information on revalidating CDN cache using URL paths, Cache-Tags, or hostnames, refer to the Revalidate CDN Cache documentation.
(i) Time-Based Revalidation
Configure routes with time-based revalidation using s-maxage and stale-while-revalidate:
nitro: {
routeRules: {
'/isr': {
ssr: true,
headers: {
'Cache-Control': 'public, max-age=0, s-maxage=60, stale-while-revalidate=30',
},
},
},
}(ii) On-Demand Revalidation
You can trigger on-demand revalidation using Automate: Revalidate CDN cache using Automate.
Note: Ensure you revalidate the cache for the data endpoint that backs the content, in addition to the page URL. This is important if your page uses cached API endpoints for data delivery. Example: domain/api/api-route
This page will be server-rendered on each request when accessed at /ssr (unless cached).
Limitation
Currently, Edge URL Rewrites are not supported for Analog.js applications on Contentstack Launch.
Example Git Repository
A fully implemented version of this project is available in the following Git repository, which serves as the reference for the complete configuration and implementation.
Repository Link: Analog.js Example Starter Repository
