feat: whyrating - initial project from turbostarter boilerplate

This commit is contained in:
Alejandro Gutiérrez
2026-02-04 01:54:52 +01:00
commit 5cdc07cd39
1618 changed files with 338230 additions and 0 deletions

View File

@@ -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 🎉

View File

@@ -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. 🎉

View File

@@ -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" />

View File

@@ -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>