test: expand node monorepo test coverage (#361)

* docs: add monorepo support section to Node.js documentation

Addresses user questions about monorepo support by documenting that
Railpack automatically handles npm/pnpm/yarn workspaces and Turborepo
configurations with links to example projects.

* test: improve monorepo example tests to verify workspace functionality

Enhanced integration tests for monorepo examples to properly test that
workspace package linking and dependencies work correctly:

**node-npm-workspaces:**
- Root now imports and uses functions from pkg-a and pkg-b workspace packages
- pkg-a uses its dependency (abbrev) to demonstrate transitive deps work
- pkg-b exports a simple function
- Updated to ES modules for consistency
- Test now verifies all workspace packages load and execute correctly

**node-pnpm-workspaces:**
- Root now imports and uses functions from pkg-a and pkg-b workspace packages
- pkg-a uses its dependency (abbrev) to demonstrate transitive deps work
- pkg-b exports a simple function
- Updated to ES modules for consistency
- Test now verifies all workspace packages load and execute correctly

**node-turborepo:**
- Changed from justBuild to httpCheck since this is a Next.js web server
- Added start script to root package.json to run the web app
- Test now verifies the built app starts and responds to HTTP requests
- This properly tests that the @repo/ui workspace package is built and linked

These changes ensure that monorepo builds are actually testing workspace
functionality, not just that the root package builds in isolation.

Fixes #332

* feat: add yarn workspaces and full-stack monorepo examples

Added two new monorepo examples to complete coverage:

**node-yarn-workspaces:**
- Demonstrates yarn workspaces with workspace package imports
- Uses the packageManager field for corepack
- Similar structure to npm/pnpm workspace examples for consistency
- Tests that workspace packages load and transitive dependencies work

**node-monorepo-fullstack:**
- Real-world example with Express API + frontend + shared package
- Shows how to share code (@monorepo/shared) between API and web packages
- API uses Express and shared utilities/constants
- Frontend demonstrates importing shared code
- Uses HTTP checks to verify API endpoints work correctly
- Demonstrates common full-stack monorepo pattern

Updated documentation to link to the yarn workspaces example and added
a note about the full-stack example for users looking for a more
realistic monorepo setup.

Addresses #332

* fix: format pkg-b package.json properly

Fixed uglified JSON that was created with echo instead of proper editing.

* fix: add yarn.lock and workspace deps to yarn-workspaces example

- Added yarn.lock file required by yarn 4
- Added workspace package dependencies (pkg-a, pkg-b) to root package.json
- Yarn requires lockfile to exist and won't create one in CI mode

* fix: update yarn.lock with correct workspace references

- Added workspace:* aliases to pkg-a and pkg-b entries
- Removed unused transitive dependencies that aren't in package.json
- Yarn requires both the workspace:* and workspace:packages/* forms

* docs: add lockfile guidelines to CLAUDE.md

Never manually update lockfiles - always use the package manager to
generate them properly with correct checksums.

* fix: add workspace deps to pnpm-workspaces package.json

ES module imports require workspace packages to be listed as dependencies
in the root package.json for Node.js to resolve them correctly.

* fix: generate yarn.lock with proper checksums using yarn

Used yarn install via corepack to generate proper yarn.lock with real
checksums instead of manually creating fake ones. Also includes Yarn PnP
files (.pnp.cjs, .pnp.loader.mjs, .yarn/) generated by yarn 4.

* fix: regenerate lockfiles using package managers

Regenerated pnpm-lock.yaml and yarn install-state.gz using the actual
package managers (pnpm and yarn via corepack) instead of manual edits.

- pnpm-lock.yaml: Updated for new workspace dependencies
- .yarn/install-state.gz: Regenerated by yarn install

* fix: remove Yarn PnP files and add .gitignore

Yarn PnP files (.pnp.cjs, .pnp.loader.mjs, .yarn/install-state.gz) should
not be committed as they contain environment-specific paths. They will be
generated during yarn install at build time.

Added .gitignore matching the pattern used in node-yarn-3 example.

* test: update snapshots

* refactor: merge the more realistic monorepo example into existing npm workspaces example

* build: ignore example claude folders

* test: snapshot update

* test: improve unit tests for node workspaces

* docs: deslop AI documentation

* test: improve turborepo example

* test: update snapshots

* test: update unit test for changed monorepo structure

* test: update snapshot

---------

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
Michael Bianco
2026-01-17 08:40:43 -07:00
committed by GitHub
co-authored by Hanzo Dev
parent 907047145f
commit 5568301223
74 changed files with 1676 additions and 1119 deletions
+1
View File
@@ -47,3 +47,4 @@ tmp/
### AI Tooling ###
.claude/settings.local.json
examples/**/.claude
+4
View File
@@ -28,6 +28,10 @@ with support for Node, Python, Go, PHP, and more.
- When configuring Mise settings, prefer environment variables (e.g.
`MISE_PIPX_UVX`) over TOML settings to maintain consistency with existing
patterns in the codebase.
- **Never manually update lockfiles** (yarn.lock, package-lock.json,
pnpm-lock.yaml, etc.). Always use the respective package manager to generate
or update lockfiles. Manual edits can result in invalid checksums and broken
builds.
# Mise Setup
@@ -45,12 +45,13 @@
],
"include": [
"/root/.cache",
"."
".",
"/opt/corepack"
],
"step": "build"
}
],
"startCommand": "node index.js",
"startCommand": "npm run start",
"variables": {
"CI": "true",
"NODE_ENV": "production",
@@ -90,6 +91,7 @@
"MISE_DATA_DIR": "/mise",
"MISE_IDIOMATIC_VERSION_FILE_ENABLE_TOOLS": "python,node,ruby,elixir,go,java,yarn",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_NODE_COREPACK": "true",
"MISE_NODE_VERIFY": "false",
"MISE_PARANOID": "1",
"MISE_SHIMS_DIR": "/mise/shims",
@@ -104,6 +106,14 @@
{
"path": "/app/node_modules/.bin"
},
{
"dest": "package.json",
"src": "package.json"
},
{
"cmd": "sh -c 'npm i -g corepack@latest \u0026\u0026 corepack enable \u0026\u0026 corepack prepare --activate'",
"customName": "npm i -g corepack@latest \u0026\u0026 corepack enable \u0026\u0026 corepack prepare --activate"
},
{
"cmd": "mkdir -p /app/node_modules/.cache"
},
@@ -116,12 +126,16 @@
"src": "package.json"
},
{
"dest": "packages/pkg-a/package.json",
"src": "packages/pkg-a/package.json"
"dest": "packages/api/package.json",
"src": "packages/api/package.json"
},
{
"dest": "packages/pkg-b/package.json",
"src": "packages/pkg-b/package.json"
"dest": "packages/shared/package.json",
"src": "packages/shared/package.json"
},
{
"dest": "packages/web/package.json",
"src": "packages/web/package.json"
},
{
"cmd": "npm ci"
@@ -135,6 +149,7 @@
"name": "install",
"variables": {
"CI": "true",
"COREPACK_HOME": "/opt/corepack",
"NODE_ENV": "production",
"NPM_CONFIG_FUND": "false",
"NPM_CONFIG_PRODUCTION": "false",
@@ -50,7 +50,7 @@
"step": "build"
}
],
"startCommand": "node index.js",
"startCommand": "pnpm run start",
"variables": {
"CI": "true",
"NODE_ENV": "production",
@@ -8,10 +8,6 @@
"directory": "/var/lib/apt/lists",
"type": "locked"
},
"next-apps-docs": {
"directory": "/app/apps/docs/.next/cache",
"type": "shared"
},
"next-apps-web": {
"directory": "/app/apps/web/.next/cache",
"type": "shared"
@@ -59,6 +55,7 @@
"step": "build"
}
],
"startCommand": "npm run start",
"variables": {
"CI": "true",
"NODE_ENV": "production",
@@ -128,10 +125,6 @@
"dest": ".npmrc",
"src": ".npmrc"
},
{
"dest": "apps/docs/package.json",
"src": "apps/docs/package.json"
},
{
"dest": "apps/web/package.json",
"src": "apps/web/package.json"
@@ -156,6 +149,10 @@
"dest": "packages/ui/package.json",
"src": "packages/ui/package.json"
},
{
"dest": "packages/utils/package.json",
"src": "packages/utils/package.json"
},
{
"cmd": "npm ci"
}
@@ -178,7 +175,6 @@
{
"caches": [
"node-modules",
"next-apps-docs",
"next-apps-web"
],
"commands": [
@@ -0,0 +1,195 @@
{
"caches": {
"apt": {
"directory": "/var/cache/apt",
"type": "locked"
},
"apt-lists": {
"directory": "/var/lib/apt/lists",
"type": "locked"
},
"node-modules": {
"directory": "/app/node_modules/.cache",
"type": "shared"
},
"yarn-install": {
"directory": "/app/.yarn/cache",
"type": "shared"
}
},
"deploy": {
"base": {
"step": "packages:apt:runtime"
},
"inputs": [
{
"include": [
"/mise/shims",
"/mise/installs",
"/usr/local/bin/mise",
"/etc/mise/config.toml",
"/root/.local/state/mise"
],
"step": "packages:mise"
},
{
"include": [
"/app/.yarn",
"/root/.yarn"
],
"step": "build"
},
{
"exclude": [
"node_modules",
".yarn"
],
"include": [
"/root/.cache",
".",
"/opt/corepack"
],
"step": "build"
}
],
"startCommand": "yarn run start",
"variables": {
"CI": "true",
"NODE_ENV": "production",
"NPM_CONFIG_FUND": "false",
"NPM_CONFIG_PRODUCTION": "false",
"NPM_CONFIG_UPDATE_NOTIFIER": "false"
}
},
"steps": [
{
"assets": {
"mise.toml": "[mise.toml]"
},
"commands": [
{
"path": "/mise/shims"
},
{
"customName": "create mise config",
"name": "mise.toml",
"path": "/etc/mise/config.toml"
},
{
"cmd": "mise install",
"customName": "install mise packages: node"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-builder:latest"
}
],
"name": "packages:mise",
"variables": {
"MISE_CACHE_DIR": "/mise/cache",
"MISE_CONFIG_DIR": "/mise",
"MISE_DATA_DIR": "/mise",
"MISE_IDIOMATIC_VERSION_FILE_ENABLE_TOOLS": "python,node,ruby,elixir,go,java,yarn",
"MISE_INSTALLS_DIR": "/mise/installs",
"MISE_NODE_COREPACK": "true",
"MISE_NODE_VERIFY": "false",
"MISE_PARANOID": "1",
"MISE_SHIMS_DIR": "/mise/shims",
"MISE_TRUSTED_CONFIG_PATHS": "/app"
}
},
{
"caches": [
"yarn-install"
],
"commands": [
{
"path": "/app/node_modules/.bin"
},
{
"dest": "package.json",
"src": "package.json"
},
{
"cmd": "sh -c 'npm i -g corepack@latest \u0026\u0026 corepack enable \u0026\u0026 corepack prepare --activate'",
"customName": "npm i -g corepack@latest \u0026\u0026 corepack enable \u0026\u0026 corepack prepare --activate"
},
{
"cmd": "mkdir -p /app/node_modules/.cache"
},
{
"dest": "package.json",
"src": "package.json"
},
{
"dest": "packages/pkg-a/package.json",
"src": "packages/pkg-a/package.json"
},
{
"dest": "packages/pkg-b/package.json",
"src": "packages/pkg-b/package.json"
},
{
"dest": "yarn.lock",
"src": "yarn.lock"
},
{
"cmd": "yarn install --check-cache"
}
],
"inputs": [
{
"step": "packages:mise"
}
],
"name": "install",
"variables": {
"CI": "true",
"COREPACK_HOME": "/opt/corepack",
"NODE_ENV": "production",
"NPM_CONFIG_FUND": "false",
"NPM_CONFIG_PRODUCTION": "false",
"NPM_CONFIG_UPDATE_NOTIFIER": "false"
}
},
{
"caches": [
"node-modules"
],
"inputs": [
{
"step": "install"
},
{
"include": [
"."
],
"local": true
}
],
"name": "build",
"secrets": [
"*"
]
},
{
"caches": [
"apt",
"apt-lists"
],
"commands": [
{
"cmd": "sh -c 'apt-get update \u0026\u0026 apt-get install -y libatomic1'",
"customName": "install apt packages: libatomic1"
}
],
"inputs": [
{
"image": "ghcr.io/railwayapp/railpack-runtime:latest"
}
],
"name": "packages:apt:runtime"
}
]
}
+1 -1
View File
@@ -142,7 +142,7 @@ func TestGetNextApps(t *testing.T) {
{
name: "turbo with 2 next apps",
path: "../../../examples/node-turborepo",
want: []string{"apps/docs", "apps/web"},
want: []string{"apps/web"},
},
}
+15 -3
View File
@@ -18,7 +18,7 @@ func TestWorkspace(t *testing.T) {
name: "npm workspaces",
path: "../../../examples/node-npm-workspaces",
hasWorkspaces: true,
numPackages: 2,
numPackages: 3,
},
{
name: "pnpm workspaces",
@@ -43,7 +43,19 @@ func TestWorkspace(t *testing.T) {
require.Equal(t, tt.hasWorkspaces, workspace.HasWorkspaces())
require.Equal(t, tt.numPackages, len(workspace.Packages))
if tt.hasWorkspaces {
if tt.hasWorkspaces && tt.name == "npm workspaces" {
api := workspace.GetPackage("packages/api")
require.NotNil(t, api)
require.Equal(t, "@monorepo/api", api.PackageJson.Name)
shared := workspace.GetPackage("packages/shared")
require.NotNil(t, shared)
require.Equal(t, "@monorepo/shared", shared.PackageJson.Name)
web := workspace.GetPackage("packages/web")
require.NotNil(t, web)
require.Equal(t, "@monorepo/web", web.PackageJson.Name)
} else if tt.hasWorkspaces && tt.name == "pnpm workspaces" {
pkgA := workspace.GetPackage("packages/pkg-a")
require.NotNil(t, pkgA)
require.Equal(t, "pkg-a", pkgA.PackageJson.Name)
@@ -121,7 +133,7 @@ func TestWorkspaceAllPackageJson(t *testing.T) {
{
name: "npm workspaces",
path: "../../../examples/node-npm-workspaces",
numExpected: 3,
numExpected: 4,
},
{
name: "pnpm workspaces",
+22
View File
@@ -118,6 +118,28 @@ install the specified package manager version. When a package manager is
detected via the `engines` field, the specified version constraint will be
used.
### Monorepo Support
Railpack automatically supports monorepo (workspaces) configurations with all major
package managers. No special configuration is required.
**Supported Approaches:**
- **npm, bun, yarn**: Uses the `workspaces` field in `package.json`
- **pnpm**: Uses `pnpm-workspace.yaml` configuration
([example][pnpm-workspaces-example])
When building a monorepo, Railpack will:
- Detect workspace configurations automatically
- Install all workspace dependencies correctly
- Respect workspace dependency links between packages
- Cache workspace node_modules appropriately
If your monorepo requires building a specific workspace package, ensure
your build and start scripts are defined in the root `package.json` or use
a [config file](/architecture/user-config) to specify custom commands.
### Install
Railpack will only include the necessary files to install dependencies in order
-5
View File
@@ -1,5 +0,0 @@
const cowsay = require("cowsay");
console.log(cowsay.say({
text: "Hello from npm workspaces",
}));
File diff suppressed because it is too large Load Diff
+5 -12
View File
@@ -1,20 +1,13 @@
{
"name": "npm-workspaces",
"private": true,
"version": "1.0.0",
"main": "index.js",
"private": true,
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"start": "node packages/api/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"workspaces": [
"packages/pkg-a",
"packages/pkg-b"
"packages/*"
],
"dependencies": {
"cowsay": "^1.6.0"
}
"packageManager": "[email protected]"
}
@@ -0,0 +1,30 @@
import express from "express";
import { APP_NAME, API_VERSION, formatMessage, createResponse } from "@monorepo/shared";
const app = express();
const PORT = process.env.PORT || 3000;
app.use(express.json());
app.get("/", (req, res) => {
console.log(formatMessage("Health check requested"));
res.json(createResponse({
app: APP_NAME,
version: API_VERSION,
message: "API is running"
}));
});
app.get("/api/users", (req, res) => {
console.log(formatMessage("Users list requested"));
res.json(createResponse({
users: [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
]
}));
});
app.listen(PORT, () => {
console.log(formatMessage(`${APP_NAME} API v${API_VERSION} listening on port ${PORT}`));
});
@@ -0,0 +1,10 @@
{
"name": "@monorepo/api",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"dependencies": {
"@monorepo/shared": "*",
"express": "^4.21.2"
}
}
@@ -1 +0,0 @@
console.log("pkg-a");
@@ -1,15 +0,0 @@
{
"name": "pkg-a",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"abbrev": "^3.0.0"
}
}
@@ -1 +0,0 @@
console.log("pkg-b");
@@ -1,13 +0,0 @@
{
"name": "pkg-b",
"version": "1.0.0",
"main": "index.js",
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": ""
}
@@ -0,0 +1,3 @@
export const APP_NAME = "Fullstack Monorepo";
export const API_VERSION = "1.0.0";
export const DEFAULT_PORT = 3000;
@@ -0,0 +1,2 @@
export * from "./constants.js";
export * from "./utils.js";
@@ -0,0 +1,11 @@
{
"name": "@monorepo/shared",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"exports": {
".": "./index.js",
"./constants": "./constants.js",
"./utils": "./utils.js"
}
}
@@ -0,0 +1,11 @@
export function formatMessage(message) {
return `[${new Date().toISOString()}] ${message}`;
}
export function createResponse(data, status = "success") {
return {
status,
data,
timestamp: new Date().toISOString()
};
}
@@ -0,0 +1,9 @@
import { APP_NAME, formatMessage } from "@monorepo/shared";
document.getElementById("app-name").textContent = APP_NAME;
console.log(formatMessage(`${APP_NAME} frontend loaded`));
document.getElementById("content").innerHTML = `
<p>Welcome to the ${APP_NAME} web application!</p>
<p>This demonstrates a full-stack monorepo with shared code.</p>
`;
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fullstack Monorepo</title>
</head>
<body>
<h1 id="app-name"></h1>
<div id="content"></div>
<script type="module" src="./app.js"></script>
</body>
</html>
@@ -0,0 +1,8 @@
{
"name": "@monorepo/web",
"version": "1.0.0",
"type": "module",
"dependencies": {
"@monorepo/shared": "*"
}
}
+12 -1
View File
@@ -1,5 +1,16 @@
[
{
"expectedOutput": "Hello from npm workspaces"
"httpCheck": {
"path": "/",
"expected": 200,
"internalPort": 3000
}
},
{
"httpCheck": {
"path": "/api/users",
"expected": 200,
"internalPort": 3000
}
}
]
+6
View File
@@ -1,2 +1,8 @@
import { greet as greetA } from "pkg-a";
import { greet as greetB } from "pkg-b";
console.log("Node v:", process.version);
console.log("Hello from pnpm workspaces");
console.log(greetA());
console.log(greetB());
+8 -2
View File
@@ -4,10 +4,16 @@
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC"
"license": "ISC",
"dependencies": {
"pkg-a": "workspace:*",
"pkg-b": "workspace:*"
}
}
@@ -0,0 +1,8 @@
import abbrev from "abbrev";
console.log("pkg-a loaded");
export function greet() {
const words = abbrev(["package", "packed"]);
return `pkg-a says: ${Object.keys(words).join(", ")}`;
}
@@ -2,6 +2,7 @@
"name": "pkg-a",
"version": "1.0.0",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
@@ -0,0 +1,5 @@
console.log("pkg-b loaded");
export function greet() {
return "pkg-b says: hello from workspace!";
}
@@ -2,7 +2,7 @@
"name": "pkg-b",
"version": "1.0.0",
"main": "index.js",
"devDependencies": {},
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
+12 -5
View File
@@ -6,22 +6,29 @@ settings:
importers:
.: {}
.:
dependencies:
pkg-a:
specifier: workspace:*
version: link:packages/pkg-a
pkg-b:
specifier: workspace:*
version: link:packages/pkg-b
packages/pkg-a:
dependencies:
abbrev:
specifier: ^3.0.0
version: 3.0.0
version: 3.0.1
packages/pkg-b: {}
packages:
[email protected].0:
resolution: {integrity: sha512-+/kfrslGQ7TNV2ecmQwMJj/B65g5KVq1/L3SGVZ3tCYGqlzFuFCGBZJtMP99wH3NpEUyAjn0zPdPUg0D+DwrOA==}
[email protected].1:
resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==}
engines: {node: ^18.17.0 || >=20.5.0}
snapshots:
[email protected].0: {}
[email protected].1: {}
+8 -1
View File
@@ -1,5 +1,12 @@
[
{
"expectedOutput": ["Node v: v22.2.0", "Hello from pnpm workspaces"]
"expectedOutput": [
"Node v: v22.2.0",
"Hello from pnpm workspaces",
"pkg-a loaded",
"pkg-b loaded",
"pkg-a says:",
"pkg-b says: hello from workspace!"
]
}
]
-84
View File
@@ -1,84 +0,0 @@
# Turborepo starter
This Turborepo starter is maintained by the Turborepo core team.
## Using this example
Run the following command:
```sh
npx create-turbo@latest
```
## What's inside?
This Turborepo includes the following packages/apps:
### Apps and Packages
- `docs`: a [Next.js](https://nextjs.org/) app
- `web`: another [Next.js](https://nextjs.org/) app
- `@repo/ui`: a stub React component library shared by both `web` and `docs` applications
- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`)
- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo
Each package/app is 100% [TypeScript](https://www.typescriptlang.org/).
### Utilities
This Turborepo has some additional tools already setup for you:
- [TypeScript](https://www.typescriptlang.org/) for static type checking
- [ESLint](https://eslint.org/) for code linting
- [Prettier](https://prettier.io) for code formatting
### Build
To build all apps and packages, run the following command:
```
cd my-turborepo
pnpm build
```
### Develop
To develop all apps and packages, run the following command:
```
cd my-turborepo
pnpm dev
```
### Remote Caching
> [!TIP]
> Vercel Remote Cache is free for all plans. Get started today at [vercel.com](https://vercel.com/signup?/signup?utm_source=remote-cache-sdk&utm_campaign=free_remote_cache).
Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines.
By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup?utm_source=turborepo-examples), then enter the following commands:
```
cd my-turborepo
npx turbo login
```
This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview).
Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo:
```
npx turbo link
```
## Useful Links
Learn more about the power of Turborepo:
- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks)
- [Caching](https://turbo.build/repo/docs/core-concepts/caching)
- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching)
- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering)
- [Configuration Options](https://turbo.build/repo/docs/reference/configuration)
- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference)
@@ -1,36 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# env files (can opt-in for commiting if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
@@ -1,36 +0,0 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

@@ -1,50 +0,0 @@
:root {
--background: #ffffff;
--foreground: #171717;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
}
body {
color: var(--foreground);
background: var(--background);
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
a {
color: inherit;
text-decoration: none;
}
.imgDark {
display: none;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
.imgLight {
display: none;
}
.imgDark {
display: unset;
}
}
@@ -1,31 +0,0 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
const geistSans = localFont({
src: "./fonts/GeistVF.woff",
variable: "--font-geist-sans",
});
const geistMono = localFont({
src: "./fonts/GeistMonoVF.woff",
variable: "--font-geist-mono",
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}>
{children}
</body>
</html>
);
}
@@ -1,188 +0,0 @@
.page {
--gray-rgb: 0, 0, 0;
--gray-alpha-200: rgba(var(--gray-rgb), 0.08);
--gray-alpha-100: rgba(var(--gray-rgb), 0.05);
--button-primary-hover: #383838;
--button-secondary-hover: #f2f2f2;
display: grid;
grid-template-rows: 20px 1fr 20px;
align-items: center;
justify-items: center;
min-height: 100svh;
padding: 80px;
gap: 64px;
font-synthesis: none;
}
@media (prefers-color-scheme: dark) {
.page {
--gray-rgb: 255, 255, 255;
--gray-alpha-200: rgba(var(--gray-rgb), 0.145);
--gray-alpha-100: rgba(var(--gray-rgb), 0.06);
--button-primary-hover: #ccc;
--button-secondary-hover: #1a1a1a;
}
}
.main {
display: flex;
flex-direction: column;
gap: 32px;
grid-row-start: 2;
}
.main ol {
font-family: var(--font-geist-mono);
padding-left: 0;
margin: 0;
font-size: 14px;
line-height: 24px;
letter-spacing: -0.01em;
list-style-position: inside;
}
.main li:not(:last-of-type) {
margin-bottom: 8px;
}
.main code {
font-family: inherit;
background: var(--gray-alpha-100);
padding: 2px 4px;
border-radius: 4px;
font-weight: 600;
}
.ctas {
display: flex;
gap: 16px;
}
.ctas a {
appearance: none;
border-radius: 128px;
height: 48px;
padding: 0 20px;
border: none;
font-family: var(--font-geist-sans);
border: 1px solid transparent;
transition: background 0.2s, color 0.2s, border-color 0.2s;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
line-height: 20px;
font-weight: 500;
}
a.primary {
background: var(--foreground);
color: var(--background);
gap: 8px;
}
a.secondary {
border-color: var(--gray-alpha-200);
min-width: 180px;
}
button.secondary {
appearance: none;
border-radius: 128px;
height: 48px;
padding: 0 20px;
border: none;
font-family: var(--font-geist-sans);
border: 1px solid transparent;
transition: background 0.2s, color 0.2s, border-color 0.2s;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
line-height: 20px;
font-weight: 500;
background: transparent;
border-color: var(--gray-alpha-200);
min-width: 180px;
}
.footer {
font-family: var(--font-geist-sans);
grid-row-start: 3;
display: flex;
gap: 24px;
}
.footer a {
display: flex;
align-items: center;
gap: 8px;
}
.footer img {
flex-shrink: 0;
}
/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
a.primary:hover {
background: var(--button-primary-hover);
border-color: transparent;
}
a.secondary:hover {
background: var(--button-secondary-hover);
border-color: transparent;
}
.footer a:hover {
text-decoration: underline;
text-underline-offset: 4px;
}
}
@media (max-width: 600px) {
.page {
padding: 32px;
padding-bottom: 80px;
}
.main {
align-items: center;
}
.main ol {
text-align: center;
}
.ctas {
flex-direction: column;
}
.ctas a {
font-size: 14px;
height: 40px;
padding: 0 16px;
}
a.secondary {
min-width: auto;
}
.footer {
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
}
@media (prefers-color-scheme: dark) {
.logo {
filter: invert();
}
}
@@ -1,102 +0,0 @@
import Image, { type ImageProps } from "next/image";
import { Button } from "@repo/ui/button";
import styles from "./page.module.css";
type Props = Omit<ImageProps, "src"> & {
srcLight: string;
srcDark: string;
};
const ThemeImage = (props: Props) => {
const { srcLight, srcDark, ...rest } = props;
return (
<>
<Image {...rest} src={srcLight} className="imgLight" />
<Image {...rest} src={srcDark} className="imgDark" />
</>
);
};
export default function Home() {
return (
<div className={styles.page}>
<main className={styles.main}>
<ThemeImage
className={styles.logo}
srcLight="turborepo-dark.svg"
srcDark="turborepo-light.svg"
alt="Turborepo logo"
width={180}
height={38}
priority
/>
<ol>
<li>
Get started by editing <code>apps/docs/app/page.tsx</code>
</li>
<li>Save and see your changes instantly.</li>
</ol>
<div className={styles.ctas}>
<a
className={styles.primary}
href="https://vercel.com/new/clone?demo-description=Learn+to+implement+a+monorepo+with+a+two+Next.js+sites+that+has+installed+three+local+packages.&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F4K8ZISWAzJ8X1504ca0zmC%2F0b21a1c6246add355e55816278ef54bc%2FBasic.png&demo-title=Monorepo+with+Turborepo&demo-url=https%3A%2F%2Fexamples-basic-web.vercel.sh%2F&from=templates&project-name=Monorepo+with+Turborepo&repository-name=monorepo-turborepo&repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fturborepo%2Ftree%2Fmain%2Fexamples%2Fbasic&root-directory=apps%2Fdocs&skippable-integrations=1&teamSlug=vercel&utm_source=create-turbo"
target="_blank"
rel="noopener noreferrer"
>
<Image
className={styles.logo}
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
href="https://turbo.build/repo/docs?utm_source"
target="_blank"
rel="noopener noreferrer"
className={styles.secondary}
>
Read our docs
</a>
</div>
<Button appName="docs" className={styles.secondary}>
Open alert
</Button>
</main>
<footer className={styles.footer}>
<a
href="https://vercel.com/templates?search=turborepo&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
</a>
<a
href="https://turbo.build?utm_source=create-turbo"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to turbo.build →
</a>
</footer>
</div>
);
}
@@ -1,4 +0,0 @@
import { nextJsConfig } from "@repo/eslint-config/next-js";
/** @type {import("eslint").Linter.Config} */
export default nextJsConfig;
@@ -1,4 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;
@@ -1,28 +0,0 @@
{
"name": "docs",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
"dev": "next dev --turbopack --port 3001",
"build": "next build",
"start": "next start",
"lint": "next lint --max-warnings 0",
"check-types": "tsc --noEmit"
},
"dependencies": {
"@repo/ui": "*",
"next": "^15.1.6",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@repo/eslint-config": "*",
"@repo/typescript-config": "*",
"@types/node": "^22",
"@types/react": "19.0.8",
"@types/react-dom": "19.0.3",
"eslint": "^9.20.0",
"typescript": "5.7.3"
}
}
@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.5 13.5V6.5V5.41421C14.5 5.149 14.3946 4.89464 14.2071 4.70711L9.79289 0.292893C9.60536 0.105357 9.351 0 9.08579 0H8H3H1.5V1.5V13.5C1.5 14.8807 2.61929 16 4 16H12C13.3807 16 14.5 14.8807 14.5 13.5ZM13 13.5V6.5H9.5H8V5V1.5H3V13.5C3 14.0523 3.44772 14.5 4 14.5H12C12.5523 14.5 13 14.0523 13 13.5ZM9.5 5V2.12132L12.3787 5H9.5ZM5.13 5.00062H4.505V6.25062H5.13H6H6.625V5.00062H6H5.13ZM4.505 8H5.13H11H11.625V9.25H11H5.13H4.505V8ZM5.13 11H4.505V12.25H5.13H11H11.625V11H11H5.13Z" fill="#666666"/>
</svg>

Before

Width:  |  Height:  |  Size: 645 B

@@ -1,10 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_868_525)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.268 14.0934C11.9051 13.4838 13.2303 12.2333 13.9384 10.6469C13.1192 10.7941 12.2138 10.9111 11.2469 10.9925C11.0336 12.2005 10.695 13.2621 10.268 14.0934ZM8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8C0 12.4183 3.58172 16 8 16ZM8.48347 14.4823C8.32384 14.494 8.16262 14.5 8 14.5C7.83738 14.5 7.67616 14.494 7.51654 14.4823C7.5132 14.4791 7.50984 14.4759 7.50647 14.4726C7.2415 14.2165 6.94578 13.7854 6.67032 13.1558C6.41594 12.5744 6.19979 11.8714 6.04101 11.0778C6.67605 11.1088 7.33104 11.125 8 11.125C8.66896 11.125 9.32395 11.1088 9.95899 11.0778C9.80021 11.8714 9.58406 12.5744 9.32968 13.1558C9.05422 13.7854 8.7585 14.2165 8.49353 14.4726C8.49016 14.4759 8.4868 14.4791 8.48347 14.4823ZM11.4187 9.72246C12.5137 9.62096 13.5116 9.47245 14.3724 9.28806C14.4561 8.87172 14.5 8.44099 14.5 8C14.5 7.55901 14.4561 7.12828 14.3724 6.71194C13.5116 6.52755 12.5137 6.37904 11.4187 6.27753C11.4719 6.83232 11.5 7.40867 11.5 8C11.5 8.59133 11.4719 9.16768 11.4187 9.72246ZM10.1525 6.18401C10.2157 6.75982 10.25 7.36805 10.25 8C10.25 8.63195 10.2157 9.24018 10.1525 9.81598C9.46123 9.85455 8.7409 9.875 8 9.875C7.25909 9.875 6.53877 9.85455 5.84749 9.81598C5.7843 9.24018 5.75 8.63195 5.75 8C5.75 7.36805 5.7843 6.75982 5.84749 6.18401C6.53877 6.14545 7.25909 6.125 8 6.125C8.74091 6.125 9.46123 6.14545 10.1525 6.18401ZM11.2469 5.00748C12.2138 5.08891 13.1191 5.20593 13.9384 5.35306C13.2303 3.7667 11.9051 2.51622 10.268 1.90662C10.695 2.73788 11.0336 3.79953 11.2469 5.00748ZM8.48347 1.51771C8.4868 1.52089 8.49016 1.52411 8.49353 1.52737C8.7585 1.78353 9.05422 2.21456 9.32968 2.84417C9.58406 3.42562 9.80021 4.12856 9.95899 4.92219C9.32395 4.89118 8.66896 4.875 8 4.875C7.33104 4.875 6.67605 4.89118 6.04101 4.92219C6.19978 4.12856 6.41594 3.42562 6.67032 2.84417C6.94578 2.21456 7.2415 1.78353 7.50647 1.52737C7.50984 1.52411 7.51319 1.52089 7.51653 1.51771C7.67615 1.50597 7.83738 1.5 8 1.5C8.16262 1.5 8.32384 1.50597 8.48347 1.51771ZM5.73202 1.90663C4.0949 2.51622 2.76975 3.7667 2.06159 5.35306C2.88085 5.20593 3.78617 5.08891 4.75309 5.00748C4.96639 3.79953 5.30497 2.73788 5.73202 1.90663ZM4.58133 6.27753C3.48633 6.37904 2.48837 6.52755 1.62761 6.71194C1.54392 7.12828 1.5 7.55901 1.5 8C1.5 8.44099 1.54392 8.87172 1.62761 9.28806C2.48837 9.47245 3.48633 9.62096 4.58133 9.72246C4.52807 9.16768 4.5 8.59133 4.5 8C4.5 7.40867 4.52807 6.83232 4.58133 6.27753ZM4.75309 10.9925C3.78617 10.9111 2.88085 10.7941 2.06159 10.6469C2.76975 12.2333 4.0949 13.4838 5.73202 14.0934C5.30497 13.2621 4.96639 12.2005 4.75309 10.9925Z" fill="#666666"/>
</g>
<defs>
<clipPath id="clip0_868_525">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,19 +0,0 @@
<svg width="473" height="76" viewBox="0 0 473 76" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M130.998 30.6565V22.3773H91.0977V30.6565H106.16V58.1875H115.935V30.6565H130.998Z" fill="black"/>
<path d="M153.542 58.7362C165.811 58.7362 172.544 52.5018 172.544 42.2275V22.3773H162.768V41.2799C162.768 47.0155 159.776 50.2574 153.542 50.2574C147.307 50.2574 144.315 47.0155 144.315 41.2799V22.3773H134.539V42.2275C134.539 52.5018 141.272 58.7362 153.542 58.7362Z" fill="black"/>
<path d="M187.508 46.3173H197.234L204.914 58.1875H216.136L207.458 45.2699C212.346 43.5243 215.338 39.634 215.338 34.3473C215.338 26.6665 209.603 22.3773 200.874 22.3773H177.732V58.1875H187.508V46.3173ZM187.508 38.5867V30.5568H200.376C203.817 30.5568 205.712 32.053 205.712 34.5967C205.712 36.9907 203.817 38.5867 200.376 38.5867H187.508Z" fill="black"/>
<path d="M219.887 58.1875H245.472C253.452 58.1875 258.041 54.397 258.041 48.0629C258.041 43.8235 255.348 40.9308 252.156 39.634C254.35 38.5867 257.043 36.0929 257.043 32.1528C257.043 25.8187 252.555 22.3773 244.625 22.3773H219.887V58.1875ZM229.263 36.3922V30.3074H243.627C246.32 30.3074 247.817 31.3548 247.817 33.3498C247.817 35.3448 246.32 36.3922 243.627 36.3922H229.263ZM229.263 43.7238H244.525C247.168 43.7238 248.615 45.0205 248.615 46.9657C248.615 48.9108 247.168 50.2075 244.525 50.2075H229.263V43.7238Z" fill="black"/>
<path d="M281.942 21.7788C269.423 21.7788 260.396 29.6092 260.396 40.2824C260.396 50.9557 269.423 58.786 281.942 58.786C294.461 58.786 303.438 50.9557 303.438 40.2824C303.438 29.6092 294.461 21.7788 281.942 21.7788ZM281.942 30.2575C288.525 30.2575 293.463 34.1478 293.463 40.2824C293.463 46.417 288.525 50.3073 281.942 50.3073C275.359 50.3073 270.421 46.417 270.421 40.2824C270.421 34.1478 275.359 30.2575 281.942 30.2575Z" fill="black"/>
<path d="M317.526 46.3173H327.251L334.932 58.1875H346.154L337.476 45.2699C342.364 43.5243 345.356 39.634 345.356 34.3473C345.356 26.6665 339.62 22.3773 330.892 22.3773H307.75V58.1875H317.526V46.3173ZM317.526 38.5867V30.5568H330.394C333.835 30.5568 335.73 32.053 335.73 34.5967C335.73 36.9907 333.835 38.5867 330.394 38.5867H317.526Z" fill="black"/>
<path d="M349.904 22.3773V58.1875H384.717V49.9083H359.48V44.0729H381.874V35.9932H359.48V30.6565H384.717V22.3773H349.904Z" fill="black"/>
<path d="M399.204 46.7662H412.221C420.95 46.7662 426.685 42.5767 426.685 34.5967C426.685 26.5668 420.95 22.3773 412.221 22.3773H389.428V58.1875H399.204V46.7662ZM399.204 38.6365V30.5568H411.673C415.164 30.5568 417.059 32.053 417.059 34.5967C417.059 37.0904 415.164 38.6365 411.673 38.6365H399.204Z" fill="black"/>
<path d="M450.948 21.7788C438.43 21.7788 429.402 29.6092 429.402 40.2824C429.402 50.9557 438.43 58.786 450.948 58.786C463.467 58.786 472.444 50.9557 472.444 40.2824C472.444 29.6092 463.467 21.7788 450.948 21.7788ZM450.948 30.2575C457.532 30.2575 462.469 34.1478 462.469 40.2824C462.469 46.417 457.532 50.3073 450.948 50.3073C444.365 50.3073 439.427 46.417 439.427 40.2824C439.427 34.1478 444.365 30.2575 450.948 30.2575Z" fill="black"/>
<path d="M38.5017 18.0956C27.2499 18.0956 18.0957 27.2498 18.0957 38.5016C18.0957 49.7534 27.2499 58.9076 38.5017 58.9076C49.7535 58.9076 58.9077 49.7534 58.9077 38.5016C58.9077 27.2498 49.7535 18.0956 38.5017 18.0956ZM38.5017 49.0618C32.6687 49.0618 27.9415 44.3346 27.9415 38.5016C27.9415 32.6686 32.6687 27.9414 38.5017 27.9414C44.3347 27.9414 49.0619 32.6686 49.0619 38.5016C49.0619 44.3346 44.3347 49.0618 38.5017 49.0618Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.2115 14.744V7.125C56.7719 8.0104 69.9275 21.7208 69.9275 38.5016C69.9275 55.2824 56.7719 68.989 40.2115 69.8782V62.2592C52.5539 61.3776 62.3275 51.0644 62.3275 38.5016C62.3275 25.9388 52.5539 15.6256 40.2115 14.744ZM20.5048 54.0815C17.233 50.3043 15.124 45.4935 14.7478 40.2115H7.125C7.5202 47.6025 10.4766 54.3095 15.1088 59.4737L20.501 54.0815H20.5048ZM36.7916 69.8782V62.2592C31.5058 61.883 26.695 59.7778 22.9178 56.5022L17.5256 61.8944C22.6936 66.5304 29.4006 69.483 36.7878 69.8782H36.7916Z" fill="url(#paint0_linear_2028_278)"/>
<defs>
<linearGradient id="paint0_linear_2028_278" x1="41.443" y1="11.5372" x2="10.5567" y2="42.4236" gradientUnits="userSpaceOnUse">
<stop stop-color="#0096FF"/>
<stop offset="1" stop-color="#FF1E56"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

@@ -1,19 +0,0 @@
<svg width="473" height="76" viewBox="0 0 473 76" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M130.998 30.6566V22.3773H91.0977V30.6566H106.16V58.1876H115.935V30.6566H130.998Z" fill="white"/>
<path d="M153.542 58.7362C165.811 58.7362 172.544 52.5018 172.544 42.2276V22.3773H162.768V41.2799C162.768 47.0156 159.776 50.2574 153.542 50.2574C147.307 50.2574 144.315 47.0156 144.315 41.2799V22.3773H134.539V42.2276C134.539 52.5018 141.272 58.7362 153.542 58.7362Z" fill="white"/>
<path d="M187.508 46.3173H197.234L204.914 58.1876H216.136L207.458 45.2699C212.346 43.5243 215.338 39.6341 215.338 34.3473C215.338 26.6666 209.603 22.3773 200.874 22.3773H177.732V58.1876H187.508V46.3173ZM187.508 38.5867V30.5568H200.376C203.817 30.5568 205.712 32.0531 205.712 34.5967C205.712 36.9907 203.817 38.5867 200.376 38.5867H187.508Z" fill="white"/>
<path d="M219.887 58.1876H245.472C253.452 58.1876 258.041 54.3971 258.041 48.0629C258.041 43.8236 255.348 40.9308 252.156 39.6341C254.35 38.5867 257.043 36.0929 257.043 32.1528C257.043 25.8187 252.555 22.3773 244.625 22.3773H219.887V58.1876ZM229.263 36.3922V30.3074H243.627C246.32 30.3074 247.817 31.3548 247.817 33.3498C247.817 35.3448 246.32 36.3922 243.627 36.3922H229.263ZM229.263 43.7238H244.525C247.168 43.7238 248.615 45.0206 248.615 46.9657C248.615 48.9108 247.168 50.2076 244.525 50.2076H229.263V43.7238Z" fill="white"/>
<path d="M281.942 21.7788C269.423 21.7788 260.396 29.6092 260.396 40.2824C260.396 50.9557 269.423 58.7861 281.942 58.7861C294.461 58.7861 303.438 50.9557 303.438 40.2824C303.438 29.6092 294.461 21.7788 281.942 21.7788ZM281.942 30.2576C288.525 30.2576 293.463 34.1478 293.463 40.2824C293.463 46.4171 288.525 50.3073 281.942 50.3073C275.359 50.3073 270.421 46.4171 270.421 40.2824C270.421 34.1478 275.359 30.2576 281.942 30.2576Z" fill="white"/>
<path d="M317.526 46.3173H327.251L334.932 58.1876H346.154L337.476 45.2699C342.364 43.5243 345.356 39.6341 345.356 34.3473C345.356 26.6666 339.62 22.3773 330.892 22.3773H307.75V58.1876H317.526V46.3173ZM317.526 38.5867V30.5568H330.394C333.835 30.5568 335.73 32.0531 335.73 34.5967C335.73 36.9907 333.835 38.5867 330.394 38.5867H317.526Z" fill="white"/>
<path d="M349.904 22.3773V58.1876H384.717V49.9083H359.48V44.0729H381.874V35.9932H359.48V30.6566H384.717V22.3773H349.904Z" fill="white"/>
<path d="M399.204 46.7662H412.221C420.95 46.7662 426.685 42.5767 426.685 34.5967C426.685 26.5668 420.95 22.3773 412.221 22.3773H389.428V58.1876H399.204V46.7662ZM399.204 38.6366V30.5568H411.673C415.164 30.5568 417.059 32.0531 417.059 34.5967C417.059 37.0904 415.164 38.6366 411.673 38.6366H399.204Z" fill="white"/>
<path d="M450.948 21.7788C438.43 21.7788 429.402 29.6092 429.402 40.2824C429.402 50.9557 438.43 58.7861 450.948 58.7861C463.467 58.7861 472.444 50.9557 472.444 40.2824C472.444 29.6092 463.467 21.7788 450.948 21.7788ZM450.948 30.2576C457.532 30.2576 462.469 34.1478 462.469 40.2824C462.469 46.4171 457.532 50.3073 450.948 50.3073C444.365 50.3073 439.427 46.4171 439.427 40.2824C439.427 34.1478 444.365 30.2576 450.948 30.2576Z" fill="white"/>
<path d="M38.5017 18.0956C27.2499 18.0956 18.0957 27.2498 18.0957 38.5016C18.0957 49.7534 27.2499 58.9076 38.5017 58.9076C49.7535 58.9076 58.9077 49.7534 58.9077 38.5016C58.9077 27.2498 49.7535 18.0956 38.5017 18.0956ZM38.5017 49.0618C32.6687 49.0618 27.9415 44.3346 27.9415 38.5016C27.9415 32.6686 32.6687 27.9414 38.5017 27.9414C44.3347 27.9414 49.0619 32.6686 49.0619 38.5016C49.0619 44.3346 44.3347 49.0618 38.5017 49.0618Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.2115 14.744V7.125C56.7719 8.0104 69.9275 21.7208 69.9275 38.5016C69.9275 55.2824 56.7719 68.989 40.2115 69.8782V62.2592C52.5539 61.3776 62.3275 51.0644 62.3275 38.5016C62.3275 25.9388 52.5539 15.6256 40.2115 14.744ZM20.5048 54.0815C17.233 50.3043 15.124 45.4935 14.7478 40.2115H7.125C7.5202 47.6025 10.4766 54.3095 15.1088 59.4737L20.501 54.0815H20.5048ZM36.7916 69.8782V62.2592C31.5058 61.883 26.695 59.7778 22.9178 56.5022L17.5256 61.8944C22.6936 66.5304 29.4006 69.483 36.7878 69.8782H36.7916Z" fill="url(#paint0_linear_2028_477)"/>
<defs>
<linearGradient id="paint0_linear_2028_477" x1="41.443" y1="11.5372" x2="10.5567" y2="42.4236" gradientUnits="userSpaceOnUse">
<stop stop-color="#0096FF"/>
<stop offset="1" stop-color="#FF1E56"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

@@ -1,10 +0,0 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_977_547)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5 3L18.5 17H2.5L10.5 3Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_977_547">
<rect width="16" height="16" fill="white" transform="translate(2.5 2)"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 367 B

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5H14.5V12.5C14.5 13.0523 14.0523 13.5 13.5 13.5H2.5C1.94772 13.5 1.5 13.0523 1.5 12.5V2.5ZM0 1H1.5H14.5H16V2.5V12.5C16 13.8807 14.8807 15 13.5 15H2.5C1.11929 15 0 13.8807 0 12.5V2.5V1ZM3.75 5.5C4.16421 5.5 4.5 5.16421 4.5 4.75C4.5 4.33579 4.16421 4 3.75 4C3.33579 4 3 4.33579 3 4.75C3 5.16421 3.33579 5.5 3.75 5.5ZM7 4.75C7 5.16421 6.66421 5.5 6.25 5.5C5.83579 5.5 5.5 5.16421 5.5 4.75C5.5 4.33579 5.83579 4 6.25 4C6.66421 4 7 4.33579 7 4.75ZM8.75 5.5C9.16421 5.5 9.5 5.16421 9.5 4.75C9.5 4.33579 9.16421 4 8.75 4C8.33579 4 8 4.33579 8 4.75C8 5.16421 8.33579 5.5 8.75 5.5Z" fill="#666666"/>
</svg>

Before

Width:  |  Height:  |  Size: 750 B

@@ -1,20 +0,0 @@
{
"extends": "@repo/typescript-config/nextjs.json",
"compilerOptions": {
"plugins": [
{
"name": "next"
}
]
},
"include": [
"**/*.ts",
"**/*.tsx",
"next-env.d.ts",
"next.config.js",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
@@ -0,0 +1,10 @@
import { APP_NAME, API_VERSION, formatHealthCheck } from "@repo/utils";
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({
app: APP_NAME,
version: API_VERSION,
...formatHealthCheck("ok"),
});
}
@@ -12,6 +12,7 @@
},
"dependencies": {
"@repo/ui": "*",
"@repo/utils": "*",
"next": "^15.1.6",
"react": "^19.0.0",
"react-dom": "^19.0.0"
+27 -4
View File
@@ -20,6 +20,7 @@
},
"apps/docs": {
"version": "0.1.0",
"extraneous": true,
"dependencies": {
"@repo/ui": "*",
"next": "^15.1.6",
@@ -40,6 +41,7 @@
"version": "0.1.0",
"dependencies": {
"@repo/ui": "*",
"@repo/utils": "*",
"next": "^15.1.6",
"react": "^19.0.0",
"react-dom": "^19.0.0"
@@ -942,6 +944,10 @@
"resolved": "packages/ui",
"link": true
},
"node_modules/@repo/utils": {
"resolved": "packages/utils",
"link": true
},
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
@@ -2167,6 +2173,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/date-fns": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
@@ -2319,10 +2335,6 @@
"node": ">=8"
}
},
"node_modules/docs": {
"resolved": "apps/docs",
"link": true
},
"node_modules/doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@@ -7012,6 +7024,17 @@
"eslint": "^9.20.0",
"typescript": "5.7.3"
}
},
"packages/utils": {
"name": "@repo/utils",
"version": "0.0.0",
"dependencies": {
"date-fns": "^4.1.0"
},
"devDependencies": {
"@repo/typescript-config": "*",
"typescript": "^5.3.3"
}
}
}
}
+1
View File
@@ -4,6 +4,7 @@
"scripts": {
"build": "turbo build",
"dev": "turbo dev",
"start": "cd apps/web && npm start",
"lint": "turbo lint",
"format": "prettier --write \"**/*.{ts,tsx,md}\""
},
@@ -0,0 +1,15 @@
{
"name": "@repo/utils",
"version": "0.0.0",
"private": true,
"exports": {
".": "./src/index.ts"
},
"dependencies": {
"date-fns": "^4.1.0"
},
"devDependencies": {
"@repo/typescript-config": "*",
"typescript": "^5.3.3"
}
}
@@ -0,0 +1,2 @@
export const APP_NAME = "Turborepo Example";
export const API_VERSION = "1.0.0";
@@ -0,0 +1,12 @@
import { format } from "date-fns";
export function getCurrentTimestamp(): string {
return format(new Date(), "yyyy-MM-dd HH:mm:ss");
}
export function formatHealthCheck(status: string): object {
return {
status,
timestamp: getCurrentTimestamp(),
};
}
@@ -0,0 +1,2 @@
export * from "./constants";
export * from "./helpers";
@@ -0,0 +1,8 @@
{
"extends": "@repo/typescript-config/base.json",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
+17 -1
View File
@@ -1,5 +1,21 @@
[
{
"justBuild": true
"httpCheck": {
"path": "/",
"expected": 200,
"internalPort": 3000
}
},
{
"httpCheck": {
"path": "/api/health",
"expected": 200,
"internalPort": 3000,
"expectedOutput": [
"Turborepo Example",
"1.0.0",
"ok"
]
}
}
]
+9
View File
@@ -0,0 +1,9 @@
/.yarn/*
!/.yarn/releases
!/.yarn/plugins
!/.yarn/sdks
# Swap the comments on the following lines if you don't wish to use zero-installs
# Documentation here: https://yarnpkg.com/features/zero-installs
!/.yarn/cache
/.pnp.*
+10
View File
@@ -0,0 +1,10 @@
import cowsay from "cowsay";
import { greet as greetA } from "pkg-a";
import { greet as greetB } from "pkg-b";
console.log(cowsay.say({
text: "Hello from yarn workspaces",
}));
console.log(greetA());
console.log(greetB());
@@ -0,0 +1,18 @@
{
"name": "yarn-workspaces",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"start": "node index.js"
},
"workspaces": [
"packages/*"
],
"dependencies": {
"cowsay": "^1.6.0",
"pkg-a": "workspace:*",
"pkg-b": "workspace:*"
},
"packageManager": "[email protected]"
}
@@ -0,0 +1,8 @@
import abbrev from "abbrev";
console.log("pkg-a loaded");
export function greet() {
const words = abbrev(["yarn", "yarned"]);
return `pkg-a says: ${Object.keys(words).join(", ")}`;
}
@@ -0,0 +1,9 @@
{
"name": "pkg-a",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"dependencies": {
"abbrev": "^3.0.0"
}
}
@@ -0,0 +1,5 @@
console.log("pkg-b loaded");
export function greet() {
return "pkg-b says: hello from yarn workspace!";
}
@@ -0,0 +1,6 @@
{
"name": "pkg-b",
"version": "1.0.0",
"type": "module",
"main": "index.js"
}
+11
View File
@@ -0,0 +1,11 @@
[
{
"expectedOutput": [
"Hello from yarn workspaces",
"pkg-a loaded",
"pkg-b loaded",
"pkg-a says:",
"pkg-b says: hello from yarn workspace!"
]
}
]
+323
View File
@@ -0,0 +1,323 @@
# This file is generated by running "yarn install" inside your project.
# Manual changes might be lost - proceed with caution!
__metadata:
version: 8
cacheKey: 10c0
"abbrev@npm:^3.0.0":
version: 3.0.1
resolution: "abbrev@npm:3.0.1"
checksum: 10c0/21ba8f574ea57a3106d6d35623f2c4a9111d9ee3e9a5be47baed46ec2457d2eac46e07a5c4a60186f88cb98abbe3e24f2d4cca70bc2b12f1692523e2209a9ccf
languageName: node
linkType: hard
"ansi-regex@npm:^3.0.0":
version: 3.0.1
resolution: "ansi-regex@npm:3.0.1"
checksum: 10c0/d108a7498b8568caf4a46eea4f1784ab4e0dfb2e3f3938c697dee21443d622d765c958f2b7e2b9f6b9e55e2e2af0584eaa9915d51782b89a841c28e744e7a167
languageName: node
linkType: hard
"ansi-regex@npm:^5.0.1":
version: 5.0.1
resolution: "ansi-regex@npm:5.0.1"
checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737
languageName: node
linkType: hard
"ansi-styles@npm:^4.0.0":
version: 4.3.0
resolution: "ansi-styles@npm:4.3.0"
dependencies:
color-convert: "npm:^2.0.1"
checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041
languageName: node
linkType: hard
"camelcase@npm:^5.0.0":
version: 5.3.1
resolution: "camelcase@npm:5.3.1"
checksum: 10c0/92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23
languageName: node
linkType: hard
"cliui@npm:^6.0.0":
version: 6.0.0
resolution: "cliui@npm:6.0.0"
dependencies:
string-width: "npm:^4.2.0"
strip-ansi: "npm:^6.0.0"
wrap-ansi: "npm:^6.2.0"
checksum: 10c0/35229b1bb48647e882104cac374c9a18e34bbf0bace0e2cf03000326b6ca3050d6b59545d91e17bfe3705f4a0e2988787aa5cde6331bf5cbbf0164732cef6492
languageName: node
linkType: hard
"color-convert@npm:^2.0.1":
version: 2.0.1
resolution: "color-convert@npm:2.0.1"
dependencies:
color-name: "npm:~1.1.4"
checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7
languageName: node
linkType: hard
"color-name@npm:~1.1.4":
version: 1.1.4
resolution: "color-name@npm:1.1.4"
checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95
languageName: node
linkType: hard
"cowsay@npm:^1.6.0":
version: 1.6.0
resolution: "cowsay@npm:1.6.0"
dependencies:
get-stdin: "npm:8.0.0"
string-width: "npm:~2.1.1"
strip-final-newline: "npm:2.0.0"
yargs: "npm:15.4.1"
bin:
cowsay: cli.js
cowthink: cli.js
checksum: 10c0/6233b0c64e71c3f64ce33a358de9e95649479df25f1b5abf605d1252e155dd44de743e66a545c810c20e1da754b4b7bfea22e401dccc27579748416d8ce6c055
languageName: node
linkType: hard
"decamelize@npm:^1.2.0":
version: 1.2.0
resolution: "decamelize@npm:1.2.0"
checksum: 10c0/85c39fe8fbf0482d4a1e224ef0119db5c1897f8503bcef8b826adff7a1b11414972f6fef2d7dec2ee0b4be3863cf64ac1439137ae9e6af23a3d8dcbe26a5b4b2
languageName: node
linkType: hard
"emoji-regex@npm:^8.0.0":
version: 8.0.0
resolution: "emoji-regex@npm:8.0.0"
checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010
languageName: node
linkType: hard
"find-up@npm:^4.1.0":
version: 4.1.0
resolution: "find-up@npm:4.1.0"
dependencies:
locate-path: "npm:^5.0.0"
path-exists: "npm:^4.0.0"
checksum: 10c0/0406ee89ebeefa2d507feb07ec366bebd8a6167ae74aa4e34fb4c4abd06cf782a3ce26ae4194d70706f72182841733f00551c209fe575cb00bd92104056e78c1
languageName: node
linkType: hard
"get-caller-file@npm:^2.0.1":
version: 2.0.5
resolution: "get-caller-file@npm:2.0.5"
checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde
languageName: node
linkType: hard
"get-stdin@npm:8.0.0":
version: 8.0.0
resolution: "get-stdin@npm:8.0.0"
checksum: 10c0/b71b72b83928221052f713b3b6247ebf1ceaeb4ef76937778557537fd51ad3f586c9e6a7476865022d9394b39b74eed1dc7514052fa74d80625276253571b76f
languageName: node
linkType: hard
"is-fullwidth-code-point@npm:^2.0.0":
version: 2.0.0
resolution: "is-fullwidth-code-point@npm:2.0.0"
checksum: 10c0/e58f3e4a601fc0500d8b2677e26e9fe0cd450980e66adb29d85b6addf7969731e38f8e43ed2ec868a09c101a55ac3d8b78902209269f38c5286bc98f5bc1b4d9
languageName: node
linkType: hard
"is-fullwidth-code-point@npm:^3.0.0":
version: 3.0.0
resolution: "is-fullwidth-code-point@npm:3.0.0"
checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc
languageName: node
linkType: hard
"locate-path@npm:^5.0.0":
version: 5.0.0
resolution: "locate-path@npm:5.0.0"
dependencies:
p-locate: "npm:^4.1.0"
checksum: 10c0/33a1c5247e87e022f9713e6213a744557a3e9ec32c5d0b5efb10aa3a38177615bf90221a5592674857039c1a0fd2063b82f285702d37b792d973e9e72ace6c59
languageName: node
linkType: hard
"p-limit@npm:^2.2.0":
version: 2.3.0
resolution: "p-limit@npm:2.3.0"
dependencies:
p-try: "npm:^2.0.0"
checksum: 10c0/8da01ac53efe6a627080fafc127c873da40c18d87b3f5d5492d465bb85ec7207e153948df6b9cbaeb130be70152f874229b8242ee2be84c0794082510af97f12
languageName: node
linkType: hard
"p-locate@npm:^4.1.0":
version: 4.1.0
resolution: "p-locate@npm:4.1.0"
dependencies:
p-limit: "npm:^2.2.0"
checksum: 10c0/1b476ad69ad7f6059744f343b26d51ce091508935c1dbb80c4e0a2f397ffce0ca3a1f9f5cd3c7ce19d7929a09719d5c65fe70d8ee289c3f267cd36f2881813e9
languageName: node
linkType: hard
"p-try@npm:^2.0.0":
version: 2.2.0
resolution: "p-try@npm:2.2.0"
checksum: 10c0/c36c19907734c904b16994e6535b02c36c2224d433e01a2f1ab777237f4d86e6289fd5fd464850491e940379d4606ed850c03e0f9ab600b0ebddb511312e177f
languageName: node
linkType: hard
"path-exists@npm:^4.0.0":
version: 4.0.0
resolution: "path-exists@npm:4.0.0"
checksum: 10c0/8c0bd3f5238188197dc78dced15207a4716c51cc4e3624c44fc97acf69558f5ebb9a2afff486fe1b4ee148e0c133e96c5e11a9aa5c48a3006e3467da070e5e1b
languageName: node
linkType: hard
"pkg-a@workspace:*, pkg-a@workspace:packages/pkg-a":
version: 0.0.0-use.local
resolution: "pkg-a@workspace:packages/pkg-a"
dependencies:
abbrev: "npm:^3.0.0"
languageName: unknown
linkType: soft
"pkg-b@workspace:*, pkg-b@workspace:packages/pkg-b":
version: 0.0.0-use.local
resolution: "pkg-b@workspace:packages/pkg-b"
languageName: unknown
linkType: soft
"require-directory@npm:^2.1.1":
version: 2.1.1
resolution: "require-directory@npm:2.1.1"
checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99
languageName: node
linkType: hard
"require-main-filename@npm:^2.0.0":
version: 2.0.0
resolution: "require-main-filename@npm:2.0.0"
checksum: 10c0/db91467d9ead311b4111cbd73a4e67fa7820daed2989a32f7023785a2659008c6d119752d9c4ac011ae07e537eb86523adff99804c5fdb39cd3a017f9b401bb6
languageName: node
linkType: hard
"set-blocking@npm:^2.0.0":
version: 2.0.0
resolution: "set-blocking@npm:2.0.0"
checksum: 10c0/9f8c1b2d800800d0b589de1477c753492de5c1548d4ade52f57f1d1f5e04af5481554d75ce5e5c43d4004b80a3eb714398d6907027dc0534177b7539119f4454
languageName: node
linkType: hard
"string-width@npm:^4.1.0, string-width@npm:^4.2.0":
version: 4.2.3
resolution: "string-width@npm:4.2.3"
dependencies:
emoji-regex: "npm:^8.0.0"
is-fullwidth-code-point: "npm:^3.0.0"
strip-ansi: "npm:^6.0.1"
checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b
languageName: node
linkType: hard
"string-width@npm:~2.1.1":
version: 2.1.1
resolution: "string-width@npm:2.1.1"
dependencies:
is-fullwidth-code-point: "npm:^2.0.0"
strip-ansi: "npm:^4.0.0"
checksum: 10c0/e5f2b169fcf8a4257a399f95d069522f056e92ec97dbdcb9b0cdf14d688b7ca0b1b1439a1c7b9773cd79446cbafd582727279d6bfdd9f8edd306ea5e90e5b610
languageName: node
linkType: hard
"strip-ansi@npm:^4.0.0":
version: 4.0.0
resolution: "strip-ansi@npm:4.0.0"
dependencies:
ansi-regex: "npm:^3.0.0"
checksum: 10c0/d75d9681e0637ea316ddbd7d4d3be010b1895a17e885155e0ed6a39755ae0fd7ef46e14b22162e66a62db122d3a98ab7917794e255532ab461bb0a04feb03e7d
languageName: node
linkType: hard
"strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1":
version: 6.0.1
resolution: "strip-ansi@npm:6.0.1"
dependencies:
ansi-regex: "npm:^5.0.1"
checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952
languageName: node
linkType: hard
"strip-final-newline@npm:2.0.0":
version: 2.0.0
resolution: "strip-final-newline@npm:2.0.0"
checksum: 10c0/bddf8ccd47acd85c0e09ad7375409d81653f645fda13227a9d459642277c253d877b68f2e5e4d819fe75733b0e626bac7e954c04f3236f6d196f79c94fa4a96f
languageName: node
linkType: hard
"which-module@npm:^2.0.0":
version: 2.0.1
resolution: "which-module@npm:2.0.1"
checksum: 10c0/087038e7992649eaffa6c7a4f3158d5b53b14cf5b6c1f0e043dccfacb1ba179d12f17545d5b85ebd94a42ce280a6fe65d0cbcab70f4fc6daad1dfae85e0e6a3e
languageName: node
linkType: hard
"wrap-ansi@npm:^6.2.0":
version: 6.2.0
resolution: "wrap-ansi@npm:6.2.0"
dependencies:
ansi-styles: "npm:^4.0.0"
string-width: "npm:^4.1.0"
strip-ansi: "npm:^6.0.0"
checksum: 10c0/baad244e6e33335ea24e86e51868fe6823626e3a3c88d9a6674642afff1d34d9a154c917e74af8d845fd25d170c4ea9cf69a47133c3f3656e1252b3d462d9f6c
languageName: node
linkType: hard
"y18n@npm:^4.0.0":
version: 4.0.3
resolution: "y18n@npm:4.0.3"
checksum: 10c0/308a2efd7cc296ab2c0f3b9284fd4827be01cfeb647b3ba18230e3a416eb1bc887ac050de9f8c4fd9e7856b2e8246e05d190b53c96c5ad8d8cb56dffb6f81024
languageName: node
linkType: hard
"yargs-parser@npm:^18.1.2":
version: 18.1.3
resolution: "yargs-parser@npm:18.1.3"
dependencies:
camelcase: "npm:^5.0.0"
decamelize: "npm:^1.2.0"
checksum: 10c0/25df918833592a83f52e7e4f91ba7d7bfaa2b891ebf7fe901923c2ee797534f23a176913ff6ff7ebbc1cc1725a044cc6a6539fed8bfd4e13b5b16376875f9499
languageName: node
linkType: hard
"yargs@npm:15.4.1":
version: 15.4.1
resolution: "yargs@npm:15.4.1"
dependencies:
cliui: "npm:^6.0.0"
decamelize: "npm:^1.2.0"
find-up: "npm:^4.1.0"
get-caller-file: "npm:^2.0.1"
require-directory: "npm:^2.1.1"
require-main-filename: "npm:^2.0.0"
set-blocking: "npm:^2.0.0"
string-width: "npm:^4.2.0"
which-module: "npm:^2.0.0"
y18n: "npm:^4.0.0"
yargs-parser: "npm:^18.1.2"
checksum: 10c0/f1ca680c974333a5822732825cca7e95306c5a1e7750eb7b973ce6dc4f97a6b0a8837203c8b194f461969bfe1fb1176d1d423036635285f6010b392fa498ab2d
languageName: node
linkType: hard
"yarn-workspaces@workspace:.":
version: 0.0.0-use.local
resolution: "yarn-workspaces@workspace:."
dependencies:
cowsay: "npm:^1.6.0"
pkg-a: "workspace:*"
pkg-b: "workspace:*"
languageName: unknown
linkType: soft