with one click
corp-web-japan-preview-navigation-links
// Apply selective `/t/...` preview navigation links in corp-web-japan using a small `t("/path")` helper that defaults to preview outside production.
// Apply selective `/t/...` preview navigation links in corp-web-japan using a small `t("/path")` helper that defaults to preview outside production.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | corp-web-japan-preview-navigation-links |
| description | Apply selective `/t/...` preview navigation links in corp-web-japan using a small `t("/path")` helper that defaults to preview outside production. |
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| metadata | {"hermes":{"tags":["corp-web-japan","preview","navigation","header","footer","environment"]}} |
Use this when the user wants some navigation links in corp-web-japan to point to /t/... preview pages in non-production, while keeping production links unchanged.
Typical cases:
/t/... preview implementations.href: t("/about-us") rather than a large mode/config abstraction.Prefer a tiny helper with explicit call sites:
href: t("/about-us")
This is preferred over:
preview mode prop passed through layout/header/footerWhy:
Do not use process.env.NODE_ENV !== "production" directly for this repo pattern.
Instead, add src/lib/is-production.ts and mirror the proven corp-web-app helper exactly:
const isProduction = () => {
return process.env.VERCEL_TARGET_ENV === 'production';
};
export default isProduction;
Then implement the preview helper like:
import isProduction from "@/lib/is-production";
export function t(path: string) {
return !isProduction() ? `/t${path}` : path;
}
Reason:
VERCEL_TARGET_ENV === 'production' is the chosen production signal hereThere are now two valid patterns depending on the user's request.
Use this when the user wants selected links to point to /t/... automatically outside production, with no user-facing toggle.
src/lib/is-production.tssrc/lib/preview-path.tsImport t where needed and apply it only to routes that should use preview by default outside production.
Use this when the user wants a visible preview-mode control in stage/preview deployments that can turn /t/... navigation on and off interactively.
This pattern was used for PR 179 follow-up work.
/t linkssrc/lib/preview-navigation.ts
t(path, previewModeEnabled)src/app/api/preview-navigation/route.ts
on / off)src/components/layout/site-header.tsx
src/components/layout/site-header-client.tsx
src/components/layout/preview-mode-toggle.tsx
router.refresh()src/components/layout/site-footer.tsx
t(..., previewModeEnabled) logicpreviewModeEnabled is truesrc/components/layout/site-footer.module.css
previewModeEnabled is trueThe header was already a client component for dropdown state, while footer/sidebar links need server-consistent href generation. The safest low-scope pattern is:
This avoids trying to make environment-based navigation decisions independently in multiple client components.
Important extension learned from follow-up debugging:
links={previewResourceCategorySidebarLinks} overrides for /t/... routes/whitepapers can silently reset the sidebar back to public links even while header/footer still show preview navigationPREVIEW_NAVIGATION_COOKIE + getPreviewNavigationState(...), while still allowing an explicit links prop override where a page intentionally needs a fixed link setExamples:
src/components/layout/site-header.tsxsrc/components/layout/site-footer.tsxsrc/components/sections/news-list-page.tsxExample:
{ label: "私たちについて", href: t("/about-us") }
{ label: "ニュース", href: t("/news") }
{ label: "ホワイトペーパー", href: t("/whitepapers") }
Leave normal links alone:
{ label: "お問い合わせ", href: "/contact-us" }
Only wire t("/path") for preview pages that actually exist on the current main branch.
Before changing links, verify whether the target route exists, e.g.:
src/app/t/about-us/page.tsxsrc/app/t/news/page.tsxsrc/app/t/whitepapers/page.tsxsrc/app/t/events/page.tsxIf a route is not on main yet, do not point navigation at it just because a preview idea exists.
Practical example from this task:
/t/about-us, /t/news, /t/whitepapers, /t/events existed on main/t/certifications did not exist on main/certifications was intentionally left unchanged until the preview page landsUse this when the user wants a preview-only link added under existing header/footer resource menus, but only while Preview Toggle is enabled.
Example requirement:
イベント under ブログ in the GNB resource menuイベント link under ブログ in the footer resource menu/t/events only when preview navigation is enabledRecommended implementation in both:
src/components/layout/site-header-client.tsxsrc/components/layout/site-footer.tsxPattern:
{ label: "ホワイトペーパー", href: "/whitepapers" },
{ label: "ブログ", href: "/blog" },
...(previewModeEnabled ? [{ label: "イベント", href: t("/events", previewModeEnabled) }] : []),
Why this exact pattern:
t() helper so the preview target becomes /t/eventsDo not:
t(...) unless the task explicitly asks for thatWhen adding a preview-only item to header/footer resource menus, update existing source-string tests in the same PR.
Current relevant tests:
tests/canonical-endpoints.test.mjstests/link-and-metadata-integrity.test.mjsExpected string to add:
'label: "イベント", href: t("/events", previewModeEnabled)'
If the repo uses the shared resource sidebar component in src/components/sections/resource-category-sidebar.tsx, also update its preview link set in the same PR.
Current required preview sidebar entry:
{ label: "イベント", href: "/t/events" }
Why:
イベント correctly while the shared resource sidebar still omits it/whitepapers can therefore reproduce a partial preview-navigation mismatch even when GNB and footer are already fixedRecommended test alignment:
tests/resource-list-page-structure.test.mjsイベント -> /t/eventsKeep the change minimal:
src/app/t/events/page.tsx already existsKeep the change minimal:
Use this when the user wants the デモ section in the GNB or footer to switch between preview and public destinations with the same Preview Toggle behavior used elsewhere.
Recommended implementation:
src/components/layout/site-header-client.tsxsrc/components/layout/site-footer.tsxpreviewModeEnabled valueCurrent proven pattern:
Header:
{ label: "活用事例", href: t("/use-cases", previewModeEnabled) }
{ label: "AIP機能", href: t("/demo/aip", previewModeEnabled) }
{ label: "ACP機能", href: t("/demo/acp", previewModeEnabled) }
Footer:
{ label: "活用事例", href: t("/use-cases", previewModeEnabled) }
{ label: "AIP 機能", href: t("/demo/aip", previewModeEnabled) }
{ label: "ACP 機能", href: t("/demo/acp", previewModeEnabled) }
Result:
/t/use-cases, /t/demo/aip, /t/demo/acp/use-cases, /demo/aip, /demo/acpImportant repo-specific nuance learned here:
/use-cases, not /demo/use-cases, when using the Preview Toggle helper patternAIP機能 / ACP機能, but the footer currently uses AIP 機能 / ACP 機能 with a space; keep string-based tests aligned with the actual component text instead of normalizing them speculativelyRecommended verification:
tests/link-and-metadata-integrity.test.mjstests/canonical-endpoints.test.mjstests/footer-preview-navigation.test.mjsnpm run typecheckUse this when the user wants footer-only preview navigation that should appear only while the Preview Toggle is enabled.
Recommended implementation:
internalFooterColumn object inside src/components/layout/site-footer.tsx...(previewModeEnabled ? [internalFooterColumn] : [])/internal/internal/whitepaper-gating-demo/internal/mdx-list-demo/internal/load-moreRecommended regression test shape:
tests/footer-preview-navigation.test.mjssite-footer.tsx:
previewModeEnabledInternal section titlePractical note from this task:
site-footer.module.css; otherwise the normal five-column desktop layout can become cramped when the sixth column appearsPractical lesson from this task:
src/lib/is-production.ts was already present on origin/mainorigin/mainSafe check pattern:
git show origin/main:src/lib/is-production.ts
If the file already exists on main:
origin/mainIf you convert navigation call sites from literal href strings to the helper form t("/path"), update repo string-based tests in the same change.
Important files from this task:
tests/canonical-endpoints.test.mjstests/link-and-metadata-integrity.test.mjsTypical failure pattern:
href: "/about-us" or href: "/whitepapers"href: t("/about-us") or href: t("/whitepapers")So when updating navigation to use the preview helper, also update test expectations to the helper-based string form where applicable.
Additional repo-specific pitfall learned from PR follow-up work:
tests/news/mdx-routing-and-preview.test.mjs does source-structure assertions against src/components/sections/news-list-page.tsx, not just runtime behavior.NewsListPage, preserve or consciously update the expected source-visible defaults there.News default heading in the component sourceまずは小さく、失敗しないAXを始めよう簡単サインアップで、14日間の無料トライアルをお試しくださいhttps://app.querypie.com/NewsListPage is: keep the new company-info link behavior, but preserve the existing preview page's source-visible heading/CTA structure unless the task explicitly includes a UX rewrite and matching test updates.For this user's preference, start with the lightest meaningful verification:
npm run typecheck
If CI later fails, the most likely first follow-up is to check the string-based navigation tests above.
A reliable local confirmation command from this task was:
npm run test:ci
If the PR does not show any pull_request checks even after pushing:
gh pr checks and gh run listgh workflow run CI --ref <pr-branch>
Then watch it and inspect failed logs with:
gh run watch <run-id> --exit-status
gh run view <run-id> --log-failed
If the user later asks to replace environment detection after the initial PR is already open:
is-production.ts implementation from corp-web-appt("/path") is used at explicit selected call sites/t paths/t/.../t/... routes are not linked prematurelynpm run typecheck passes