Skip to content

Commit 6ad5d28

Browse files
Initial commit from create-turbo
0 parents  commit 6ad5d28

31 files changed

Lines changed: 10431 additions & 0 deletions

.changeset/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Changesets
2+
3+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4+
with multi-package repos, or single-package repos to help you version and publish your code. You can
5+
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6+
7+
We have a quick list of common questions to get you started engaging with this project in
8+
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

.changeset/config.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json",
3+
"changelog": "@changesets/cli/changelog",
4+
"commit": false,
5+
"fixed": [],
6+
"linked": [],
7+
"access": "public",
8+
"updateInternalDependencies": "patch",
9+
"ignore": [
10+
"@repo/docs"
11+
]
12+
}

.github/workflows/release.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
concurrency: ${{ github.workflow }}-${{ github.ref }}
9+
10+
jobs:
11+
release:
12+
name: Release
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout Repo
16+
uses: actions/checkout@v4
17+
18+
- name: Setup Node.js 20.x
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: 20
22+
23+
- name: Install Dependencies
24+
run: yarn
25+
26+
- name: Create Release Pull Request or Publish to npm
27+
id: changesets
28+
uses: changesets/action@v1
29+
with:
30+
# This expects you to have a script called release which does a build for your packages and calls changeset publish
31+
publish: yarn release
32+
env:
33+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
35+
36+
- name: Send a Slack notification if a publish happens
37+
if: steps.changesets.outputs.published == 'true'
38+
# You can do something when a publish happens.
39+
run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!"

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.DS_Store
2+
node_modules
3+
.turbo
4+
*.log
5+
.next
6+
dist
7+
dist-ssr
8+
*.local
9+
.env
10+
.cache
11+
server/dist
12+
public/dist
13+
storybook-static/

.npmrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
auto-install-peers = true
2+
public-hoist-pattern[]=*storybook*

.vscode/settings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"eslint.workingDirectories": [
3+
{
4+
"mode": "auto"
5+
}
6+
]
7+
}

README.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# Turborepo Design System Starter
2+
3+
This is a community-maintained example. If you experience a problem, please submit a pull request with a fix. GitHub Issues will be closed.
4+
5+
This guide explains how to use a React design system starter powered by:
6+
7+
- 🏎 [Turborepo](https://turborepo.dev) — High-performance build system for Monorepos
8+
- 🚀 [React](https://reactjs.org/) — JavaScript library for user interfaces
9+
- 🛠 [Tsup](https://github.com/egoist/tsup) — TypeScript bundler powered by esbuild
10+
- 📖 [Storybook](https://storybook.js.org/) — UI component environment powered by Vite
11+
12+
As well as a few others tools preconfigured:
13+
14+
- [TypeScript](https://www.typescriptlang.org/) for static type checking
15+
- [ESLint](https://eslint.org/) for code linting
16+
- [Prettier](https://prettier.io) for code formatting
17+
- [Changesets](https://github.com/changesets/changesets) for managing versioning and changelogs
18+
- [GitHub Actions](https://github.com/changesets/action) for fully automated package publishing
19+
20+
## Using this example
21+
22+
Run the following command:
23+
24+
```sh
25+
npx create-turbo@latest -e design-system
26+
```
27+
28+
### Useful Commands
29+
30+
- `pnpm build` - Build all packages, including the Storybook site
31+
- `pnpm dev` - Run all packages locally and preview with Storybook
32+
- `pnpm lint` - Lint all packages
33+
- `pnpm changeset` - Generate a changeset
34+
- `pnpm clean` - Clean up all `node_modules` and `dist` folders (runs each package's clean script)
35+
36+
## Turborepo
37+
38+
[Turborepo](https://turborepo.dev) is a high-performance build system for JavaScript and TypeScript codebases. It was designed after the workflows used by massive software engineering organizations to ship code at scale. Turborepo abstracts the complex configuration needed for monorepos and provides fast, incremental builds with zero-configuration remote caching.
39+
40+
Using Turborepo simplifies managing your design system monorepo, as you can have a single lint, build, test, and release process for all packages. [Learn more](https://vercel.com/blog/monorepos-are-changing-how-teams-build-software) about how monorepos improve your development workflow.
41+
42+
## Apps & Packages
43+
44+
This Turborepo includes the following packages and applications:
45+
46+
- `apps/docs`: Component documentation site with Storybook
47+
- `packages/ui`: Core React components
48+
- `packages/typescript-config`: Shared `tsconfig.json`s used throughout the Turborepo
49+
- `packages/eslint-config`: ESLint preset
50+
51+
Each package and app is 100% [TypeScript](https://www.typescriptlang.org/). Workspaces enables us to "hoist" dependencies that are shared between packages to the root `package.json`. This means smaller `node_modules` folders and a better local dev experience. To install a dependency for the entire monorepo, use the `-w` workspaces flag with `pnpm add`.
52+
53+
This example sets up your `.gitignore` to exclude all generated files, other folders like `node_modules` used to store your dependencies.
54+
55+
### Compilation
56+
57+
To make the ui library code work across all browsers, we need to compile the raw TypeScript and React code to plain JavaScript. We can accomplish this with `tsup`, which uses `esbuild` to greatly improve performance.
58+
59+
Running `pnpm build` from the root of the Turborepo will run the `build` command defined in each package's `package.json` file. Turborepo runs each `build` in parallel and caches & hashes the output to speed up future builds.
60+
61+
For `@acme/ui`, the `build` command is equivalent to the following:
62+
63+
```bash
64+
tsup src/*.tsx --format esm,cjs --dts --external react
65+
```
66+
67+
`tsup` compiles all of the components in the design system individually, into both ES Modules and CommonJS formats as well as their TypeScript types. The `package.json` for `@acme/ui` then instructs the consumer to select the correct format:
68+
69+
```json:ui/package.json
70+
{
71+
"name": "@acme/ui",
72+
"version": "0.0.0",
73+
"sideEffects": false,
74+
"exports":{
75+
"./button": {
76+
"types": "./src/button.tsx",
77+
"import": "./dist/button.mjs",
78+
"require": "./dist/button.js"
79+
}
80+
}
81+
}
82+
```
83+
84+
Run `pnpm build` to confirm compilation is working correctly. You should see a folder `ui/dist` which contains the compiled output.
85+
86+
```bash
87+
ui
88+
└── dist
89+
├── button.d.ts <-- Types
90+
├── button.js <-- CommonJS version
91+
├── button.mjs <-- ES Modules version
92+
└── button.d.mts <-- ES Modules version with Types
93+
```
94+
95+
## Components
96+
97+
Each file inside of `ui/src` is a component inside our design system. For example:
98+
99+
```tsx:ui/src/Button.tsx
100+
import * as React from 'react';
101+
102+
export interface ButtonProps {
103+
children: React.ReactNode;
104+
}
105+
106+
export function Button(props: ButtonProps) {
107+
return <button>{props.children}</button>;
108+
}
109+
110+
Button.displayName = 'Button';
111+
```
112+
113+
When adding a new file, ensure that its specifier is defined in `package.json` file:
114+
115+
```json:ui/package.json
116+
{
117+
"name": "@acme/ui",
118+
"version": "0.0.0",
119+
"sideEffects": false,
120+
"exports":{
121+
"./button": {
122+
"types": "./src/button.tsx",
123+
"import": "./dist/button.mjs",
124+
"require": "./dist/button.js"
125+
}
126+
// Add new component exports here
127+
}
128+
}
129+
```
130+
131+
## Storybook
132+
133+
Storybook provides us with an interactive UI playground for our components. This allows us to preview our components in the browser and instantly see changes when developing locally. This example preconfigures Storybook to:
134+
135+
- Use Vite to bundle stories instantly (in milliseconds)
136+
- Automatically find any stories inside the `stories/` folder
137+
- Support using module path aliases like `@acme/ui` for imports
138+
- Write MDX for component documentation pages
139+
140+
For example, here's the included Story for our `Button` component:
141+
142+
```js:apps/docs/stories/button.stories.mdx
143+
import { Button } from '@acme/ui/button';
144+
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
145+
146+
<Meta title="Components/Button" component={Button} />
147+
148+
# Button
149+
150+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec euismod, nisl eget consectetur tempor, nisl nunc egestas nisi, euismod aliquam nisl nunc euismod.
151+
152+
## Props
153+
154+
<Props of={Box} />
155+
156+
## Examples
157+
158+
<Preview>
159+
<Story name="Default">
160+
<Button>Hello</Button>
161+
</Story>
162+
</Preview>
163+
```
164+
165+
This example includes a few helpful Storybook scripts:
166+
167+
- `pnpm dev`: Starts Storybook in dev mode with hot reloading at `localhost:6006`
168+
- `pnpm build`: Builds the Storybook UI and generates the static HTML files
169+
- `pnpm preview-storybook`: Starts a local server to view the generated Storybook UI
170+
171+
## Versioning & Publishing Packages
172+
173+
This example uses [Changesets](https://github.com/changesets/changesets) to manage versions, create changelogs, and publish to npm. It's preconfigured so you can start publishing packages immediately.
174+
175+
You'll need to create an `NPM_TOKEN` and `GITHUB_TOKEN` and add it to your GitHub repository settings to enable access to npm. It's also worth installing the [Changesets bot](https://github.com/apps/changeset-bot) on your repository.
176+
177+
### Generating the Changelog
178+
179+
To generate your changelog, run `pnpm changeset` locally:
180+
181+
1. **Which packages would you like to include?** – This shows which packages and changed and which have remained the same. By default, no packages are included. Press `space` to select the packages you want to include in the `changeset`.
182+
1. **Which packages should have a major bump?** – Press `space` to select the packages you want to bump versions for.
183+
1. If doing the first major version, confirm you want to release.
184+
1. Write a summary for the changes.
185+
1. Confirm the changeset looks as expected.
186+
1. A new Markdown file will be created in the `changeset` folder with the summary and a list of the packages included.
187+
188+
### Releasing
189+
190+
When you push your code to GitHub, the [GitHub Action](https://github.com/changesets/action) will run the `release` script defined in the root `package.json`:
191+
192+
```bash
193+
turbo run build --filter=docs^... && changeset publish
194+
```
195+
196+
Turborepo runs the `build` script for all publishable packages (excluding docs) and publishes the packages to npm. By default, this example includes `acme` as the npm organization. To change this, do the following:
197+
198+
- Rename folders in `packages/*` to replace `acme` with your desired scope
199+
- Search and replace `acme` with your desired scope
200+
- Re-run `pnpm install`
201+
202+
To publish packages to a private npm organization scope, **remove** the following from each of the `package.json`'s
203+
204+
```diff
205+
- "publishConfig": {
206+
- "access": "public"
207+
- },
208+
```

apps/docs/.eslintrc.cjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/** @type {import("eslint").Linter.Config} */
2+
module.exports = {
3+
extends: ["@repo/eslint-config/storybook.js"],
4+
};

apps/docs/.storybook/main.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { dirname, join, resolve } from "path";
2+
3+
function getAbsolutePath(value) {
4+
return dirname(require.resolve(join(value, "package.json")));
5+
}
6+
7+
const config = {
8+
stories: ["../stories/*.stories.tsx", "../stories/**/*.stories.tsx"],
9+
addons: [
10+
getAbsolutePath("@storybook/addon-links"),
11+
getAbsolutePath("@storybook/addon-essentials"),
12+
],
13+
framework: {
14+
name: getAbsolutePath("@storybook/react-vite"),
15+
options: {},
16+
},
17+
18+
core: {},
19+
20+
async viteFinal(config, { configType }) {
21+
// customize the Vite config here
22+
return {
23+
...config,
24+
define: { "process.env": {} },
25+
resolve: {
26+
alias: [
27+
{
28+
find: "ui",
29+
replacement: resolve(__dirname, "../../../packages/ui/"),
30+
},
31+
],
32+
},
33+
};
34+
},
35+
36+
docs: {
37+
autodocs: true,
38+
},
39+
};
40+
41+
export default config;

apps/docs/package.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "docs",
3+
"version": "0.0.0",
4+
"type": "module",
5+
"private": true,
6+
"scripts": {
7+
"dev": "storybook dev -p 6006",
8+
"build": "storybook build --docs",
9+
"preview-storybook": "serve storybook-static",
10+
"clean": "rm -rf .turbo node_modules",
11+
"lint": "eslint ./stories/*.stories.tsx --max-warnings 0"
12+
},
13+
"dependencies": {
14+
"@acme/ui": "workspace:*",
15+
"react": "^18.2.0",
16+
"react-dom": "^18.2.0"
17+
},
18+
"devDependencies": {
19+
"@repo/eslint-config": "workspace:*",
20+
"@storybook/addon-actions": "^8.2.6",
21+
"@storybook/addon-essentials": "^8.2.6",
22+
"@storybook/addon-links": "^8.2.6",
23+
"@storybook/react": "^8.2.6",
24+
"@storybook/react-vite": "^8.2.6",
25+
"@vitejs/plugin-react": "^4.2.1",
26+
"eslint": "^8.57.0",
27+
"serve": "^14.2.1",
28+
"storybook": "^8.2.6",
29+
"@repo/typescript-config": "workspace:*",
30+
"typescript": "5.5.4",
31+
"vite": "^5.1.4"
32+
}
33+
}

0 commit comments

Comments
 (0)