Skip to content

[refactor] migrate feasible app page components from Client to Server for SEO#9

Merged
TechQuery merged 40 commits into
mainfrom
copilot/seo-goodactionhub
Jun 16, 2026
Merged

[refactor] migrate feasible app page components from Client to Server for SEO#9
TechQuery merged 40 commits into
mainfrom
copilot/seo-goodactionhub

Conversation

Copilot AI commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

PR-9 PR-9 PR-9 Powered by Pull Request Badge

This PR addresses SEO for the three list surfaces by moving rendering/filtering state into URL-driven server pages. It also standardizes pagination to URL parameters with a 10-item page size and visible page links at the end of each list, fully unifies translation handling on mobx-i18n, and converts the remaining feasible app page entrypoints from client rendering to server rendering.

  • Scope (issue requirements)

    • Convert list pages to server-rendered components.
    • Switch list search to same-page GET form submissions.
    • Add URL-param pagination in units of 10 with centered page links.
    • Convert additional feasible client-rendered page entrypoints to server rendering when page-level client state is unnecessary.
  • Server-rendered list pages

    • Reworked:
      • app/activities/page.tsx
      • app/restaurants/page.tsx
      • app/tutoring/page.tsx
    • Pages now read searchParams on the server, compute filtered datasets, and slice results by page.
    • SSR language selection now normalizes cookie/query/header inputs and loads language maps through mobx-i18n, including async fallback loading.
  • Additional server-rendered app pages

    • Reworked:
      • app/home/page.tsx
      • app/origin/page.tsx
      • app/recommend/page.tsx
    • /home and /origin now resolve translations on the server instead of keeping the page entrypoints client-only.
    • /recommend now reads keywords from server searchParams, loads recommendation data on the server, and renders recommendation results without a client-page bootstrap.
    • The aggregation search UI was adjusted to accept server-provided translated labels so it can be rendered from server pages.
  • URL-driven search + filtering

    • Replaced client-local search state with GET forms:
      • /activities?keywords=...
      • /restaurants?keywords=...&filter=...
      • /tutoring?keywords=...&tag=...
      • /recommend?keywords=...
    • Filter/tag interactions now generate navigable links so state is crawlable/shareable.
  • Pagination behavior

    • Introduced shared pagination helpers in lib/pagination.ts.
    • Uses the upstream MobX-RESTful-Shadcn pager via install-generated files under components/ui/mobx-restful-shadcn/pager/, while keeping the external component source itself out of Git.
    • All three list pages now use:
      • PAGE_SIZE = 10
      • pageIndex query param
      • centered numbered links + prev/next controls
  • Data access alignment

    • Added fetchActivitiesCatalog() in lib/activities.ts and reused it in activities list/detail, /api/data, and /recommend to keep fetch behavior consistent.
  • Client i18n unification

    • Replaced the remaining i18next / react-i18next client integration with mobx-i18n context-based injection.
    • Migrated locale resources into MobX-i18n TypeScript translation maps and kept async loading for non-default languages.
    • Removed the hook-based translation helper so the infrastructure remains usable from class components.
    • Initializes the shared client i18n context with statically loaded zh-CN as the default language map.
    • Switching language now refreshes the current page so updated cookies are reflected by SSR immediately.
<form action="/tutoring" method="get">
  <input name="keywords" defaultValue={keywords} />
  {selectedTag && <input type="hidden" name="tag" value={selectedTag} />}
  <button type="submit">搜索</button>
</form>

// URL shape: /tutoring?keywords=数学&tag=小学&pageIndex=2

Human changes

  1. [refactor] simplify Source Code with MobX-i18n & MobX-RESTful-Shadcn
  2. [add] Traditional Chinese translation data
  3. [optimize] update i18n data & simplify i18n SSR bootstrap
  4. [optimize] upgrade to amondnet/vercel-action 42 & other latest Upstream packages/actions

Copilot AI linked an issue Jun 6, 2026 that may be closed by this pull request
@TechQuery TechQuery added the feature New feature or request label Jun 6, 2026
Copilot AI changed the title [WIP] Implement SEO improvements for GoodActionHub SEO: server-render list pages, GET-based search, and URL pagination (size=10) Jun 6, 2026
Copilot AI requested a review from TechQuery June 6, 2026 23:58

@TechQuery TechQuery left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

先合并主分支最新代码,再通篇修改以下建议。

Comment thread lib/activities.ts Outdated
Comment thread app/activities/page.tsx Outdated
Comment thread app/activities/page.tsx Outdated
Comment thread app/activities/page.tsx Outdated
Comment thread app/activities/page.tsx Outdated
Comment thread app/restaurants/page.tsx Outdated
Comment thread app/restaurants/page.tsx Outdated
Comment thread app/restaurants/page.tsx Outdated
Comment thread app/restaurants/page.tsx Outdated
Comment thread app/tutoring/page.tsx Outdated
Copilot AI changed the title SEO: server-render list pages, GET-based search, and URL pagination (size=10) SEO: server-render list pages, GET-based search, URL pagination (size=10), and SSR locale fallback Jun 7, 2026
Copilot AI requested a review from TechQuery June 7, 2026 21:25
[add] Traditional Chinese translation data
[optimize] update Upstream packages
@TechQuery TechQuery marked this pull request as ready for review June 8, 2026 00:54
Copilot AI review requested due to automatic review settings June 8, 2026 00:54

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 aims to improve SEO and shareability of the three “list” surfaces by moving search/filter/pagination state into URL-driven server-rendered pages, and by adding SSR language selection/fallback for list-page UI text.

Changes:

  • Reworked /activities, /restaurants, and /tutoring list pages to be server components with GET-based search and URL pagination (page size = 10).
  • Introduced SSR language loading via mobx-i18n + new translation maps for zh-CN, zh-TW, and en-US.
  • Aligned activities data fetching by adding fetchActivitiesCatalog() and reusing it in the API route and activities pages.

Reviewed changes

Copilot reviewed 20 out of 22 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
public/locales/zh-TW/translation.json Adds Traditional Chinese i18next translation namespace data.
public/locales/zh-TW/common.json Adds Traditional Chinese i18next common namespace data.
package.json Updates scripts/deps; introduces shadcn-helper install hook and dependency upgrades.
lib/pagination.ts Adds shared page parsing + visible page calculation helpers.
lib/activities.ts Adds fetchActivitiesCatalog() to centralize activities fetch behavior.
i18n/zh-TW.ts Adds SSR translation map for Traditional Chinese.
i18n/zh-CN.ts Adds SSR translation map for Simplified Chinese.
i18n/en-US.ts Adds SSR translation map for English (US).
i18n/index.ts Adds SSR i18n store + cookie/header/query language loading.
i18n/config.ts Extends client i18next config to support zh-TW and formatting tweaks.
eslint.config.ts Adds React version setting and keeps existing TS-eslint rule override.
components/index.ini Declares a shadcn registry component to be installed (pager).
components.json Adds a custom shadcn registry URL.
app/tutoring/page.tsx Converts tutoring list to SSR with GET search + URL tag selection + pagination.
app/tutoring/[slug]/page.tsx Adds SSR i18n text usage in tutoring detail page.
app/restaurants/page.tsx Converts restaurants list to SSR with GET search + URL filter + pagination.
app/restaurants/[id]/page.tsx Adds SSR i18n text usage in restaurant detail page.
app/api/data/route.ts Uses fetchActivitiesCatalog() for consistent upstream fetch behavior.
app/activities/page.tsx Converts activities list to SSR with GET search + pagination and SSR locale loading.
app/activities/[id]/page.tsx Uses fetchActivitiesCatalog() + SSR i18n text usage in activity detail page.
.gitignore Ignores components/ui/ (shadcn UI components).
Comments suppressed due to low confidence (1)

app/api/data/route.ts:14

  • fetchActivitiesCatalog() now throws on upstream fetch errors, but the API route catches everything and returns HTTP 500. Previously, upstream fetch failures returned 502 (bad gateway), which more accurately signals an upstream dependency issue. Consider preserving 502 for fetch failures so monitoring/clients can distinguish upstream vs server errors.
export async function GET() {
  try {
    const externalData = await fetchActivitiesCatalog();
    const data = externalData.map(transformItem);
    return NextResponse.json(data);
  } catch (err) {
    console.error('Failed to fetch data from external API:', err);
    return NextResponse.json({ error: 'Failed to load data' }, { status: 500 });
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/pagination.ts Outdated
Comment on lines +1 to +4
export function parsePage(rawPage?: string): number {
const parsed = Number.parseInt(rawPage ?? '1', 10);
return Number.isFinite(parsed) && parsed > 0 ? parsed : 1;
}
Comment thread app/tutoring/page.tsx Outdated
Comment thread app/restaurants/page.tsx Outdated
Comment thread app/activities/page.tsx Outdated
Comment thread app/activities/page.tsx Outdated
Comment thread package.json
Comment thread components.json
Comment thread i18n/index.ts Outdated
Comment thread i18n/index.ts

@TechQuery TechQuery left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

完全使用 mobx-i18n 替代 i18next

Copilot AI commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

@copilot 每次让你通篇改是要你搜索类似的模式,你要理解它是个什么概念,而不是单纯查找相似的字符串!

已在 25972e1 按“理解概念而不是只搜字符串”的方式继续收口:把剩余两个带 props 的 observer 组件统一成同一套 FC<Props> 声明风格,并把还漏掉的导入分组顺序一并改齐;npm run testnpm run build、Code Review 和 CodeQL 已通过。

Copilot AI requested a review from TechQuery June 15, 2026 18:48
Co-authored-by: South Drifter <shiy2008@gmail.com>
[optimize] upgrade to amondnet/vercel-action 42
@TechQuery TechQuery changed the title SEO: server-render list pages, GET-based search, URL pagination (size=10), SSR locale fallback, and MobX i18n unification [refactor] migrate List Page components from Client to Server for SEO Jun 15, 2026
@TechQuery TechQuery requested a review from FenjuFu June 15, 2026 21:26
@TechQuery TechQuery added the enhancement Some improvements label Jun 16, 2026
@TechQuery

Copy link
Copy Markdown
Member

@copilot 把所有客户端渲染的页面尽可能改成服务端渲染,实在有困难的就先不改。

Copilot AI commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot 把所有客户端渲染的页面尽可能改成服务端渲染,实在有困难的就先不改。

已在 968a32b 尽量把客户端渲染页面改成服务端渲染:/home/origin/recommend 都已改为服务端页面,交互仅下沉到必要的子组件;npm run testnpm run build、CodeQL 已通过。

Copilot AI changed the title [refactor] migrate List Page components from Client to Server for SEO [refactor] migrate feasible app page components from Client to Server for SEO Jun 16, 2026
Copilot AI requested a review from TechQuery June 16, 2026 02:35

@TechQuery TechQuery left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot 通篇改

Comment thread components/Aggregation.tsx Outdated
Comment on lines +2 to +6
interface AggregationProps {
searchLabel: string;
searchPlaceholder: string;
searchAriaLabel: string;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Record 泛型

Comment thread components/Aggregation.tsx Outdated
Comment on lines 8 to 13
export const Aggregation = ({
searchLabel,
searchPlaceholder,
searchAriaLabel,
}: AggregationProps) => {
return (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
export const Aggregation = ({
searchLabel,
searchPlaceholder,
searchAriaLabel,
}: AggregationProps) => {
return (
export const Aggregation: FC<AggregationProps> = ({
searchLabel,
searchPlaceholder,
searchAriaLabel,
}) => (

Comment thread components/SwitchLanguage.tsx Outdated
<Select.Content className="rounded-lg border border-slate-200 bg-white shadow-lg z-50">
<Select.Viewport className="p-1">
{Object.entries(supportedLngDisplayNames).map(([lng, label]) => (
{Object.entries(LanguageName).map(([lng, label]) => (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
{Object.entries(LanguageName).map(([lng, label]) => (
{Object.entries(LanguageName).map(([language, label]) => (

Copilot AI commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot 通篇改

已在 08feb3b 按这轮“通篇改”继续收口:Aggregation 改成 Record 泛型 + FC<Props> 简洁写法,SwitchLanguage 的语言项遍历也统一成显式 language 命名;npm run testnpm run build 和本轮 Code Review / CodeQL 已通过。

Copilot AI requested a review from TechQuery June 16, 2026 02:47
@TechQuery TechQuery merged commit bc15085 into main Jun 16, 2026
3 checks passed
@TechQuery TechQuery deleted the copilot/seo-goodactionhub branch June 16, 2026 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Some improvements feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

对 GoodActionHub 进行 SEO

3 participants