feat(db): mesh data model — meshes, members, invites, audit log
- pgSchema "mesh" with 4 tables isolating the peer mesh domain - Enums: visibility, transport, tier, role - audit_log is metadata-only (E2E encryption enforced at broker/client) - Cascade on mesh delete, soft-delete via archivedAt/revokedAt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: Adding apps
|
||||
description: Learn how to add apps to your Turborepo workspace.
|
||||
url: /docs/web/customization/add-app
|
||||
---
|
||||
|
||||
# Adding apps
|
||||
|
||||
<Callout title="Advanced topic" type="warn">
|
||||
This is an **advanced topic** - you should only follow these instructions if you are sure you want to add a new app to your TurboStarter project within your monorepo and want to keep pulling updates from the TurboStarter repository.
|
||||
</Callout>
|
||||
|
||||
In some ways - creating a new repository may be the easiest way to manage your application. However, if you want to keep your application within the monorepo and pull updates from the TurboStarter repository, you can follow these instructions.
|
||||
|
||||
To pull updates into a separate application outside of `web` - we can use [git subtree](https://www.atlassian.com/git/tutorials/git-subtree).
|
||||
|
||||
Basically, we will create a subtree at `apps/web` and create a new remote branch for the subtree. When we create a new application, we will pull the subtree into the new application. This allows us to keep it in sync with the `apps/web` folder.
|
||||
|
||||
To add a new app to your TurboStarter project, you need to follow these steps:
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
## Create a subtree
|
||||
|
||||
First, we need to create a subtree for the `apps/web` folder. We will create a branch named `web-branch` and create a subtree for the `apps/web` folder.
|
||||
|
||||
```bash
|
||||
git subtree split --prefix=apps/web --branch web-branch
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
## Create a new app
|
||||
|
||||
Now, we can create a new application in the `apps` folder.
|
||||
|
||||
Let's say we want to create a new app `ai-chat` at `apps/ai-chat` with the same structure as the `apps/web` folder (which acts as the template for all new apps).
|
||||
|
||||
```bash
|
||||
git subtree add --prefix=apps/ai-chat origin web-branch --squash
|
||||
```
|
||||
|
||||
You should now be able to see the `apps/ai-chat` folder with the contents of the `apps/web` folder.
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
## Update the app
|
||||
|
||||
When you want to update the new application, follow these steps:
|
||||
|
||||
### Pull the latest updates from the TurboStarter repository
|
||||
|
||||
The command below will update all the changes from the TurboStarter repository:
|
||||
|
||||
```bash
|
||||
git pull upstream main
|
||||
```
|
||||
|
||||
### Push the `web-branch` updates
|
||||
|
||||
After you have pulled the updates from the TurboStarter repository, you can split the branch again and push the updates to the web-branch:
|
||||
|
||||
```bash
|
||||
git subtree split --prefix=apps/web --branch web-branch
|
||||
```
|
||||
|
||||
Now, you can push the updates to the `web-branch`:
|
||||
|
||||
```bash
|
||||
git push origin web-branch
|
||||
```
|
||||
|
||||
### Pull the updates to the new application
|
||||
|
||||
Now, you can pull the updates to the new application:
|
||||
|
||||
```bash
|
||||
git subtree pull --prefix=apps/ai-chat origin web-branch --squash
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
That's it! You now have a new application in the monorepo 🎉
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
title: Adding packages
|
||||
description: Learn how to add packages to your Turborepo workspace.
|
||||
url: /docs/web/customization/add-package
|
||||
---
|
||||
|
||||
# Adding packages
|
||||
|
||||
<Callout title="Advanced topic" type="warn">
|
||||
This is an **advanced topic** - you should only follow these instructions if you are sure you want to add a new package to your TurboStarter application instead of adding a folder to your application in `apps/web` or modify existing packages under `packages`. You don't need to do this to add a new page or component to your application.
|
||||
</Callout>
|
||||
|
||||
To add a new package to your TurboStarter application, you need to follow these steps:
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
## Generate a new package
|
||||
|
||||
First, enter the command below to create a new package in your TurboStarter application:
|
||||
|
||||
```bash
|
||||
turbo gen package
|
||||
```
|
||||
|
||||
Turborepo will ask you to enter the name of the package you want to create. Enter the name of the package you want to create and press enter.
|
||||
|
||||
If you don't want to add dependencies to your package, you can skip this step by pressing enter.
|
||||
|
||||
The command will have generated a new package under packages named `@turbostarter/<package-name>`. If you named it `example`, the package will be named `@turbostarter/example`.
|
||||
|
||||
Finally, to make fast refresh work when you make changes to the package, you need to add the package to the `next.config.ts` file in the root of your TurboStarter application `apps/web`.
|
||||
|
||||
```ts title="next.config.ts"
|
||||
const INTERNAL_PACKAGES = [
|
||||
// all internal packages,
|
||||
"@turbostarter/example",
|
||||
];
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
## Export a module from your package
|
||||
|
||||
By default, the package exports a single module using the `index.ts` file. You can add more exports by creating new files in the package directory and exporting them from the `index.ts` file or creating export files in the package directory and adding them to the `exports` field in the `package.json` file.
|
||||
|
||||
### From `index.ts` file
|
||||
|
||||
The easiest way to export a module from a package is to create a new file in the package directory and export it from the `index.ts` file.
|
||||
|
||||
```ts title="packages/example/src/module.ts"
|
||||
export function example() {
|
||||
return "example";
|
||||
}
|
||||
```
|
||||
|
||||
Then, export the module from the `index.ts` file.
|
||||
|
||||
```ts title="packages/example/src/index.ts"
|
||||
export * from "./module";
|
||||
```
|
||||
|
||||
### From `exports` field in `package.json`
|
||||
|
||||
**This can be very useful for tree-shaking.** Assuming you have a file named `module.ts` in the package directory, you can export it by adding it to the `exports` field in the `package.json` file.
|
||||
|
||||
```json title="packages/example/package.json"
|
||||
{
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./module": "./src/module.ts"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**When to do this?**
|
||||
|
||||
1. when exporting two modules that don't share dependencies to ensure better tree-shaking. For example, if your exports contains both client and server modules.
|
||||
2. for better organization of your package
|
||||
|
||||
For example, create two exports `client` and `server` in the package directory and add them to the `exports` field in the `package.json` file.
|
||||
|
||||
```json title="packages/example/package.json"
|
||||
{
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./client": "./src/client.ts",
|
||||
"./server": "./src/server.ts"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. The `client` module can be imported using `import { client } from '@turbostarter/example/client'`
|
||||
2. The `server` module can be imported using `import { server } from '@turbostarter/example/server'`
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
## Use the package in your application
|
||||
|
||||
You can now use the package in your application by importing it using the package name:
|
||||
|
||||
```ts title="apps/web/src/app/page.tsx"
|
||||
import { example } from "@turbostarter/example";
|
||||
|
||||
console.log(example());
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
Et voilà! You have successfully added a new package to your TurboStarter application. 🎉
|
||||
@@ -0,0 +1,120 @@
|
||||
---
|
||||
title: Components
|
||||
description: Manage and customize your app components.
|
||||
url: /docs/web/customization/components
|
||||
---
|
||||
|
||||
# Components
|
||||
|
||||
For the components part, we're using [shadcn/ui](https://ui.shadcn.com) for atomic, accessible and highly customizable components.
|
||||
|
||||
<Callout type="info" title="Why shadcn/ui?">
|
||||
shadcn/ui is a powerful tool that allows you to generate pre-designed
|
||||
components with a single command. It's built with Tailwind CSS and Radix UI,
|
||||
and it's highly customizable.
|
||||
</Callout>
|
||||
|
||||
TurboStarter defines two packages that are responsible for the UI part of your app:
|
||||
|
||||
* `@turbostarter/ui` - shared styles, [themes](/docs/web/customization/styling#themes) and assets (e.g. icons)
|
||||
* `@turbostarter/ui-web` - pre-built UI web components, ready to use in your app
|
||||
|
||||
## Adding a new component
|
||||
|
||||
There are basically two ways to add a new component:
|
||||
|
||||
<Tabs items={["Using the CLI", "Copy-pasting"]}>
|
||||
<Tab value="Using the CLI">
|
||||
TurboStarter is fully compatible with [shadcn CLI](https://ui.shadcn.com/docs/cli), so you can generate new components with single command.
|
||||
|
||||
Run the following command from the **root** of your project:
|
||||
|
||||
```bash
|
||||
pnpm --filter @turbostarter/ui-web ui:add
|
||||
```
|
||||
|
||||
This will launch an interactive command-line interface to guide you through the process of adding a new component where you can pick which component you want to add.
|
||||
|
||||
```bash
|
||||
Which components would you like to add? > Space to select. A to toggle all.
|
||||
Enter to submit.
|
||||
|
||||
◯ accordion
|
||||
◯ alert
|
||||
◯ alert-dialog
|
||||
◯ aspect-ratio
|
||||
◯ avatar
|
||||
◯ badge
|
||||
◯ button
|
||||
◯ calendar
|
||||
◯ card
|
||||
◯ checkbox
|
||||
```
|
||||
|
||||
Newly created components will appear in the `packages/ui/web/src` directory.
|
||||
</Tab>
|
||||
|
||||
<Tab value="Copy-pasting">
|
||||
You can always copy-paste a component from the [shadcn/ui](https://ui.shadcn.com/docs/components) website and modify it to your needs.
|
||||
|
||||
This is possible, because the components are headless and don't need (in most cases) any additional dependencies.
|
||||
|
||||
Copy code from the website, create a new file in the `packages/ui/web/src` directory and paste the code into the file.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Callout title="Keep it atomic" type="warn">
|
||||
Keep in mind that you should always try to keep shared components as atomic as possible. This will make it easier to reuse them and to build specific views by composition.
|
||||
|
||||
E.g. include components like `Button`, `Input`, `Card`, `Dialog` in shared package, but keep specific components like `LoginForm` in your app directory.
|
||||
</Callout>
|
||||
|
||||
## Using components
|
||||
|
||||
Each component is a standalone entity which has a separate export from the package. It helps to keep things modular, avoid unnecessary dependencies and make tree-shaking possible.
|
||||
|
||||
To import a component from the UI package, use the following syntax:
|
||||
|
||||
```tsx title="components/my-component.tsx"
|
||||
// [!code word:card]
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
} from "@turbostarter/ui-web/card";
|
||||
```
|
||||
|
||||
Then you can use it to build a component specific to your app:
|
||||
|
||||
```tsx title="components/my-component.tsx"
|
||||
export function MyComponent() {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>My Component</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p>My Component Content</p>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button>Click me</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
<Callout title="Recommendation: use v0 to generate layouts">
|
||||
We recommend using [v0](https://v0.dev) to generate layouts for your app. It's a powerful tool that allows you to generate layouts from the natural language instructions.
|
||||
|
||||
Of course, **it won't replace a designer**, but it can be a good starting point for your layout.
|
||||
</Callout>
|
||||
|
||||
<Cards>
|
||||
<Card href="https://ui.shadcn.com/" title="shadcn/ui" description="ui.shadcn.com" />
|
||||
|
||||
<Card href="https://v0.dev/chat" title="v0 by Vercel" description="v0.dev" />
|
||||
</Cards>
|
||||
@@ -0,0 +1,153 @@
|
||||
---
|
||||
title: Styling
|
||||
description: Get started with styling your app.
|
||||
url: /docs/web/customization/styling
|
||||
---
|
||||
|
||||
# Styling
|
||||
|
||||
To build the web user interface, TurboStarter comes with [Tailwind CSS](https://tailwindcss.com/) and [Radix UI](https://www.radix-ui.com/) pre-configured.
|
||||
|
||||
<Callout title="Why Tailwind CSS and Radix UI?" type="info">
|
||||
The combination of Tailwind CSS and Radix UI gives ready-to-use, accessible UI components that can be fully customized to match your brand's design.
|
||||
</Callout>
|
||||
|
||||
## Tailwind configuration
|
||||
|
||||
In the `packages/ui/shared/src/styles` directory, you will find shared CSS files with Tailwind CSS configuration. To change global styles, you can edit the files in this folder.
|
||||
|
||||
Here is an example of a shared CSS file that includes the Tailwind CSS configuration:
|
||||
|
||||
```css title="packages/ui/shared/src/styles/globals.css"
|
||||
@import "tailwindcss";
|
||||
@import "./themes.css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
:root {
|
||||
--radius: 0.65rem;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
For colors, we rely strictly on [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) in [OKLCH](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch) format to allow for easy theme management without the need for any JavaScript.
|
||||
|
||||
Also, each app has its own `globals.css` file, which extends the shared config and allows you to override the global styles.
|
||||
|
||||
Here is an example of an app's `globals.css` file:
|
||||
|
||||
```css title="apps/web/src/assets/styles/globals.css"
|
||||
@import "@turbostarter/ui/globals.css";
|
||||
@import "@turbostarter/ui-web/globals.css";
|
||||
|
||||
@theme inline {
|
||||
/* Overridden theme variables for the app */
|
||||
--background: oklch(0.98 0.01 80);
|
||||
--foreground: oklch(0.22 0.03 120);
|
||||
--card: oklch(0.97 0.02 50);
|
||||
--card-foreground: oklch(0.18 0.01 280);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
This way, we maintain a separation of concerns and a clear structure for the Tailwind CSS configuration.
|
||||
|
||||
## Themes
|
||||
|
||||
TurboStarter comes with **9+** predefined themes, which you can use to quickly change the look and feel of your app.
|
||||
|
||||
They're defined in the `packages/ui/shared/src/styles/themes` directory. Each theme is a set of variables that can be overridden:
|
||||
|
||||
```ts title="packages/ui/shared/src/styles/themes/colors/orange.ts"
|
||||
export const orange = {
|
||||
light: {
|
||||
background: [1, 0, 0],
|
||||
foreground: [0.141, 0.005, 285.823],
|
||||
card: [1, 0, 0],
|
||||
"card-foreground": [0.141, 0.005, 285.823],
|
||||
...
|
||||
}
|
||||
} satisfies ThemeColors;
|
||||
```
|
||||
|
||||
Each variable is stored as a [OKLCH](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch) array, which is then converted to a CSS variable at build time (by our custom build script). That way we can ensure full type-safety and reuse themes across different parts of our apps (e.g. use the same theme in emails).
|
||||
|
||||
Feel free to add your own themes or override the existing ones to match your brand's identity.
|
||||
|
||||
To apply a theme to your app, you can use the `data-theme` attribute on the `html` element:
|
||||
|
||||
```tsx title="apps/web/src/app/layout.tsx"
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html>
|
||||
<body data-theme="orange">{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Dark mode
|
||||
|
||||
TurboStarter comes with built-in dark mode support.
|
||||
|
||||
Each theme has a corresponding set of dark mode variables, which are used to switch the theme to its dark mode counterpart.
|
||||
|
||||
```ts title="packages/ui/shared/src/styles/themes/colors/orange.ts"
|
||||
export const orange = {
|
||||
light: {},
|
||||
dark: {
|
||||
background: [0.141, 0.005, 285.823],
|
||||
foreground: [0.985, 0, 0],
|
||||
card: [0.21, 0.006, 285.885],
|
||||
"card-foreground": [0.985, 0, 0],
|
||||
...
|
||||
}
|
||||
} satisfies ThemeColors;
|
||||
```
|
||||
|
||||
Because the dark variant is defined to use a class (`@custom-variant dark (&:is(.dark *))`) in the shared Tailwind configuration, we need to add the `dark` class to the `html` element to apply dark mode styles.
|
||||
|
||||
For this purpose, we're using the [next-themes](https://github.com/pacocoursey/next-themes) package under the hood to handle user preference management.
|
||||
|
||||
```tsx title="apps/web/src/providers/theme.tsx"
|
||||
export const ThemeProvider = memo<ThemeProviderProps>(({ children }) => {
|
||||
return (
|
||||
<NextThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme={appConfig.theme.mode}
|
||||
enableSystem
|
||||
>
|
||||
{children}
|
||||
<ThemeConfigProvider />
|
||||
</NextThemeProvider>
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
You can also define the default theme mode and color in the [app configuration](/docs/web/configuration/app).
|
||||
|
||||
<Cards>
|
||||
<Card title="Tailwind CSS" description="tailwindcss.com" href="https://tailwindcss.com/" />
|
||||
|
||||
<Card title="Radix UI" description="radix-ui.com" href="https://www.radix-ui.com/" />
|
||||
</Cards>
|
||||
Reference in New Issue
Block a user