Skip to content

Convert repository to monorepo layout (apps/web + packages) with Turbo#211

Open
EvanTechDev wants to merge 27 commits intodevfrom
feature/upgrade-project-to-monorepo-with-turborepo
Open

Convert repository to monorepo layout (apps/web + packages) with Turbo#211
EvanTechDev wants to merge 27 commits intodevfrom
feature/upgrade-project-to-monorepo-with-turborepo

Conversation

@EvanTechDev
Copy link
Copy Markdown
Owner

@EvanTechDev EvanTechDev commented Mar 27, 2026

Motivation

  • Restructure the project into a monorepo so the web app and shared code live in distinct workspaces for better reuse and tooling.
  • Centralize shared config (tsconfig/tailwind/postcss), UI components, and i18n assets to simplify maintenance and workspace builds.

Description

  • Introduce a Turborepo workspace: add turbo.json, convert the root package.json to a workspace-aware monorepo config, and add workspace scripts using turbo.
  • Move the Next.js application into apps/web/ and add apps/web/package.json, tsconfig.json, postcss.config.mjs, and tailwind.config.ts that re-export shared configs from packages/config.
  • Create packages/config, packages/i18n, and packages/ui packages and move config files, locale JSON files, i18n runtime, UI components, and the gen-locales script into these packages; update imports and paths accordingly (notably packages/i18n/scripts/gen-locales.mjs and packages/i18n/src/i18n.ts).
  • Update repository files: delete top-level tailwind.config.ts and .env.example, adjust .gitignore to include apps/web/.next/ and the new generated locales path, and update README.md to document the monorepo structure and new bun/turbo commands.

Testing

  • No automated CI tests were executed as part of this change.

Codex Task

由 Sourcery 总结

将当前仓库转换为基于 Turbo 的 monorepo,并将应用和共享包拆分为各自的 workspace。

Build(构建):

  • 将根目录下的 package 切换为启用 workspace 的 monorepo,使用 Turborepo 来编排开发、构建和脚本执行。
  • 新增 app 和 package 两类 workspace 的 package.json 文件,其中包含共享的 config、UI 和 i18n 包,并对外导出配置和脚本。
  • 将 TypeScript、Tailwind 和 PostCSS 的配置集中到一个共享配置包中,并更新 Web 应用以使用这些共享配置。

Documentation(文档):

  • 更新 README,说明新的 monorepo 布局、入口点以及 Web 应用所需的环境变量设置方式。

Chores(日常维护):

  • 将 Next.js 应用迁移到 apps/web,并相应调整路径、导入,以及生成的 locales/i18n 运行时代码位置。
  • 更新仓库的忽略规则,移除在 monorepo 结构中已不再使用的、位于根目录的过时配置和环境变量示例文件。
Original summary in English

Summary by Sourcery

Convert the repository into a Turbo-powered monorepo with separated app and shared package workspaces.

Build:

  • Switch the root package to a workspace-enabled monorepo using Turborepo for dev, build, and script orchestration.
  • Introduce app and package workspace package.json files, including shared config, UI, and i18n packages with exported configs and scripts.
  • Centralize TypeScript, Tailwind, and PostCSS configuration into a shared config package and update the web app to consume them.

Documentation:

  • Update the README to document the new monorepo layout, entry points, and environment variable setup for the web app.

Chores:

  • Relocate the Next.js app to apps/web and adjust paths, imports, and generated locales/i18n runtime locations accordingly.
  • Update repository ignore rules and remove obsolete root-level config and env example files no longer used in the monorepo structure.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
one-calendar Ready Ready Preview, Comment, Open in v0 Mar 28, 2026 11:46am

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 27, 2026

审阅者指南

将现有的单体 Next.js 应用仓库转换为基于 Turborepo 的 monorepo,分别为 Web 应用以及共享的 config、i18n 和 UI 包创建独立的 workspace,并相应配置 Turbo 任务、路径别名和共享配置。

跨 workspace 的 generate:locales 任务时序图

sequenceDiagram
  actor Dev
  participant RootPkg as root_package_json
  participant Turbo as turbo
  participant I18nPkg as @repo/i18n
  participant GenLocales as gen-locales_mjs
  participant FS as file_system

  Dev->>RootPkg: bun run generate:locales
  RootPkg->>Turbo: turbo generate:locales --filter=@repo/i18n
  Turbo->>I18nPkg: run script generate:locales
  I18nPkg->>GenLocales: bun scripts/gen-locales.mjs
  GenLocales->>FS: read src/locales/*.json
  FS-->>GenLocales: locale json contents
  GenLocales->>FS: write src/locales.ts
  GenLocales-->>I18nPkg: log generated locales_ts
  I18nPkg-->>Turbo: task success
  Turbo-->>RootPkg: pipeline success
  RootPkg-->>Dev: generate:locales completed
Loading

文件级变更

变更 详情 文件
将根项目转换为 Turborepo monorepo,并把任务委派给各个 workspace。
  • 将根 package 重命名为 one-calendar-monorepo,并声明 apps/* 和 packages/* 为 workspaces
  • 用基于 turbo 的 dev、build、start 和生成命令替换直接调用 Next.js 的脚本,并通过过滤器仅作用于特定 workspace
  • 添加 turbo 作为 devDependency,并在根目录新增 turbo.json 以配置流水线
package.json
turbo.json
将 Next.js 应用移入 apps/web,并为其创建对应的 workspace package 配置。
  • 创建 apps/web/package.json,将应用原有依赖迁移过来,并使用调用 packages/i18n workspace 中 i18n 生成器的 Next.js 脚本
  • 更新 Web 应用的 tsconfig,使其扩展共享基础配置,并为 UI 和 i18n 包定义路径别名
  • 更新 README 中对公共资源的引用,并文档化 monorepo 结构及新命令
apps/web/package.json
apps/web/tsconfig.json
apps/web/postcss.config.mjs
apps/web/tailwind.config.ts
README.md
将共享的 TypeScript、Tailwind 和 PostCSS 配置抽取到独立的 config 包中。
  • 将之前根目录的 tsconfig.json 移至 packages/config/tsconfig.base.json,并简化为与框架无关的基础配置
  • 新增 packages/config/package.json,对外导出 postcss、tailwind 和 tsconfig 配置供其他 workspace 使用
  • 创建共享的 Tailwind 和 PostCSS 配置入口文件,通过 re-export 的方式供 Web 应用使用
packages/config/package.json
packages/config/tsconfig.base.json
packages/config/tailwind.config.ts
apps/web/postcss.config.mjs
apps/web/tailwind.config.ts
tsconfig.json
将 i18n 逻辑和语言包生成抽取到可复用的 i18n 包中。
  • 将语言包生成脚本移动到 packages/i18n/scripts/gen-locales.mjs,并调整路径,从 src/locales 读取并将结果输出为带相对导入的 src/locales.ts
  • 重构运行时 i18n 逻辑到 packages/i18n/src/i18n.ts 中,并从生成的本地 i18n 模块中导入翻译内容
  • 添加 packages/i18n/package.json,定义 generate:locales 脚本,以便从 Turbo 和 Web 应用中调用
packages/i18n/package.json
packages/i18n/scripts/gen-locales.mjs
packages/i18n/src/i18n.ts
lib/gen-locales.mjs
lib/i18n.ts
引入占位的共享 UI 包,并通过路径别名让 Web 应用从中消费组件。
  • 创建最小化的 packages/ui/package.json,用于共享 UI 组件
  • 在 Web 应用 tsconfig 中配置 paths,使 UI 导入解析到 packages/ui/src
packages/ui/package.json
apps/web/tsconfig.json
更新仓库级文档和 ignore 规则以适配新的目录结构和生成产物。
  • 更新 README 中关于运行应用、环境变量文件位置和 monorepo 结构说明的内容
  • 调整 .gitignore,覆盖新的 Next.js 构建输出路径以及生成的语言包文件位置
  • 删除已废弃的顶层 Tailwind 配置和环境示例文件,这些现在都限定在 Web 应用中
README.md
.gitignore
tailwind.config.ts
.env.example

使用提示与命令

与 Sourcery 交互

  • 触发新审阅: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 从审阅评论生成 GitHub issue: 通过回复某条审阅评论,请求 Sourcery 从该评论创建 issue。你也可以直接回复该评论 @sourcery-ai issue 来创建 issue。
  • 生成 pull request 标题: 在 pull request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 正文任意位置写上 @sourcery-ai summary,即可在指定位置生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审阅者指南: 在 pull request 中评论 @sourcery-ai guide,即可随时(重新)生成审阅者指南。
  • 一次性解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可标记解决所有 Sourcery 评论。适用于你已经处理完所有评论且不希望再看到它们时。
  • 一次性关闭所有 Sourcery 审阅: 在 pull request 中评论 @sourcery-ai dismiss,即可关闭所有现有的 Sourcery 审阅。特别适合想要从头开始新的审阅时——别忘了再评论 @sourcery-ai review 触发新审阅!

自定义你的使用体验

访问你的 控制面板 以:

  • 启用或禁用审阅功能,例如 Sourcery 生成的 pull request 摘要、审阅者指南等。
  • 修改审阅语言。
  • 添加、移除或编辑自定义审阅指令。
  • 调整其他审阅设置。

获取帮助

Original review guide in English

Reviewer's Guide

Convert the existing single Next.js app repository into a Turborepo-based monorepo with separate workspaces for the web app and shared config, i18n, and UI packages, wiring Turbo tasks, path aliases, and shared configs accordingly.

Sequence diagram for generate:locales task across workspaces

sequenceDiagram
  actor Dev
  participant RootPkg as root_package_json
  participant Turbo as turbo
  participant I18nPkg as @repo/i18n
  participant GenLocales as gen-locales_mjs
  participant FS as file_system

  Dev->>RootPkg: bun run generate:locales
  RootPkg->>Turbo: turbo generate:locales --filter=@repo/i18n
  Turbo->>I18nPkg: run script generate:locales
  I18nPkg->>GenLocales: bun scripts/gen-locales.mjs
  GenLocales->>FS: read src/locales/*.json
  FS-->>GenLocales: locale json contents
  GenLocales->>FS: write src/locales.ts
  GenLocales-->>I18nPkg: log generated locales_ts
  I18nPkg-->>Turbo: task success
  Turbo-->>RootPkg: pipeline success
  RootPkg-->>Dev: generate:locales completed
Loading

File-Level Changes

Change Details Files
Convert root project to a Turborepo monorepo and delegate tasks to workspaces.
  • Rename the root package to one-calendar-monorepo and declare apps/* and packages/* as workspaces
  • Replace direct Next.js scripts with turbo-powered dev, build, start, and generation commands filtered to specific workspaces
  • Add turbo as a devDependency and introduce a root turbo.json pipeline configuration
package.json
turbo.json
Move the Next.js app into apps/web and create its workspace package configuration.
  • Create apps/web/package.json with the app’s previous dependencies and Next.js scripts that call the i18n generator in the packages/i18n workspace
  • Update tsconfig for the web app to extend the shared base config and define path aliases for UI and i18n packages
  • Update README references to public assets and document the monorepo structure and new commands
apps/web/package.json
apps/web/tsconfig.json
apps/web/postcss.config.mjs
apps/web/tailwind.config.ts
README.md
Extract shared TypeScript, Tailwind, and PostCSS configuration into a dedicated config package.
  • Move the previous root tsconfig.json into packages/config/tsconfig.base.json and simplify it to a framework-agnostic base config
  • Introduce packages/config/package.json exporting postcss, tailwind, and tsconfig configs for other workspaces
  • Create shared Tailwind and PostCSS config entrypoints used by the web app via re-exports
packages/config/package.json
packages/config/tsconfig.base.json
packages/config/tailwind.config.ts
apps/web/postcss.config.mjs
apps/web/tailwind.config.ts
tsconfig.json
Extract i18n logic and locale generation into a reusable i18n package.
  • Move the locale generation script to packages/i18n/scripts/gen-locales.mjs and adjust paths to read from src/locales and emit src/locales.ts with relative imports
  • Refactor i18n runtime to live in packages/i18n/src/i18n.ts and import translations from the generated local i18n module
  • Add a packages/i18n/package.json with a generate:locales script wired for use from Turbo and the web app
packages/i18n/package.json
packages/i18n/scripts/gen-locales.mjs
packages/i18n/src/i18n.ts
lib/gen-locales.mjs
lib/i18n.ts
Introduce a placeholder shared UI package and wire the web app to consume it via path aliases.
  • Create a minimal packages/ui/package.json for shared UI components
  • Configure the web app tsconfig paths so that UI imports resolve to packages/ui/src
packages/ui/package.json
apps/web/tsconfig.json
Update repository-level docs and ignore rules for the new layout and generated artifacts.
  • Update README instructions for running the app, environment file location, and monorepo layout description
  • Adjust .gitignore to cover the new Next.js build output path and generated locale file location
  • Remove obsolete top-level Tailwind config and environment example files now scoped to the web app
README.md
.gitignore
tailwind.config.ts
.env.example

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - 我发现了 3 个问题,并给出了一些整体性的反馈:

  • 新增的共享 Tailwind 配置文件 packages/config/tailwind.config.ts 目前是一个空对象,这会丢失之前所有的 Tailwind 设置;建议将原来的 tailwind.config.ts 内容迁移到这里,以保持 Web 应用的样式一致性。
  • Locale 生成目前通过两种不同方式接线(根目录脚本使用带 @repo/i18n 的 Turbo,而 apps/web 里的脚本则手动 cdpackages/i18n);建议统一成一种方式(例如始终通过 Turbo 调用 workspace 脚本),这样更清晰也更不容易出错。
给 AI Agent 的提示词
Please address the comments from this code review:

## Overall Comments
- 新增的共享 Tailwind 配置文件 `packages/config/tailwind.config.ts` 目前是一个空对象,这会丢失之前所有的 Tailwind 设置;建议将原来的 `tailwind.config.ts` 内容迁移到这里,以保持 Web 应用的样式一致性。
- Locale 生成目前通过两种不同方式接线(根目录脚本使用带 `@repo/i18n` 的 Turbo,而 `apps/web` 里的脚本则手动 `cd``packages/i18n`);建议统一成一种方式(例如始终通过 Turbo 调用 workspace 脚本),这样更清晰也更不容易出错。

## Individual Comments

### Comment 1
<location path="package.json" line_range="13-14" />
<code_context>
+    "dev": "turbo dev --filter=web",
+    "build": "turbo build",
+    "start": "turbo start --filter=web",
+    "generate:locales": "turbo generate:locales --filter=@repo/i18n",
+    "generate:oauth-metadata": "turbo generate:oauth-metadata --filter=web"
   },
   "devDependencies": {
</code_context>
<issue_to_address>
**issue (bug_risk):** These turbo commands are missing the `run` subcommand and likely won't execute the intended tasks.

The turbo CLI requires `turbo run <task>` for task execution. As written, these scripts will fail because `turbo generate:locales` and `turbo generate:oauth-metadata` won’t match any command. Please update to:

```jsonc
"generate:locales": "turbo run generate:locales --filter=@repo/i18n",
"generate:oauth-metadata": "turbo run generate:oauth-metadata --filter=web"
```

And follow this pattern for any similar scripts you add.
</issue_to_address>

### Comment 2
<location path="apps/web/package.json" line_range="6-12" />
<code_context>
+  "private": true,
+  "packageManager": "bun@1.3.8",
+  "scripts": {
+    "dev": "(cd ../../packages/i18n && bun run generate:locales) && next dev",
+    "build": "(cd ../../packages/i18n && bun run generate:locales) && next build",
+    "start": "next start",
+    "generate:locales": "(cd ../../packages/i18n && bun run generate:locales)",
</code_context>
<issue_to_address>
**suggestion:** The subshell `cd` approach for pre-generating locales is fragile and bypasses the monorepo task graph.

This pattern hardcodes repo layout and shell behavior and sidesteps turbo’s dependency graph and caching. Instead, either:

1. Add a `generate:locales` script in `apps/web` that depends on `@repo/i18n`’s `generate:locales` via turbo’s `pipeline`/`dependsOn`, or
2. Run `turbo run generate:locales --filter=@repo/i18n` from the root and make `dev`/`build` depend on that.

This avoids path/shell brittleness and lets turbo cache and schedule the work correctly.

```suggestion
  "scripts": {
    "dev": "bun run generate:locales && next dev",
    "build": "bun run generate:locales && next build",
    "start": "next start",
    "generate:locales": "turbo run generate:locales --filter=@repo/i18n",
    "generate:oauth-metadata": "bun lib/gen-oauth-metadata.mjs"
  },
```
</issue_to_address>

### Comment 3
<location path="apps/web/tsconfig.json" line_range="13" />
<code_context>
+      "@/*": ["./*"],
+      "@/components/ui/*": ["../../packages/ui/src/*"],
+      "@/lib/i18n": ["../../packages/i18n/src/i18n.ts"],
+      "@/lib/locales": ["../../packages/i18n/src/locales.ts"]
+    }
+  },
</code_context>
<issue_to_address>
**suggestion:** Pointing a path alias directly at the generated locales file can cause editor/typecheck issues before generation runs.

Because `../../packages/i18n/src/locales.ts` is generated, it won’t exist (and TS/IDE will error) until `generate:locales` has run at least once. To avoid that, you could either:

- Point this alias at the i18n package entry (e.g. `@repo/i18n`) instead of the generated file, or
- Point it at a stable barrel file in the i18n package that re-exports from `./locales`, so the barrel is always present.

That way you keep `@/lib/locales` ergonomics without depending directly on a generated artifact.

Suggested implementation:

```
      "@/components/ui/*": ["../../packages/ui/src/*"],
      "@/lib/i18n": ["../../packages/i18n/src/i18n.ts"],
      "@/lib/locales": ["@repo/i18n"]

```

For this to work cleanly, ensure that the `@repo/i18n` package's main entry exports the same `locales` surface that consumers expect from `@/lib/locales`. If it currently does not, add the appropriate re-exports in the i18n package (e.g., export `locales` or equivalent from its entry file).
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得这些 Review 有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的 Review。
Original comment in English

Hey - I've found 3 issues, and left some high level feedback:

  • The new shared Tailwind config in packages/config/tailwind.config.ts is an empty object, which drops all of the previous Tailwind settings; consider porting the original tailwind.config.ts contents here so the web app’s styling remains consistent.
  • Locale generation is wired up in two different ways (root scripts using Turbo with @repo/i18n and apps/web scripts manually cd-ing into packages/i18n); it would be clearer and less error-prone to standardize on a single approach (e.g., always invoking the workspace script via Turbo).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new shared Tailwind config in `packages/config/tailwind.config.ts` is an empty object, which drops all of the previous Tailwind settings; consider porting the original `tailwind.config.ts` contents here so the web app’s styling remains consistent.
- Locale generation is wired up in two different ways (root scripts using Turbo with `@repo/i18n` and `apps/web` scripts manually `cd`-ing into `packages/i18n`); it would be clearer and less error-prone to standardize on a single approach (e.g., always invoking the workspace script via Turbo).

## Individual Comments

### Comment 1
<location path="package.json" line_range="13-14" />
<code_context>
+    "dev": "turbo dev --filter=web",
+    "build": "turbo build",
+    "start": "turbo start --filter=web",
+    "generate:locales": "turbo generate:locales --filter=@repo/i18n",
+    "generate:oauth-metadata": "turbo generate:oauth-metadata --filter=web"
   },
   "devDependencies": {
</code_context>
<issue_to_address>
**issue (bug_risk):** These turbo commands are missing the `run` subcommand and likely won't execute the intended tasks.

The turbo CLI requires `turbo run <task>` for task execution. As written, these scripts will fail because `turbo generate:locales` and `turbo generate:oauth-metadata` won’t match any command. Please update to:

```jsonc
"generate:locales": "turbo run generate:locales --filter=@repo/i18n",
"generate:oauth-metadata": "turbo run generate:oauth-metadata --filter=web"
```

And follow this pattern for any similar scripts you add.
</issue_to_address>

### Comment 2
<location path="apps/web/package.json" line_range="6-12" />
<code_context>
+  "private": true,
+  "packageManager": "bun@1.3.8",
+  "scripts": {
+    "dev": "(cd ../../packages/i18n && bun run generate:locales) && next dev",
+    "build": "(cd ../../packages/i18n && bun run generate:locales) && next build",
+    "start": "next start",
+    "generate:locales": "(cd ../../packages/i18n && bun run generate:locales)",
</code_context>
<issue_to_address>
**suggestion:** The subshell `cd` approach for pre-generating locales is fragile and bypasses the monorepo task graph.

This pattern hardcodes repo layout and shell behavior and sidesteps turbo’s dependency graph and caching. Instead, either:

1. Add a `generate:locales` script in `apps/web` that depends on `@repo/i18n`’s `generate:locales` via turbo’s `pipeline`/`dependsOn`, or
2. Run `turbo run generate:locales --filter=@repo/i18n` from the root and make `dev`/`build` depend on that.

This avoids path/shell brittleness and lets turbo cache and schedule the work correctly.

```suggestion
  "scripts": {
    "dev": "bun run generate:locales && next dev",
    "build": "bun run generate:locales && next build",
    "start": "next start",
    "generate:locales": "turbo run generate:locales --filter=@repo/i18n",
    "generate:oauth-metadata": "bun lib/gen-oauth-metadata.mjs"
  },
```
</issue_to_address>

### Comment 3
<location path="apps/web/tsconfig.json" line_range="13" />
<code_context>
+      "@/*": ["./*"],
+      "@/components/ui/*": ["../../packages/ui/src/*"],
+      "@/lib/i18n": ["../../packages/i18n/src/i18n.ts"],
+      "@/lib/locales": ["../../packages/i18n/src/locales.ts"]
+    }
+  },
</code_context>
<issue_to_address>
**suggestion:** Pointing a path alias directly at the generated locales file can cause editor/typecheck issues before generation runs.

Because `../../packages/i18n/src/locales.ts` is generated, it won’t exist (and TS/IDE will error) until `generate:locales` has run at least once. To avoid that, you could either:

- Point this alias at the i18n package entry (e.g. `@repo/i18n`) instead of the generated file, or
- Point it at a stable barrel file in the i18n package that re-exports from `./locales`, so the barrel is always present.

That way you keep `@/lib/locales` ergonomics without depending directly on a generated artifact.

Suggested implementation:

```
      "@/components/ui/*": ["../../packages/ui/src/*"],
      "@/lib/i18n": ["../../packages/i18n/src/i18n.ts"],
      "@/lib/locales": ["@repo/i18n"]

```

For this to work cleanly, ensure that the `@repo/i18n` package's main entry exports the same `locales` surface that consumers expect from `@/lib/locales`. If it currently does not, add the appropriate re-exports in the i18n package (e.g., export `locales` or equivalent from its entry file).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

package.json Outdated
Comment on lines +13 to +14
"generate:locales": "turbo generate:locales --filter=@repo/i18n",
"generate:oauth-metadata": "turbo generate:oauth-metadata --filter=web"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): 这些 turbo 命令缺少 run 子命令,很可能无法执行预期的任务。

Turbo CLI 在执行任务时需要使用 turbo run <task>。按当前写法,这些脚本会失败,因为 turbo generate:localesturbo generate:oauth-metadata 不会匹配到任何命令。请更新为:

"generate:locales": "turbo run generate:locales --filter=@repo/i18n",
"generate:oauth-metadata": "turbo run generate:oauth-metadata --filter=web"

并在你新增的其他类似脚本中也遵循这一写法。

Original comment in English

issue (bug_risk): These turbo commands are missing the run subcommand and likely won't execute the intended tasks.

The turbo CLI requires turbo run <task> for task execution. As written, these scripts will fail because turbo generate:locales and turbo generate:oauth-metadata won’t match any command. Please update to:

"generate:locales": "turbo run generate:locales --filter=@repo/i18n",
"generate:oauth-metadata": "turbo run generate:oauth-metadata --filter=web"

And follow this pattern for any similar scripts you add.

Comment on lines +6 to +12
"scripts": {
"dev": "(cd ../../packages/i18n && bun run generate:locales) && next dev",
"build": "(cd ../../packages/i18n && bun run generate:locales) && next build",
"start": "next start",
"generate:locales": "(cd ../../packages/i18n && bun run generate:locales)",
"generate:oauth-metadata": "bun lib/gen-oauth-metadata.mjs"
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: 使用子 Shell cd 的方式在运行前生成 locales 比较脆弱,而且绕过了 monorepo 的任务图。

这种模式对仓库目录结构和 Shell 行为进行了硬编码,并且绕开了 turbo 的依赖图和缓存机制。更好的做法是:

  1. apps/web 中添加一个 generate:locales 脚本,通过 turbo 的 pipeline/dependsOn 依赖 @repo/i18ngenerate:locales,或者
  2. 从根目录运行 turbo run generate:locales --filter=@repo/i18n,并让 dev/build 依赖该任务。

这样可以避免路径/ Shell 的脆弱性,并让 turbo 正确地进行缓存和调度。

Suggested change
"scripts": {
"dev": "(cd ../../packages/i18n && bun run generate:locales) && next dev",
"build": "(cd ../../packages/i18n && bun run generate:locales) && next build",
"start": "next start",
"generate:locales": "(cd ../../packages/i18n && bun run generate:locales)",
"generate:oauth-metadata": "bun lib/gen-oauth-metadata.mjs"
},
"scripts": {
"dev": "bun run generate:locales && next dev",
"build": "bun run generate:locales && next build",
"start": "next start",
"generate:locales": "turbo run generate:locales --filter=@repo/i18n",
"generate:oauth-metadata": "bun lib/gen-oauth-metadata.mjs"
},
Original comment in English

suggestion: The subshell cd approach for pre-generating locales is fragile and bypasses the monorepo task graph.

This pattern hardcodes repo layout and shell behavior and sidesteps turbo’s dependency graph and caching. Instead, either:

  1. Add a generate:locales script in apps/web that depends on @repo/i18n’s generate:locales via turbo’s pipeline/dependsOn, or
  2. Run turbo run generate:locales --filter=@repo/i18n from the root and make dev/build depend on that.

This avoids path/shell brittleness and lets turbo cache and schedule the work correctly.

Suggested change
"scripts": {
"dev": "(cd ../../packages/i18n && bun run generate:locales) && next dev",
"build": "(cd ../../packages/i18n && bun run generate:locales) && next build",
"start": "next start",
"generate:locales": "(cd ../../packages/i18n && bun run generate:locales)",
"generate:oauth-metadata": "bun lib/gen-oauth-metadata.mjs"
},
"scripts": {
"dev": "bun run generate:locales && next dev",
"build": "bun run generate:locales && next build",
"start": "next start",
"generate:locales": "turbo run generate:locales --filter=@repo/i18n",
"generate:oauth-metadata": "bun lib/gen-oauth-metadata.mjs"
},

"@/*": ["./*"],
"@/components/ui/*": ["../../packages/ui/src/*"],
"@/lib/i18n": ["../../packages/i18n/src/i18n.ts"],
"@/lib/locales": ["../../packages/i18n/src/locales.ts"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: 将路径别名直接指向生成的 locales 文件,可能会在生成步骤执行之前引发编辑器/类型检查错误。

由于 ../../packages/i18n/src/locales.ts 是生成文件,在至少运行过一次 generate:locales 之前它是不存在的,因此 TS/IDE 会报错。为了避免这个问题,你可以:

  • 将该别名指向 i18n 包的入口(例如 @repo/i18n)而不是生成文件,或者
  • 将其指向 i18n 包中一个稳定存在的 barrel 文件,该文件从 ./locales 中重新导出,这样 barrel 始终存在。

这样既能保留 @/lib/locales 的易用性,又不会直接依赖生成产物。

建议实现方式:

      "@/components/ui/*": ["../../packages/ui/src/*"],
      "@/lib/i18n": ["../../packages/i18n/src/i18n.ts"],
      "@/lib/locales": ["@repo/i18n"]

为了让这一方案工作顺畅,需要确保 @repo/i18n 包的主入口导出与使用方期望从 @/lib/locales 获取的相同 locales 接口。如果当前还没有,请在 i18n 包的入口文件中添加相应的二次导出(例如导出 locales 或等效的对象/函数)。

Original comment in English

suggestion: Pointing a path alias directly at the generated locales file can cause editor/typecheck issues before generation runs.

Because ../../packages/i18n/src/locales.ts is generated, it won’t exist (and TS/IDE will error) until generate:locales has run at least once. To avoid that, you could either:

  • Point this alias at the i18n package entry (e.g. @repo/i18n) instead of the generated file, or
  • Point it at a stable barrel file in the i18n package that re-exports from ./locales, so the barrel is always present.

That way you keep @/lib/locales ergonomics without depending directly on a generated artifact.

Suggested implementation:

      "@/components/ui/*": ["../../packages/ui/src/*"],
      "@/lib/i18n": ["../../packages/i18n/src/i18n.ts"],
      "@/lib/locales": ["@repo/i18n"]

For this to work cleanly, ensure that the @repo/i18n package's main entry exports the same locales surface that consumers expect from @/lib/locales. If it currently does not, add the appropriate re-exports in the i18n package (e.g., export locales or equivalent from its entry file).

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant