CSP (Cacheable Server Props) Page
This works like SSR (server-rendered) page, however, the ctx we pass back to you only contains static data, so the page can be cached.
The cacheableServerProps helper
Export getServerSideProps with the cacheableServerProps helper.
Note that because the ctx we provide to you only contains static data, you will implement your data-fetching logic inside the getStaticProps function.
import { cacheableServerProps, callAPI } from '@traveloka/core';
export default MyPage() {
return <>Hello</>
}
export const getServerSideProps = cacheableServerProps({
resources: [MyComponentRQ, MyOtherComponentRQ],
getStaticProps: async (ctx, rawAppContext) => {
const res = await callAPI(ctx, options);
return {
props: {
myData: res.result.data,
},
// Default is 10m (600s)
revalidate: 10 * 60,
};
},
});
Dynamic Path Configuration
For Next.js routes with dynamic segments (e.g., [token], [id]), you need to configure webcfn to enable caching.
Configuration File
Add path patterns to packages/proxies/webcfn/lambda/config.json:
[
{
"pattern": "/booking/v2/[token]"
},
/**
* Prevent '/activities/country/product/xxx' being replaced
*/
{
"pattern": "/activities/country/product/[nameId]",
"rewrite_uri": false
},
{
"pattern": "/activities/[country]/[type]/[nameId]"
}
]
Supported Pattern Formats
[param]- Single dynamic segment (e.g.,[token],[id])- Multiple dynamic segments in one path are supported
[...param](catch-all) is NOT supported for caching
How It Works
When a request matches a configured pattern:
-
Path Rewrite: Dynamic segments are replaced with parameter names
/booking/v2/abc123→/booking/v2/token
-
Headers Added:
X-Custom-Origin-Uri: Original path for downstream routing
-
Query Parameter:
__cfnrewrite__=1is appended to mark the rewrite -
Client-Side: The browser URL remains unchanged;
useNextRouteranduseCurrentRoutehandle the mapping
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
pattern | string | required | Path pattern with dynamic segments in brackets |
rewrite_uri | boolean | true | Set to false to disable rewriting for this pattern |
Important Notes
- Patterns must start with
/ - Locale prefix (e.g.,
/id-id,/en-sg) is automatically handled - The rewrite happens at the CloudFront edge (webcfn Lambda)
- Original dynamic values are preserved in
X-Custom-Origin-Uriheader for routing decisions
Developer Testing & Release Guide
1. Local Configuration
Configure the dynamic path pattern in @packages/proxies/webcfn/lambda/config.json:
[
{
"pattern": "/booking/v2/[token]"
}
]
2. Local Development Testing
After configuring the file, the Next.js Service will receive the static path (e.g., /booking/v2/token). The original path is preserved in the Request Header X-Custom-Origin-Uri.
Verify Path Rewrite Success:
Open browser console and check __NEXT_DATA__.query:
__NEXT_DATA__.query;
// Expected output if rewrite is successful:
// { token: "token" } // Static value, not the dynamic value like "abc123"
If the rewrite is successful, dynamic parameters will show static values (parameter names) instead of actual dynamic values.
Ensure the page behaves correctly in local environment.
3. PR Environment Testing
Verify Path Rewrite in PR:
Similarly, open browser console in the PR environment and check:
__NEXT_DATA__.query;
// Should show static parameter names, not dynamic values
Confirm dynamic parameters have been replaced with static values and the page functions correctly.
4. Staging Environment Deployment
After confirming the page works correctly in PR:
- Contact the Infra team to deploy the page to the staging environment
- Configure the staging CDN with the webcfn Lambda
- Verify CDN Caching is active - check response headers for cache hits
- Test that the page behaves correctly in the staging environment
5. Production Release
Once staging testing is complete:
-
Merge the code and release a new version
-
⚠️ CRITICAL: Deployment Order
You MUST deploy in this order:
First: Deploy www Next.js server
Then: Contact Infra team to deploy CloudFront CDN changes to production
Why this order matters:
- The www Next.js server can work without the CDN path rewrite Lambda
- However, if you deploy the CDN Lambda first but your www page isn't adapted for static paths, it will cause errors
- The www server handles both dynamic and static paths gracefully
6. Post-Production Verification
After CDN deployment:
- Verify pages are being served from CDN cache
- Check
__NEXT_DATA__.queryin production to confirm static values - Monitor for any errors or unexpected behavior
- Ensure all dynamic paths are working correctly
Summary of Key Points:
- ✅ Configure
config.jsonfor dynamic paths - ✅ Verify using
__NEXT_DATA__.query(should show static values) - ✅ Test in local → PR → Staging → Production
- ✅ Critical: Deploy www server BEFORE CDN changes
- ✅ Contact Infra team for staging and production CDN configuration
Query String Stripping
For CSP pages, you can strip non-cacheable query params before the request reaches Next.js. This helps prevent sensitive or non-deterministic query values from being embedded in SSR HTML (for example inside __NEXT_DATA__.query), while keeping the browser URL unchanged.
How to Configure
- Add your cache key type in
packages/core/next/view-cache-key/types.ts:
export type FlightCSPCacheKey = 'ap' | 'utm_source' | 'findcheapestdate';
export type CSPCacheKey = PaymentCSPCacheKey | FlightCSPCacheKey;
- Add route-level preserved query keys in
packages/core/next/view-cache-key/queryCacheKeySetting.ts:
export const FlightQueryCacheKeySetting: {
[pathname: string]: Array<FlightCSPCacheKey>;
} = {
'/flight/fullsearch': ['ap', 'findcheapestdate', 'utm_source'],
};
export const queryCacheKeySetting: {
[pathname: string]: Array<CSPCacheKey>;
} = {
...FlightQueryCacheKeySetting,
...PaymentQueryCacheKeySetting,
};
-
Export your setting from
packages/core/next/view-cache-key/index.ts. -
Wire middleware in the app server:
import { queryStripMiddleware } from '@traveloka/core/server';
import { FlightQueryCacheKeySetting } from '@traveloka/core/next/view-cache-key';
server.use(queryStripMiddleware(FlightQueryCacheKeySetting));
Example
Input URL:
https://www.traveloka.com/en-id/flight/fullsearch?ap=CGK.AMS&dt=28-11-2025.NA&ps=1.0.0&sc=ECONOMY
Config:
{
'/flight/fullsearch': ['ap', 'utm_source', 'findcheapestdate']
}
URL received by Next.js server:
https://www.traveloka.com/en-id/flight/fullsearch?ap=CGK.AMS&__cfnrewrite__=1
In this example, only configured cache keys (plus default preserved keys) remain.
Default Preserved Keys and Behavior
- Always preserved:
cur,currency,__nextDataReq __cfnrewrite__=1is appended when stripping happens- Browser URL does not change; stripping only affects server-side request handling
- Client hooks (
useNextRouter,useCurrentRoute) restore stripped query params from the real browser URL
Hydration Note
When stripped params affect render output, use hydrationSafe: true in useNextRouter / useCurrentRoute to avoid hydration mismatch. Use default behavior (hydrationSafe: false) when those params do not affect SSR HTML output.