Skip to content

[refactor] replace SSR with SSG for all SEO pages - #107

Merged
TechQuery merged 2 commits into
mainfrom
TechQuery/issue106
Aug 2, 2026
Merged

[refactor] replace SSR with SSG for all SEO pages#107
TechQuery merged 2 commits into
mainfrom
TechQuery/issue106

Conversation

@TechQuery

@TechQuery TechQuery commented Aug 2, 2026

Copy link
Copy Markdown
Member

PR-107 PR-107 PR-107 Powered by Pull Request Badge

  1. [refactor] replace SSR with SSG for all SEO pages (resolve 【开源市集】官网动态页面静态化 #106)
  2. [optimize] update Upstream pages

Summary by CodeRabbit

  • 新功能

    • 项目数据现支持展示奖项信息;成员技能信息的整理和显示更加准确。
    • 未指定语言时,界面默认使用简体中文。
  • 性能优化

    • 首页、活动、奖项、项目、图书及志愿者等页面改用静态生成,提升加载速度。
    • 页面内容支持定期自动更新,兼顾访问性能与数据新鲜度。
  • 体验改进

    • 不存在的活动或团队页面将更稳定地显示为未找到页面。

[optimize] update Upstream pages
Copilot AI review requested due to automatic review settings August 2, 2026 19:55
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@TechQuery, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 32 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0a16ab1b-4302-418c-b486-1f5270a75327

📥 Commits

Reviewing files that changed from the base of the PR and between a712a55 and 991fa22.

📒 Files selected for processing (3)
  • pages/hackathon/[id].tsx
  • pages/hackathon/[id]/team/[tid].tsx
  • pages/open-library/book/[id].tsx
📝 Walkthrough

Walkthrough

本次变更将多个 Pages Router 页面从 SSR 迁移到 SSG/ISR,增加阻塞式静态路径工具,并更新 Lark 数据加载流程。同时规范化模型字段和 i18n 默认数据。

Changes

页面静态生成迁移

Layer / File(s) Summary
静态路径工具
pages/api/SSG.ts
新增 skipBuildingAll,返回空路径并使用 blocking fallback。
NGO 年份页面静态路由
pages/NGO/[year]/index.tsx, pages/NGO/[year]/landscape.tsx
年份页面使用 skipBuildingAll。数据通过类型化的 getStaticProps 获取。
内容页面 SSG/ISR
pages/index.tsx, pages/award/index.tsx, pages/issue.tsx, pages/project.tsx, pages/volunteer.tsx, pages/open-library/book/[id].tsx
页面从 getServerSideProps 改为 getStaticProps,并配置 revalidate。部分页面通过 Lark 客户端加载模型数据。
活动及团队详情静态生成
pages/hackathon/[id].tsx, pages/hackathon/[id]/team/[tid].tsx
新增静态路径和静态属性获取。流程注入 Lark 客户端,并保留配置校验及 notFound 返回。

模型字段与国际化默认值

Layer / File(s) Summary
关联字段与技能规范化
models/Hackathon.ts
ProjectModel.extractFields 增加 prize 文本数组。MemberModel.extractFields 规范化并拆分 skills
国际化默认值
models/Translation.ts
createI18nStore 默认语言改为 zh-CN。缺少序列化数据时使用 zhCN

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Next as Next.js
  participant Lark as lark.client
  participant Model as HackathonModel
  participant Page as 页面
  Next->>Lark: 获取 access token
  Lark->>Model: 注入客户端并加载数据
  Model-->>Page: 返回序列化 props
  Page-->>Next: 返回 revalidate 或 notFound
Loading

Possibly related PRs

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了将 SEO 页面从 SSR 改为 SSG 的主要变更。
Linked Issues check ✅ Passed 页面已改用 SSG、ISR 和 blocking 路径策略,支持首次访问生成页面并复用静态结果,符合 Issue #106
Out of Scope Changes check ✅ Passed 模型字段和默认语言变更与相关页面的数据生成及渲染流程相关,未发现明确的无关代码变更。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch TechQuery/issue106

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors multiple Next.js pages router routes from SSR (getServerSideProps) to SSG/ISR (getStaticProps + revalidate, and getStaticPaths with blocking fallback for dynamic routes) to improve SEO performance and reduce server-rendering dependency. It also bumps the Next.js toolchain patch level and updates related dependencies/config.

Changes:

  • Migrated several SEO-facing pages from SSR to SSG/ISR, introducing a shared skipBuildingAll helper for dynamic SSG routes.
  • Updated Next.js from 16.2.11 → 16.2.12 (including patched dependency updates) and refreshed related dependency versions.
  • Adjusted runtime/config behavior (redirect rules, translation store defaults, Lark-backed model extraction tweaks).

Reviewed changes

Copilot reviewed 17 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pnpm-workspace.yaml Updates patched Next.js dependency reference to 16.2.12 patch file.
pnpm-lock.yaml Locks updated dependency graph after Next.js + ecosystem bumps.
patches/next@16.2.12.patch Updates Next.js SWC options patch (decorators + decoratorVersion).
package.json Bumps Next.js + related dev deps; removes sass dependency.
next.config.ts Modifies redirect rules for wiki/recipe/policy routes.
pages/api/SSG.ts Adds skipBuildingAll helper for “blocking” SSG dynamic routes.
pages/index.tsx Switches homepage to getStaticProps with Lark-backed fetching + ISR.
pages/award/index.tsx Switches award page to getStaticProps with Lark-backed fetching.
pages/project.tsx Converts SSR → SSG/ISR for project listing page.
pages/issue.tsx Converts SSR → SSG/ISR for issues listing page.
pages/volunteer.tsx Converts SSR → SSG/ISR for volunteer listing page.
pages/open-library/book/[id].tsx Converts book detail route SSR → dynamic SSG (blocking) + ISR, using Lark client.
pages/NGO/[year]/index.tsx Converts NGO year route to dynamic SSG (blocking).
pages/NGO/[year]/landscape.tsx Converts NGO landscape route to dynamic SSG (blocking).
pages/hackathon/[id].tsx Converts hackathon detail SSR → dynamic SSG (blocking) + ISR, using Lark client.
pages/hackathon/[id]/team/[tid].tsx Converts hackathon team SSR → dynamic SSG (blocking), using Lark client.
models/Translation.ts Changes i18n store defaults (language + fallback map).
models/Hackathon.ts Adjusts extracted fields (project prize, member skills parsing).
.vscode/extensions.json Replaces Thunder Client recommendation with Postman extension.
Suppressed comments (3)

next.config.ts:52

  • The redirect rules no longer match the base routes (/wiki, /recipe, /policy) without a trailing slash, so those URLs will fall through (likely 404) while only /:path* redirects still work. If the intent is to send both the base route and sub-paths to the external wiki, add back an explicit redirect for the base route.
const redirects: NextConfig['redirects'] = async () =>
  ['/wiki', '/recipe', '/policy'].flatMap(route => [
    {
      source: `${route}/:path*`,
      destination: `https://wiki.fcc-cd.dev${route}/:path*`,
      permanent: true,
    },
  ]);

pages/index.tsx:25

  • getStaticProps is doing an external Lark token + API fetch. To keep build-time low/consistent with the new SSG pattern used elsewhere in this PR, wrap this handler with skipBuilding so CI builds don't execute the remote call.
export const getStaticProps: GetStaticProps<HomePageProps> = async () => {
  await lark.getAccessToken();

  const store = new ActivityModel();
  store.client = lark.client;

pages/hackathon/[id]/team/[tid].tsx:63

  • Without revalidate, the generated page will not refresh unless you redeploy. If these team/member/product records can change, add an ISR revalidate interval (matching the other SSG pages in this PR) so updates become visible automatically.
    productStore.getAll({ project: project.name as string }),
  ]);
  return { props: { activity, project, members, products } };
};

Comment thread pages/index.tsx
Comment thread pages/award/index.tsx
Comment on lines +1 to +5
import { GetStaticProps } from 'next';
import { FC } from 'react';

import { Award, AwardModel } from '../../models/Award';
import { lark } from '../api/Lark/core';
Comment thread pages/hackathon/[id]/team/[tid].tsx
Comment thread models/Hackathon.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pages/award/index.tsx (1)

18-20: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

AwardPage 未使用 awardsgetStaticProps 的数据拉取当前无效。

组件渲染空片段,awards 被完全丢弃。这会在每次构建和每次 ISR 重新生成时产生无意义的 Lark 请求。

请确认该页面是否为未完成的占位实现。如果页面尚未开发,建议暂不引入数据获取。如果需要,我可以生成一个使用 React Bootstrap 组件、并用 t() 包裹全部文案的奖项列表渲染实现。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/award/index.tsx` around lines 18 - 20, 当前 AwardPage 完全丢弃 awards,导致
getStaticProps 的数据请求无效。若页面仍是占位实现,请移除 AwardPage 的 awards 属性及对应的 getStaticProps
数据获取;若需保留数据获取,则必须在 AwardPage 中渲染 awards,避免继续无意义请求。
🧹 Nitpick comments (2)
pages/NGO/[year]/landscape.tsx (1)

17-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

建议让 getStaticProps 的 Props 类型与页面组件类型一致。

当前 getStaticProps 声明 Pick<OrganizationModel, 'typeMap'>,而 LandscapePage 声明 OpenCollaborationLandscapeProps。两者由 TypeScript 分别检查,不会互相约束。若 OpenCollaborationLandscapeProps 后续增删字段,编译器不会报错。

直接复用组件的 props 类型可以建立强类型契约。

♻️ 建议修改
-export const getStaticProps: GetStaticProps<
-  Pick<OrganizationModel, 'typeMap'>,
-  { year: string }
-> = async ({ params }) => {
+export const getStaticProps: GetStaticProps<
+  OpenCollaborationLandscapeProps,
+  { year: string }
+> = async ({ params }) => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/NGO/`[year]/landscape.tsx around lines 17 - 19, Update getStaticProps
to use the same OpenCollaborationLandscapeProps type declared by LandscapePage
instead of Pick&lt;OrganizationModel, 'typeMap'&gt;, establishing a shared
compile-time contract between the data loader and page component.
pages/volunteer.tsx (1)

14-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议在 getStaticProps 中使用新的 RepositoryModel 实例,而不是模块级单例。

repositoryStore 是模块级 MobX 单例,在 Node 服务端进程内被所有请求共享。ISR 并发重新生成时,多个 getAllContributors() 调用会写入同一份 observable 状态。当前代码只使用返回值,不读取 store 状态,所以没有正确性问题。

不过 pages/issue.tsxpages/project.tsx 已改为在 getStaticPropsnew RepositoryModel('Open-Source-Bazaar')。保持一致可以避免服务端共享可变状态。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/volunteer.tsx` around lines 14 - 18, Update getStaticProps in
pages/volunteer.tsx to instantiate a new RepositoryModel('Open-Source-Bazaar')
locally and call getAllContributors() on that instance instead of using the
module-level repositoryStore singleton. Preserve the existing returned props and
revalidate behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@models/Hackathon.ts`:
- Around line 185-189: Update the skills transformation in the team/member data
mapping to use optional chaining with an empty-array fallback before calling
map, then split the joined text and filter out empty entries so omitted or empty
skills produce [] without throwing. Remove reliance on the non-null assertion
and preserve normalized skill values for populated input.
- Around line 154-163: Update the ProjectPageProps contract and the team detail
page in pages/hackathon/[id]/team/[tid].tsx to treat prize as an optional string
array, preserving and rendering every prize rather than concatenating a single
value; keep ProjectModel.extractFields consistent with this multi-prize output.

In `@pages/hackathon/`[id].tsx:
- Line 90: Update pages/hackathon/[id].tsx lines 90-90 by wrapping
store.getOne(params!.id) in exception handling and returning { notFound: true,
revalidate: Minute / Second } on failure, matching the existing notFound branch.
In pages/hackathon/[id]/team/[tid].tsx lines 41-50, catch failures from
activityStore.getOne(params!.id) and projectStore.getOne(params!.tid) and return
{ notFound: true }. In pages/open-library/book/[id].tsx lines 26-26, catch
store.getOne failures and return notFound as specified by that file’s existing
pattern.
- Around line 97-104: Update the six model constructions in getStaticProps to
explicitly pass lark.client as each model’s client option: PersonModel,
OrganizationModel, AgendaModel, PrizeModel, TemplateModel, and ProjectModel.
Preserve the existing appId and tableIdMap arguments while ensuring all
associated data requests use the authenticated client.

In `@pages/index.tsx`:
- Around line 21-33: Wrap the getStaticProps implementation in pages/index.tsx
(lines 21-33) with skipBuilding<HomePageProps> and import skipBuilding from
./api/SSG, preserving the existing revalidate value. Apply the same wrapper in
pages/award/index.tsx (lines 7-16) using skipBuilding<{ awards: Award[] }>,
import it from ../api/SSG, and add the default revalidate value expected by
skipBuilding.

In `@pages/NGO/`[year]/index.tsx:
- Around line 25-35: 在 NGO 页面导出函数 getStaticProps 的返回值中加入与其他页面一致的 revalidate
配置,使用项目现有的时间常量,使 blocking fallback 生成的页面能够按周期重新生成;保留现有 props 内容不变。

In `@pages/NGO/`[year]/landscape.tsx:
- Around line 25-28: 为 getStaticProps 在 pages/NGO/[year]/landscape.tsx#L25-L28
的返回值加入 revalidate,并从 web-utility 导入 Minute 与 Second,使用现有周期常量;同时在
pages/hackathon/[id]/team/[tid].tsx#L58-L63 的 getStaticProps 返回值中加入相同的
revalidate 配置,使两类页面按周期重新生成。

---

Outside diff comments:
In `@pages/award/index.tsx`:
- Around line 18-20: 当前 AwardPage 完全丢弃 awards,导致 getStaticProps
的数据请求无效。若页面仍是占位实现,请移除 AwardPage 的 awards 属性及对应的 getStaticProps
数据获取;若需保留数据获取,则必须在 AwardPage 中渲染 awards,避免继续无意义请求。

---

Nitpick comments:
In `@pages/NGO/`[year]/landscape.tsx:
- Around line 17-19: Update getStaticProps to use the same
OpenCollaborationLandscapeProps type declared by LandscapePage instead of
Pick&lt;OrganizationModel, 'typeMap'&gt;, establishing a shared compile-time
contract between the data loader and page component.

In `@pages/volunteer.tsx`:
- Around line 14-18: Update getStaticProps in pages/volunteer.tsx to instantiate
a new RepositoryModel('Open-Source-Bazaar') locally and call
getAllContributors() on that instance instead of using the module-level
repositoryStore singleton. Preserve the existing returned props and revalidate
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: eb5d78cd-f053-44da-b4b8-5be7c663b43e

📥 Commits

Reviewing files that changed from the base of the PR and between d143245 and a712a55.

⛔ Files ignored due to path filters (6)
  • .vscode/extensions.json is excluded by none and included by none
  • next.config.ts is excluded by none and included by none
  • package.json is excluded by none and included by none
  • patches/next@16.2.12.patch is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml and included by none
  • pnpm-workspace.yaml is excluded by none and included by none
📒 Files selected for processing (13)
  • models/Hackathon.ts
  • models/Translation.ts
  • pages/NGO/[year]/index.tsx
  • pages/NGO/[year]/landscape.tsx
  • pages/api/SSG.ts
  • pages/award/index.tsx
  • pages/hackathon/[id].tsx
  • pages/hackathon/[id]/team/[tid].tsx
  • pages/index.tsx
  • pages/issue.tsx
  • pages/open-library/book/[id].tsx
  • pages/project.tsx
  • pages/volunteer.tsx

Comment thread models/Hackathon.ts
Comment on lines +154 to +163
extractFields({
fields: { members, products, prize, ...fields },
...meta
}: TableRecord<Project>) {
return {
...meta,
...fields,
members: (members as TableCellRelation[])?.map(normalizeText),
products: (products as TableCellRelation[])?.map(normalizeText),
prize: (prize as TableCellRelation[])?.map(normalizeText),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 5 '\b(prize|ProjectModel|Project)\b' --glob '*.{ts,tsx}' .

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 22452


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg '(^models/Hackathon\.ts$|^pages/hackathon/\[id\]/team/\[tid\]\.tsx$|^models/(BiDataTable|base).*\.ts$|^node_modules/mobx-lark|package\.json)'

echo
echo "== models/Hackathon.ts relevant sections =="
sed -n '1,220p' models/Hackathon.ts

echo
echo "== pages/hackathon/[id]/team/[tid].tsx relevant sections =="
sed -n '1,260p' 'pages/hackathon/[id]/team/[tid].tsx'

echo
echo "== search for extractFields/type overrides =="
rg -n "extractFields|BiDataTable|queryOptions|ProjectModel|export type Project" --glob '*.{ts,tsx}' models pages

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 19747


统一 prize 的模型输出和页面渲染契约。

models/Hackathon.ts 已将 ProjectModel.extracFieldsprize 输出为 string[],但团队详情页仍按单个奖项拼接和渲染,多奖项会丢失。更新 ProjectPagePropspages/hackathon/[id]/team/[tid].tsx,使奖项列表按 prize?: string[] 处理;若只保留单奖项字段,则移除模型的多奖项转换。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@models/Hackathon.ts` around lines 154 - 163, Update the ProjectPageProps
contract and the team detail page in pages/hackathon/[id]/team/[tid].tsx to
treat prize as an optional string array, preserving and rendering every prize
rather than concatenating a single value; keep ProjectModel.extractFields
consistent with this multi-prize output.

Comment thread models/Hackathon.ts
Comment thread pages/hackathon/[id].tsx Outdated
Comment thread pages/hackathon/[id].tsx Outdated
Comment thread pages/index.tsx
Comment thread pages/NGO/[year]/index.tsx
Comment thread pages/NGO/[year]/landscape.tsx
Copilot AI review requested due to automatic review settings August 2, 2026 20:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 19 changed files in this pull request and generated no new comments.

Suppressed comments (6)

models/Hackathon.ts:189

  • MemberModel.extractFields now non-null asserts skills and calls .map() unconditionally. If the "skills" field is missing/null in a record, this will throw at runtime (previously it safely defaulted to []).
      skills:
        (skills as TableCellText[])!
          .map(normalizeText)
          .join()
          .split(/\s*,\s*/) || [],

pages/award/index.tsx:15

  • After switching to SSG, this page no longer updates unless a full rebuild occurs because revalidate is omitted. If awards are expected to stay fresh (similar to prior SSR behavior), add ISR revalidation like other pages in this PR.
  return { props: { awards } };

models/Translation.ts:34

  • The new defaulting logic can put the store into an inconsistent state when a non-default language is provided without serializedData (e.g. currentLanguage becomes "en-US" while currentMap contains zh-CN strings, and the zh-CN map is stored under the wrong language key). This can lead to incorrect translations if createI18nStore is ever called without languageMap for a non-zh-CN language.
  language = 'zh-CN' as N,
  serializedData?: string,
) => {
  const data = serializedData
    ? (JSON.parse(serializedData, decodeFunctions) as TranslationMap<K>)

pages/hackathon/[id]/team/[tid].tsx:64

  • The ISR toggle uses +new Date(activity.endTime as number) but Activity.endTime is a TableCellValue and may not be numeric. If it's non-numeric, this becomes NaN and the page will keep revalidating forever (and may never disable revalidation after the event ends). Prefer a finite numeric conversion before comparing.
      revalidate: +new Date(activity.endTime as number) < Date.now() ? undefined : Minute / Second,

pages/hackathon/[id].tsx:123

  • The ISR toggle uses +new Date(activity.endTime as number) but Activity.endTime is a TableCellValue and may not be a number. If it's non-numeric, this becomes NaN and the page will keep revalidating forever (and may never disable revalidation after the event ends). Use a numeric conversion with a finite check before comparing.
      revalidate: +new Date(activity.endTime as number) < Date.now() ? undefined : Minute / Second,

next.config.ts:49

  • The redirect for the exact base routes (/wiki, /recipe, /policy) was removed, but there are no local pages for those paths. Visiting /wiki (without a trailing segment) will now 404 instead of redirecting to the external wiki root.
const redirects: NextConfig['redirects'] = async () =>
  ['/wiki', '/recipe', '/policy'].flatMap(route => [
    {
      source: `${route}/:path*`,
      destination: `https://wiki.fcc-cd.dev${route}/:path*`,

@TechQuery
TechQuery merged commit 3e608e3 into main Aug 2, 2026
7 checks passed
@TechQuery
TechQuery deleted the TechQuery/issue106 branch August 2, 2026 20:39
@dosubot

dosubot Bot commented Aug 2, 2026

Copy link
Copy Markdown

📄 Knowledge review

Dosu skipped reviewing this PR because your organization has used its 200 included credits for the month. Your usage will reset on 2026-09-01. To have Dosu review this PR before then, ask your organization admin to upgrade to a pro account.


Leave Feedback Ask Dosu about Open-Source-Bazaar.github.io Add Dosu to your team

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Some improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

【开源市集】官网动态页面静态化

2 participants