{"id":25527494,"url":"https://github.com/nktnet1/rt-stack","last_synced_at":"2026-01-09T17:30:23.223Z","repository":{"id":278384115,"uuid":"932057025","full_name":"nktnet1/rt-stack","owner":"nktnet1","description":"Turborepo for modular components, shared configs and full type-safety.","archived":false,"fork":false,"pushed_at":"2025-02-19T14:04:11.000Z","size":665,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-19T14:22:22.637Z","etag":null,"topics":["better-auth","drizzle-orm","hono","react","shadcn-ui","tailwind","tanstack","template","trpc"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nktnet1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-13T09:44:38.000Z","updated_at":"2025-02-19T14:04:15.000Z","dependencies_parsed_at":"2025-02-19T14:22:43.014Z","dependency_job_id":"ede9eb06-77a7-4182-93cf-d4c4cae0055c","html_url":"https://github.com/nktnet1/rt-stack","commit_stats":null,"previous_names":["nktnet1/rt-stack"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nktnet1%2Frt-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nktnet1%2Frt-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nktnet1%2Frt-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nktnet1%2Frt-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nktnet1","download_url":"https://codeload.github.com/nktnet1/rt-stack/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239742446,"owners_count":19689313,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["better-auth","drizzle-orm","hono","react","shadcn-ui","tailwind","tanstack","template","trpc"],"created_at":"2025-02-19T22:18:56.502Z","updated_at":"2026-01-09T17:30:23.213Z","avatar_url":"https://github.com/nktnet1.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://rtstack.nktnet.uk\" target=\"_blank\"\u003e\n        \u003cimg align=\"absmiddle\" width=\"40\" src=\"./apps/web/public/favicon.png\"\u003e\n      \u003c/a\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ch1\u003e\n        \u003ca href=\"https://rtstack.nktnet.uk\" target=\"_blank\"\u003eRT Stack\u003c/a\u003e\n      \u003c/h1\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nA modern \u0026 lightweight [turborepo](https://turbo.build/repo/docs) template for\nfullstack projects with modular components, shared configs, containerised\ndeployments and 100% type-safety.\n\n- [About](#about)\n  - [Stack overview](#stack-overview)\n  - [Base Functionalities](#base-functionalities)\n  - [Inspirations \u0026 Goals](#inspirations--goals)\n- [Quick Start](#quick-start)\n  - [Prerequisites](#prerequisites)\n  - [Setup](#setup)\n  - [Using an External Database](#using-an-external-database)\n- [Developing](#developing)\n  - [Working with a single package](#working-with-a-single-package)\n  - [Adding new shadcn components](#adding-new-shadcn-components)\n  - [Adding new better-auth plugins](#adding-new-better-auth-plugins)\n  - [Tooling Scripts](#tooling-scripts)\n- [Containerisation (Docker/Podman)](#containerisation-dockerpodman)\n- [Deployment](#deployment)\n  - [Using Containers](#using-containers)\n  - [Using Major Platforms](#using-major-platforms)\n  - [Domain Caveat](#domain-caveat)\n- [Other Notes](#other-notes)\n  - [Tanstack Router](#tanstack-router)\n  - [Server API Artificial Delays](#server-api-artificial-delays)\n  - [Environment Variables](#environment-variables)\n  - [Extensions to existing template](#extensions-to-existing-template)\n\n## About\n\n### Stack overview\n\nBelow is an overview of all the components in the stack:\n\n```\napps\n  ├─ web\n  |   ├─ react (vite)\n  |   ├─ tanstack (router, query, form)\n  |   └─ tailwindcss\n  ├─ server\n  |   └─ hono (wrapper for api \u0026 auth)\npackages\n  ├─ api\n  |   └─ orpc with valibot\n  ├─ auth\n  |   └─ better-auth\n  ├─ db\n  |   └─ drizzle-orm (postgres database)\n  ├─ ui\n  |   ├─ tailwindcss\n  |   └─ shadcn \u0026 radix ui\ntools\n  ├─ eslint\n  ├─ prettier\n  ├─ tailwind\n  └─ typescript\n```\n\nView all catalog dependencies in [pnpm-workspace.yaml](pnpm-workspace.yaml).\n\n### Base Functionalities\n\nThe following features are implemented out-of-the-box:\n\n- login/register (using [better-auth email/password](https://www.better-auth.com/docs/authentication/email-password)) credentials provider\n- themes (dark/light mode using [next-themes](https://github.com/pacocoursey/next-themes))\n- web/server integration ([oRPC](https://orpc.unnoq.com/docs/getting-started) API example for creating/listing posts)\n\nYou can visit the [live demo](https://rtstack.nktnet.uk) to see these features in action.\n\n### Inspirations \u0026 Goals\n\nMany aspects of the RT Stack were derived from the\n[t3-oss/create-t3-turbo](https://github.com/t3-oss/create-t3-turbo). However,\nthere is a preference for:\n\n- [tanstack-router](https://tanstack.com/router/latest) (web) + [hono](https://hono.dev) (server) instead of [nextjs](https://nextjs.org) (fullstack)\n- [better-auth](https://www.better-auth.com) for authentication instead of [auth.js (next-auth)](https://authjs.dev)\n- [orpc](https://orpc.unnoq.com) with openapi support instead of [trpc](https://trpc.io)\n- [valibot](https://valibot.dev) for input validation instead of [zod](https://zod.dev)\n- [tanstack-form](https://tanstack.com/form/latest) for type-safe forms instead of [react-hook-form](https://react-hook-form.com)\n- using `.env` in each application/package instead of globally, as per [turborepo's recommendations](https://turbo.build/repo/docs/crafting-your-repository/using-environment-variables#best-practices)\n\n## Quick Start\n\n### Prerequisites\n\nEnsure the following tools are available on your system:\n\n1. [node](https://nodejs.org/en/download) (version 24+)\n1. [pnpm](https://pnpm.io/installation) (version 10+)\n1. [postgres](https://www.postgresql.org) database, which you can easily run using tools like:\n   - [docker](https://docs.docker.com/engine/install) and [docker-compose](https://docs.docker.com/compose)\n   - [podman](https://podman.io/docs/installation) and [podman-compose](https://github.com/containers/podman-compose)\n   - [supabase](https://supabase.com)'s free tier cloud database\n\n### Setup\n\n```bash\n# Create a repository using the rt-stack template (replace YOUR_PROJECT)\npnpm dlx create-turbo@latest -m pnpm -e https://github.com/nktnet1/rt-stack YOUR_PROJECT\n\n# Enter the directory or open in your IDE (replace YOUR_PROJECT)\ncd YOUR_PROJECT\n\n# Install all dependencies for apps and packages\npnpm install\n\n# Copy .env.example to .env for all applications and the @repo/db package\npnpm env:copy-example\n\n# Start a local postgres instance in the background (e.g. using docker)\ndocker compose up db --detach\n\n# Push the drizzle schema to your database\npnpm db:push\n```\n\nYou can then start all applications with\n\n```bash\npnpm dev\n```\n\nBy default, the following URLs will be accessible:\n\n- Web (frontend): http://localhost:8085\n- Server (backend): http://localhost:3035\n  - API - OpenAPI reference: http://localhost:3035/api\n  - Auth - OpenAPI reference: http://localhost:3035/api/auth/reference\n\nThe [OpenAPI](https://www.openapis.org) reference uses [Scalar](https://github.com/scalar/scalar) to display all available endpoints.\n\n### Using an External Database\n\nWhen using an external postgres database (e.g. from [supabase](https://supabase.com)), you can skip the step that spins up a local postgres instance with docker.\n\nInstead, you will need to modify the following environment variables:\n\n1. `SERVER_POSTGRES_URL` in the file `apps/server/.env`\n\n   - used at runtime by the backend server in `pnpm dev`\n\n1. `DB_POSTGRES_URL` in the file `packages/db/.env`\n   - used in database schema migrations with `pnpm db:push`\n\n## Development\n\n### Working with a single package\n\nUse [`pnpm --filter=\u003cname\u003e`](https://pnpm.io/filtering) (where `\u003cname\u003e` is\ndefined in the `package.json` of each package).\n\nExample usage:\n\n```bash\n# Install the nuqs package for our web application:\npnpm --filter=web install nuqs\n\n# Format only the ui package:\npnpm --filter=@repo/ui format\n```\n\nYou can get a list of all package names using the command below:\n\n```bash\npnpm list --depth -1 --recursive\n```\n\n### Adding new shadcn components\n\nTo install a single Shadcn/UI component, e.g. `button`, use the command\n\n```bash\npnpm ui-add button\n```\n\nYou can also open an interactive session to select components using a TUI by not passing any arguments\n\n```bash\npnpm ui-add\n```\n\n- press `i` to enter interactive mode on startup\n- use `j/k` (or arrow keys) to navigate up and down.\n- use `\u003cSpace\u003e` to toggle select your desired component(s)\n- hit `\u003cEnter\u003e` to install all selected components\n\n### Adding new better-auth plugins\n\nWhen integrating more better-auth plugins, e.g.\n\n- [admin](https://better-auth.vercel.app/docs/plugins/admin)\n- [organization](https://better-auth.vercel.app/docs/plugins/organization)\n\nYou should\n\n1. Modify the auth package server and client files in accordance with the plugin's\n   respective documentations.\n\n2. Run the interactive command:\n\n   ```bash\n   pnpm auth:schema:generate\n   ```\n\n   Press `i` to enter interactive mode, then `y` to overwrite [packages/db/src/schemas/auth.ts](packages/db/src/schemas/auth.ts).\n\n3. Format and fix all linting issues, e.g. with\n\n   ```bash\n   pnpm format:fix\n   pnpm lint:fix\n   ```\n\n4. Push your new schema to the database\n\n   ```bash\n   pnpm db:push\n   ```\n\n5. Occasionally, the type inference will not work immediately in your IDE (e.g. in VSCode).\n   This can be resolved by running\n\n   ```bash\n   pnpm clean \u0026\u0026 pnpm install\n   ```\n\n   followed by a restarting your TS Server or reloading VSCode.\n\nYou can find an example in the [better-auth-admin-organization-plugins](https://github.com/nktnet1/rt-stack/tree/better-auth-admin-organization-plugins) branch.\n\n### Tooling Scripts\n\nAll scripts are defined in [package.json](package.json) and\n[turbo.json](turbo.json):\n\n```bash\npnpm clean                  # remove all .cache, .turbo, dist, node_modules\n\npnpm typecheck              # report typescript issues\n\npnpm format                 # report prettier issues\npnpm format:fix             # auto-fix prettier issues\n\npnpm lint                   # report eslint issues\npnpm lint:fix               # auto-fix eslint issues\n\npnpx codemod pnpm/catalog   # migrate dependencies to pnpm-workspace.yaml\n```\n\n## Containerisation (Docker/Podman)\n\nBoth the `web` and `server` applications have been containerised. You can start\nsee this in action by running the commands:\n\n```bash\n# Start all applications\ndocker compose up --build\n\n# Push the drizzle schema to your database. While you can use `pnpm db:push` on\n# the host machine if you have installed all the required dependencies, it is\n# also possible to do everything within docker alone.\n# Open a second terminal and run the command:\ndocker compose run --build --rm drizzle\n\n# Upon completion, you will be inside the `drizzle` docker container instead\n# of the host machine. You can now push the schema with:\nnode dist/push.mjs\n```\n\nYou can then open the web link below in your browser:\n\n- http://localhost:8085\n\nPlease note that these containers are run in production mode. For further\ndetails, see\n\n- [compose.yaml](compose.yaml)\n- [apps/server/Dockerfile](apps/server/Dockerfile)\n- [apps/web/Dockerfile](apps/web/Dockerfile)\n- [apps/web/nginx.conf](apps/web/nginx.conf)\n\n## Deployment\n\n\u003e [!TIP]\n\u003e The [live demo](https://rtstack.nktnet.uk) of RT Stack is currently deployed to\n\u003e\n\u003e - vercel for the web frontend\n\u003e - fly.io for the server backend and postgres database\n\n### Using Containers\n\nYou can deploy applications to any services that supports docker deployment.\n\nUsing docker compose (see [compose.yaml](compose.yaml)) is also an option,\nalthough this alone may not be production-ready at scale. However, it can be\npaired with\n\n- reverse proxies and load balancers offered by tools like\n  [Traefik](https://github.com/traefik/traefik) or\n  [Caddy](https://github.com/caddyserver/caddy)\n- container orchestration platforms like [Docker Swarm](https://docs.docker.com/engine/swarm) and [Kubernetes](https://kubernetes.io)\n\nPersonally, I recommend setting up a Virtual Private Server (e.g. on [Hetzner](https://www.hetzner.com))\nand make use of self-hostable PaaS software which automatically handles the complexity of deployment\nmentioned above for you - this includes:\n\n- Coolify\n  - https://github.com/coollabsio/coolify\n  - https://www.coolify.io\n- Dokploy\n  - https://github.com/Dokploy/dokploy\n  - http://dokploy.com\n\nDo note that for the **web** application, the `PUBLIC_SERVER_URL` variable\navailable at build time (as a docker build argument), rather than an environment\nvariable at runtime.\n\nAlso, both the **server** application's `PUBLIC_WEB_URL` and the **web**\napplication's `PUBLIC_SERVER_URL` needs to be set as internet-accessible URLs\nwhen deployed, e.g. `https://mycompany.com` and `https://api.mycompany.com`,\nrather than referencing `http://localhost:8085` like in development.\n\n### Using Major Platforms\n\nThe **web** application is a simple React static site powered by Vite, which is\neasily deployed to platforms such as GitHub/GitLab pages, Vercel and Netlify.\nYou can refer to the [vite documentation](https://vite.dev/guide/static-deploy)\nfor deployment guides on all major platforms.\n\nThe **server** application uses the [hono](https://hono.dev) web framework with the [Node.js runtime](https://hono.dev/docs/getting-started/nodejs). However,\nthis can be exchanged with other runtimes before deploying to your chosen\nplatforms. For example, deploying to Netlify is covered within\n[Hono's documentations](https://hono.dev/docs/getting-started/netlify#_4-deploy).\n\nSpecific to deploying the **server** application to vercel, please see [GitHub Discussion #21](https://github.com/nktnet1/rt-stack/discussions/21#discussioncomment-14380642).\n\n### Domain Caveat\n\nWhen deploying your web frontend and server backend to two different\nroot domains, you will need to [tweak your better-auth configurations](https://www.better-auth.com/docs/integrations/hono#cross-domain-cookies).\nApple's Safari browser also does not support third-party cookies (and other browsers will soon follow suit), so auth will\nnot function as expected without any proxy workarounds.\n\nTo keep things simple, it is recommended that you host your frontend and\nbackend on the same root domain and differ by subdomains. For example, the\nfrontend can be served at either `example.com` or `web.example.com`, and the\nbackend hosted at `api.example.com`.\n\n## Other Notes\n\n### Tanstack Router\n\nThe following is configured in [vite.config.ts](apps/web/vite.config.ts) web\napplication:\n\n```ts\nTanStackRouterVite({\n  routeToken: 'layout',\n}),\n```\n\nThis enables the use of a `layout.tsx` file in each directory similar to Next.js.\nYou can read more about this\n[here](https://github.com/TanStack/router/discussions/1102#discussioncomment-10946603).\n\nAlso, it is recommended that you exclude the `routerTree.gen.ts` from your IDE.\nFor example, in VSCode, you can add the following `.vscode/settings.json` at the\nroot of your turborepo:\n\n```json\n{\n  \"files.readonlyInclude\": {\n    \"**/routeTree.gen.ts\": true\n  },\n  \"files.watcherExclude\": {\n    \"**/routeTree.gen.ts\": true\n  },\n  \"search.exclude\": {\n    \"**/routeTree.gen.ts\": true\n  }\n}\n```\n\n### Server API Artificial Delays\n\nThere is an artificial delay added in development mode to simulate API usage in\nreal-world environments. You can disable this by removing the `timingMiddleware`\nin [./packages/api/src/server/orpc.ts](./packages/api/src/server/orpc.ts)\n\n### Environment Variables\n\nThis template was made to follow the recommendation of\n\n- @tyleralbee in [this turborepo's GitHub discussion](https://github.com/vercel/turborepo/discussions/9458#discussioncomment-11443969)\n- @cjkihl in [create-t3-turbo issue #397](https://github.com/t3-oss/create-t3-turbo/issues/397#issuecomment-1630028405)\n- turborepo official docs on [environment variables best practices](https://turbo.build/repo/docs/crafting-your-repository/using-environment-variables#best-practices)\n\nIn using this template, it is recommended that\n\n1. each application has a local `.env` file instead of a global `.env` at the\n   root of your repository\n1. packages should be pure, i.e. rely on factory methods and receiving inputs to\n   instantiate rather than consuming environment variables directly\n   - one exception is the `@repo/db` package, which requires the\n     `DB_POSTGRES_URL` variable for schema migration with `pnpm db:push`\n1. environment variables are prefixed, e.g. `SERVER_AUTH_SECRET` instead of\n   `AUTH_SECRET`. Caching in the app's `turbo.json` can then be configured to\n   use wildcards such as:\n   ```json\n   \"tasks\": {\n      \"build\": {\n        \"env\": [\"SERVER_*\"],\n      }\n    }\n   ```\n\nThere is also a script that creates a `.env` from `.env.example` of each\napp/package, which can be run with:\n\n```bash\n# NOTE: This will not overwrite existing local .env files\npnpm env:copy-example\n\n# To reset any modifications to your .env and restore the examples, run:\npnpm env:remove\npnpm env:copy-example\n```\n\nIt is recommended that any new apps that uses environment variables follow the\nexample script set in [apps/server/package.json](apps/server/package.json).\n\n\u003ch3\u003eExtensions to Existing Template\u003c/h3\u003e\n\u003cp\u003eThe table below demonstrates how you can build and extend upon the existing RT Stack template:\u003c/p\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eFeature\u003c/th\u003e\n      \u003cth\u003eDescription\u003c/th\u003e\n      \u003cth\u003eBranch Link\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eNextJS\u003c/td\u003e\n      \u003ctd\u003eAdds a \u003ccode\u003edocs\u003c/code\u003e application that uses Next.js and Fumadocs, along with the workspace \u003ccode\u003e@repo/ui\u003c/code\u003e package.\u003c/td\u003e\n      \u003ctd\u003e\u003ca href=\"https://github.com/nktnet1/rt-stack/tree/nextjs-fumadocs\"\u003enextjs-fumadocs\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eMulti-language support\u003c/td\u003e\n      \u003ctd\u003eImplements internationalisation support, e.g. switching between English and Vietnamese.\u003c/td\u003e\n      \u003ctd\u003e\u003ca href=\"https://github.com/nktnet1/rt-stack/tree/i18n\"\u003ei18n\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eBetter-auth Plugins\u003c/td\u003e\n      \u003ctd\u003eDemonstrates how to integrate better-auth plugins in a type-safe and CLI-compatible manner.\u003c/td\u003e\n      \u003ctd\u003e\u003ca href=\"https://github.com/nktnet1/rt-stack/tree/better-auth-admin-organization-plugins\"\u003ebetter-auth-admin-organization-plugins\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnktnet1%2Frt-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnktnet1%2Frt-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnktnet1%2Frt-stack/lists"}