{"id":27559160,"url":"https://github.com/kasper573/yas","last_synced_at":"2025-09-03T20:33:58.960Z","repository":{"id":183103296,"uuid":"657346228","full_name":"kasper573/yas","owner":"kasper573","description":"A Typescript \u0026 React full stack monorepo template","archived":false,"fork":false,"pushed_at":"2024-07-04T08:30:54.000Z","size":6599,"stargazers_count":30,"open_issues_count":17,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-12T17:08:30.797Z","etag":null,"topics":["javascript","monorepo","react","template","turborepo","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kasper573.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2023-06-22T21:35:32.000Z","updated_at":"2024-11-25T11:13:35.000Z","dependencies_parsed_at":"2024-02-03T19:29:31.885Z","dependency_job_id":"2faed0d9-d649-4202-9b0b-7decb7020a17","html_url":"https://github.com/kasper573/yas","commit_stats":{"total_commits":1367,"total_committers":5,"mean_commits":273.4,"dds":0.24067300658376,"last_synced_commit":"984354f3aecb9bdd287b24a5481a131bae8800c8"},"previous_names":["ksandin/yas"],"tags_count":64,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kasper573%2Fyas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kasper573%2Fyas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kasper573%2Fyas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kasper573%2Fyas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kasper573","download_url":"https://codeload.github.com/kasper573/yas/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249750761,"owners_count":21320203,"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":["javascript","monorepo","react","template","turborepo","typescript"],"created_at":"2025-04-19T23:34:24.076Z","updated_at":"2025-04-19T23:34:27.786Z","avatar_url":"https://github.com/kasper573.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Yet Another Stack \u0026middot; [![status](https://github.com/kasper573/yas/actions/workflows/build_and_test.yml/badge.svg)](https://github.com/kasper573/yas/actions)\n\nA Typescript \u0026 React specific full stack monorepo template for large scale web development with heavy focus on type safety and strict architecture without sacrificing developer experience.\n\n\u003e Also serves as an [incubation](#incubations) repository for experimenting with new ideas and technologies.\n\n## Notable feature highlights\n\n1. Shows how to roll your own [framework agnostic design system](libraries/design-tokens), with separate platform integrations like a [web based ui component library](libraries/ui) or a [PDF renderer](libraries/pdf), both based on the same design system but not limited by each others concerns. This is an extensible pattern that be continued to i.e. implement consistent design system bindings for react-native, webgl, email rendering, or anything really.\n\n2. Shows how organize and separate concerns among a multitude of packages in a monorepo, i.e. by enforcing a [layered architecture](#layered-architecture) using [dependency-cruiser](https://www.npmjs.com/package/dependency-cruiser), and shows several examples on modularization: above mentioned design system, and both a tRPC and GraphQL server divided into separate [server](apps/graphql-server), [client](integrations/graphql-client) and UI packages.\n\n3. Superb developer experience with fast and reliable tooling with respect our human limitations: The compiler and editor should do the heavy lifting, and while memorizing conventions is important, you should be allowed to forget and be reminded by the tools when you make a mistake, without any exceptions. The philosophy is that you should just clone this repository and start coding, and the tools will guide you to the right path.\n\n## Stack\n\nHere's a quick overview of the most notable tools and libraries used in this stack. A lot of them are encapsulated in their own packages, so make sure you check out each package's documentation for more information.\n\n### Tools\n\n- [pnpm](https://pnpm.io/) for package management.\n- [turborepo](https://turbo.build/repo) for monorepo management.\n- [Vite](https://vitejs.dev/) for bundling and development server.\n- [Vitest](https://vitest.dev/) for unit testing.\n- [Storybook](https://storybook.js.org/) for component development and testing\n- [Playwright](https://playwright.dev/) for end-to-end testing.\n- [ESLint](https://eslint.org/) for code linting.\n- [Prettier](https://prettier.io/) for code formatting.\n\n### Notable libraries\n\n- [Vanilla Extract](https://vanilla-extract.style/) for styling.\n- [tRPC](https://trpc.io/) for API server and client.\n- [GraphQL](https://graphql.org/) for API server and client.\n- [Radix UI](https://www.radix-ui.com/) for component primitives.\n- [Tanstack Query](https://tanstack.com/query) wrapper around both GraphQL \u0026 tRPC for a unified data fetching interface.\n- [Tanstack Router](https://tanstack.com/router) for routing.\n- [react-hook-form](https://react-hook-form.com/) for form state management.\n- [zod](https://github.com/colinhacks/zod) for runtime type validation.\n- [date-fns](https://date-fns.org/) for date manipulation.\n- [react-pdf](https://react-pdf.org/) for PDF generation.\n\n### Pipeline\n\nThere's also a robust CI/CD pipeline set up for this repository, which includes:\n\n- Conventional commits\n- Code quality checks\n- Build and test automation with artifacts\n\n### Deployment\n\nThis repository is designed to be agnostic to deployment strategy and hosting platform, so it contains no deployment scripts or major host specific details and instead relies on a deployable artifacts convention.\n\nEach app or package that aims to be deployed has a `build` script that will produce its depoyable artifact according to that particular app or package's framework, and expects you to configure the deployment process either yourself after forking this repository, or by using a pull based deployment platform like Vercel, Netlify, or AWS Amplify.\n\nTo ensure deployment compatibility, this repository is dogfooding above mentioned process by deploying all the apps in the `apps` directory to Vercel on a pull based deployment model.\n\n## Quick start\n\n- Clone this repository\n- Run `pnpm install`\n- Run `pnpm dev` to start all development servers. Links to all apps will be displayed in the terminal.\n\n## Conventions\n\n- The repository root is reserved for global configuration files. Use workspaces for everything else.\n- Keep packages small and focused.\n- Decouple your packages.\n- Each package should be prebuilt with `tsc` (Exceptions can be made, see [layered archiveture](#layered-architecture) below)\n- Utilize shared configuration (i.e. [@yas/tsconfig](core/tsconfig), [@yas/env](core/env), [@yas/test](core/test)).\n- Encapsulate packages (i.e. [@yas/style](libraries/style), [@yas/query-client](integrations/query-client), [@yas/validate](libraries/validate)).\n- Each non-trivial package should provide its own documentation.\n- Enforce conventions: use i.e. eslint, prettier, or [custom scripts](core/scripts) (see rant blow).\n\n### A rant on enforcing conventions\n\n\u003cdetails\u003e\n\u003csummary\u003eRead the rant\u003c/summary\u003e\n\nI am a firm believer that a convention that is not enforced quickly becomes nothing more but a suggestion.\n\n**And the best way to enforce a convention is to automate it.**\n\nWhile the industry has adopted tools like `eslint` and `prettier` to automatically enforce certain conventions with great success,\nthere's still too many conventions being handwaved \"oh, we'll deal with that in code review\",\nonly to be forgotten, or done poorly. We are forgetful, inconsistent and biased. Relying on people to enforce conventions can quickly become an aggravating waste of time and energy.\n\nWays of how people can fail to follow conventions include (but are not limited to):\n\n- The convention wasn't documented.\n- The documentation was outdated.\n- People didn't read the documentation.\n- People forgot about the convention.\n- People didn't care about the convention.\n- People didn't understand the convention.\n- People didn't have time to enforce the convention.\n\nHere's my workflow on how to turn a convention into something that can be automated:\n\n1. If your convention doesn't exist as an eslint rule: write one!\n2. If eslint is not applicable, use another linting tool, like [stylelint](https://stylelint.io/) or [dependency-cruiser](https://www.npmjs.com/package/dependency-cruiser).\n3. If there is no linting tool for your convention, write a [custom script](core/scripts)!\n4. If the convention simply cannot be automated, then try to change it into something that can be. Often you can make a compromise for the sake of consistency, but still provide similar value.\n5. If it truly is impossible to automate, at this point it's time to ask yourself how useful this convention really is. The inability to systematically enforce a software convention is in of itself often a sign that the convention is flawed. Not always, but it may very well be a red flag. You've got two options here:\n   - Change the system itself so that the convention is no longer needed or can be automated.\n   - Drop the convention and acknowledge that it's a suggestion, not a rule.\n\n\u003c/details\u003e\n\n## Root-level only scripts\n\nThe following scripts are only available in the root of the repository but will apply to the entire codebase:\n\n- `lint` Checks for code style errors.\n- `lint:fix` Fixes code style errors (where possible)\n- `format` Formats code.\n- `format:fix` Formats code and fixes code style errors (where possible)\n\n## Package scripts\n\nThese scripts are part of a convention. Individual packages may have their own scripts that are not listed here that may do other things, but these are the ones that are expected to be consistent across all packages. Packages may opt in to have the following scripts:\n\n- `dev` Starts any and all tools required during development in watch mode (i.e. a development webserver, or code generators, etc.). If applicable, should display URL to app in terminal.\n- `build` Builds the app or package into a deployable artifact according to the package's framework.\n- `test` Runs the test runner in headless mode, once.\n- `test:watch` Starts the test runner in watch mode for development.\n\n**Each script must exit with a non-zero exit code if they fail.**\n\nThe root package have these scripts defined as well and is configured to automatically run these scripts for all packages in the repository, which will be your primary way of interacting with these scripts, but you can also run them manually in a package if you need to.\n\n## Packages\n\nPackages should follow these naming conventions:\n\n- package.json name must have `@yas/` prefix\n\nExceptions apply:\n\n- Incubation packages should be named whatever they plan to register as on npm.\n- Packages that must follow a 3rd party naming convention (i.e. `eslint-*`).\n\n## Layered architecture\n\nPackage workspace folders are used as categories that represent architectural layers imposing this rule:\n\n**Lower layers should not depend on higher layers**.\n\n\u003e This is enforced using [dependency-cruiser](https://www.npmjs.com/package/dependency-cruiser)\n\nThese are the layers, from top to bottom:\n\n#### [apps](apps)\n\nDeployables (`build` script must output deployable artifacts, preferably using some standard)\n\n\u003e Since apps may use any framework, they will have their own build/dev scripts, so you don't have to use `tsc` for apps.\n\n#### [integrations](libraries)\n\nIntegrations with services (i.e. api clients).\n\n#### [libraries](libraries)\n\nBuilding blocks for creating apps.\n\n#### [core](core)\n\nLow level tooling for building apps and libraries. Should mostly be out of your way and not something you interact with directly.\n\n\u003e Most of core packages are shared configs and developer tooling and provide little to no runtime code. These packages may therefore skip prebuilding with `tsc`, since that is a performance optimization primarily intended for runtime code.\n\n#### [incubations](incubations)\n\nExperimental packages. If they become stable, they will be extracted into their own repository. Ideally, this folder should be empty.\n\n\u003e Note: I may be experimenting with some technologies of my own in this repository. The incubation packages that reside in the repository are not considered part of the template and may or may not be stable or production ready. These are my personal experiments, and while I believe in them, they may fail. If I decide to remove them, I will refactor the places they are used in the repository to use a 3rd party equivalent instead.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkasper573%2Fyas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkasper573%2Fyas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkasper573%2Fyas/lists"}