feat: whyrating - initial project from turbostarter boilerplate
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: Adding apps
|
||||
description: Learn how to add apps to your Turborepo workspace.
|
||||
url: /docs/mobile/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 `mobile` - we can use [git subtree](https://www.atlassian.com/git/tutorials/git-subtree).
|
||||
|
||||
Basically, we will create a subtree at `apps/mobile` 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/mobile` 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/mobile` folder. We will create a branch named `mobile-branch` and create a subtree for the `apps/mobile` folder.
|
||||
|
||||
```bash
|
||||
git subtree split --prefix=apps/mobile --branch mobile-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/mobile` folder (which acts as the template for all new apps).
|
||||
|
||||
```bash
|
||||
git subtree add --prefix=apps/ai-chat origin mobile-branch --squash
|
||||
```
|
||||
|
||||
You should now be able to see the `apps/ai-chat` folder with the contents of the `apps/mobile` 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 `mobile-branch` updates
|
||||
|
||||
After you have pulled the updates from the TurboStarter repository, you can split the branch again and push the updates to the mobile-branch:
|
||||
|
||||
```bash
|
||||
git subtree split --prefix=apps/mobile --branch mobile-branch
|
||||
```
|
||||
|
||||
Now, you can push the updates to the `mobile-branch`:
|
||||
|
||||
```bash
|
||||
git push origin mobile-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 mobile-branch --squash
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
That's it! You now have a new application in the monorepo 🎉
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
title: Adding packages
|
||||
description: Learn how to add packages to your Turborepo workspace.
|
||||
url: /docs/mobile/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/mobile` or modify existing packages under `packages`. You don't need to do this to add a new screen 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`.
|
||||
</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/mobile/src/app/index.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,119 @@
|
||||
---
|
||||
title: Components
|
||||
description: Manage and customize your app components.
|
||||
url: /docs/mobile/customization/components
|
||||
---
|
||||
|
||||
# Components
|
||||
|
||||
For the components part, we're using [react-native-reusables](https://reactnativereusables.com//getting-started/introduction/) for atomic, accessible and highly customizable components.
|
||||
|
||||
> It's like shadcn/ui, but for mobile apps.
|
||||
|
||||
<Callout type="info" title="Why react-native-reusables?">
|
||||
react-native-reusables is a powerful tool that allows you to generate
|
||||
pre-designed components with a single command. It's built with Uniwind (like
|
||||
Tailwind CSS for mobile) and accessibility in mind, it's also highly
|
||||
customizable.
|
||||
</Callout>
|
||||
|
||||
TurboStarter defines two packages that are responsible for the UI part of your app:
|
||||
|
||||
* `@turbostarter/ui` - shared styles, [themes](/docs/mobile/customization/styling#themes) and assets (e.g. icons)
|
||||
* `@turbostarter/ui-mobile` - pre-built UI mobile 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 [react-native-reusables CLI](https://www.npmjs.com/package/@react-native-reusables/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-mobile 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/mobile/src` directory.
|
||||
</Tab>
|
||||
|
||||
<Tab value="Copy-pasting">
|
||||
You can always copy-paste a component from the [react-native-reusables](https://reactnativereusables.com//getting-started/introduction/) 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/mobile/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="apps/mobile/src/modules/common/my-component.tsx"
|
||||
// [!code word:card]
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
} from "@turbostarter/ui-mobile/card";
|
||||
```
|
||||
|
||||
Then you can use it to build a component specific to your app:
|
||||
|
||||
```tsx title="apps/mobile/src/modules/common/my-component.tsx"
|
||||
export function MyComponent() {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>My Component</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Text>My Component Content</Text>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button>Click me</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
<Callout title="Think of it the same as for the web">
|
||||
Most of the components are the same as for the [web app](/docs/web/customization/components).
|
||||
|
||||
It means that you can basically migrate existing web components to the mobile app with just an import change!
|
||||
</Callout>
|
||||
|
||||
<Card href="https://reactnativereusables.com//getting-started/introduction/" title="react-native-reusables" description="reactnativereusables.com" />
|
||||
@@ -0,0 +1,146 @@
|
||||
---
|
||||
title: Styling
|
||||
description: Get started with styling your app.
|
||||
url: /docs/mobile/customization/styling
|
||||
---
|
||||
|
||||
# Styling
|
||||
|
||||
To build the mobile user interface, TurboStarter comes with [Uniwind](https://uniwind.dev/) pre-configured.
|
||||
|
||||
<Callout title="Why Uniwind?" type="info">
|
||||
Uniwind brings Tailwind CSS utilities to React Native. It lets you style with familiar classes while keeping native performance and platform-appropriate primitives.
|
||||
</Callout>
|
||||
|
||||
## Tailwind configuration
|
||||
|
||||
In the `packages/ui/shared/src/styles` directory, you will find shared CSS files with Tailwind configuration. To change global styles, 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 global styles.
|
||||
|
||||
Here is an example of an app's `globals.css` file:
|
||||
|
||||
```css title="apps/mobile/src/assets/styles/globals.css"
|
||||
@import "@turbostarter/ui/globals.css";
|
||||
@import "uniwind";
|
||||
|
||||
@theme inline {
|
||||
--font-sans: "Geist_400Regular";
|
||||
--font-sans-medium: "Geist_500Medium";
|
||||
--font-sans-semibold: "Geist_600SemiBold";
|
||||
--font-sans-bold: "Geist_700Bold";
|
||||
--font-mono: "GeistMono_400Regular";
|
||||
}
|
||||
```
|
||||
|
||||
This keeps a clear separation of concerns and a consistent structure for the Tailwind CSS configuration across apps.
|
||||
|
||||
## 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).
|
||||
|
||||
These variables are consumed across platforms. On mobile, the theme provider injects the shared variables into the app, so Uniwind utility classes like `bg-background` and `text-foreground` resolve correctly.
|
||||
|
||||
Feel free to add your own themes or override the existing ones to match your brand's identity.
|
||||
|
||||
To apply a custom theme to your app, use a `useTheme` hook to modify the config:
|
||||
|
||||
```tsx title="apps/mobile/src/lib/providers/theme.tsx"
|
||||
import { ThemeColor, ThemeMode } from "@turbostarter/ui";
|
||||
|
||||
import { useTheme } from "~/modules/common/hooks/use-theme";
|
||||
|
||||
export const ThemeSwitcher = () => {
|
||||
const { setConfig } = useTheme();
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
onPress={() =>
|
||||
setConfig({ mode: ThemeMode.DARK, color: ThemeColor.BLUE })
|
||||
}
|
||||
>
|
||||
<Text>Change the theme to dark blue</Text>
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
Under the hood, the `useTheme` hook uses [Uniwind.setTheme](https://docs.uniwind.dev/theming/basics#switch-to-a-specific-theme) and [updateCSSVariables](https://docs.uniwind.dev/theming/update-css-variables) utilities to apply the correct theme to the app together with its variables.
|
||||
|
||||
## 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;
|
||||
```
|
||||
|
||||
Our custom implementation reads the system color scheme via `useColorScheme` and applies `dark:` variants automatically. With the provider injecting shared variables, dark mode works out of the box.
|
||||
|
||||
You can also define the default theme mode and color in the [app configuration](/docs/mobile/configuration/app).
|
||||
|
||||
<Cards>
|
||||
<Card title="Uniwind" description="uniwind.dev" href="https://uniwind.dev/" />
|
||||
|
||||
<Card title="Theming Basics | Uniwind" description="docs.uniwind.dev" href="https://docs.uniwind.dev/theming/basics" />
|
||||
|
||||
<Card title="Custom Themes | Uniwind" description="docs.uniwind.dev" href="https://docs.uniwind.dev/theming/custom-themes" />
|
||||
</Cards>
|
||||
Reference in New Issue
Block a user