{"id":23949814,"url":"https://github.com/ironexdev/ent-stack","last_synced_at":"2025-10-18T06:18:35.459Z","repository":{"id":271156704,"uuid":"898626695","full_name":"ironexdev/ent-stack","owner":"ironexdev","description":"Full-stack TypeScript project starter - Express Next.js TRPC","archived":false,"fork":false,"pushed_at":"2025-02-07T10:28:47.000Z","size":1848,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-29T18:22:56.429Z","etag":null,"topics":["express","monorepo","nextjs","pnpm","starter-kit","trpc","typescript"],"latest_commit_sha":null,"homepage":"https://ent-stack.com","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/ironexdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":"2024-12-04T18:21:58.000Z","updated_at":"2025-02-07T10:28:50.000Z","dependencies_parsed_at":"2025-01-20T20:25:44.302Z","dependency_job_id":"ad0a7b68-7d4f-4047-bc85-c3a0786d21a5","html_url":"https://github.com/ironexdev/ent-stack","commit_stats":null,"previous_names":["ironexdev/ent-stack"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ironexdev%2Fent-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ironexdev%2Fent-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ironexdev%2Fent-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ironexdev%2Fent-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ironexdev","download_url":"https://codeload.github.com/ironexdev/ent-stack/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250316042,"owners_count":21410475,"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":["express","monorepo","nextjs","pnpm","starter-kit","trpc","typescript"],"created_at":"2025-01-06T11:51:37.425Z","updated_at":"2025-10-18T06:18:30.412Z","avatar_url":"https://github.com/ironexdev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ENT Stack\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://github.com/user-attachments/assets/c3c579a8-6ae8-46cf-a854-46d382473dbc\" width=\"350\"\u003e\n\u003c/p\u003e\n\n![ent-title](https://github.com/user-attachments/assets/9b4b4cf5-a2ca-4e9b-b498-3362cc7953b1)\n\n\u003cdiv align=\"center\"\u003e\n  \n[![NPM version][npm-image]][npm-url] [![Setup Guide][setup-guide-image]][setup-guide-url] [![ffn][documentation-image]][documentation-url]\n\n\u003c/div\u003e\n\n## Table of Contents\n\n- [What is the ENT Stack](#table-of-contents)\n- [Features](#features)\n- [Getting Started](#getting-started)\n- [Documentation](#documentation)\n- [Troubleshooting](#troubleshooting)\n\n## What is the ENT Stack?\n\nThe ENT Stack is a full-stack TypeScript project starter that integrates \u003cins\u003e**E**\u003c/ins\u003express 5, \u003cins\u003e**N**\u003c/ins\u003eext.js 15, and \u003cins\u003e**T**\u003c/ins\u003eRPC.\n\nIt allows you to build and **share code** between frontend and backend in a single project while maintaining the flexibility to **host them separately**.\n\n## Features\n\n🌀 **PNPM Workspace - Monorepo**\n\n- The stack uses \u003ca href=\"https://pnpm.io\" target=\"_blank\"\u003ePNPM\u003c/a\u003e Workspace because it's simple and painless to use. With its efficient dependency management and shared package architecture, \u003ca href=\"https://pnpm.io\" target=\"_blank\"\u003ePNPM\u003c/a\u003e ensures faster installs and a clean, modular workflow.\n- Within the monorepo, each top-level folder plays a distinct role:\n  - **apps** folder contains both the backend (`apps/backend`) and frontend (`apps/frontend`) codebases.\n  - **packages** folder contains a `shared` directory (`packages/shared`) that centralizes common configurations, utilities, services type definitions, and translations.\n- To maintain uniform code quality, each of these directories includes an `eslint.config.js` file featuring consistent rules. A root-level `tsconfig.json` provides a base set of TypeScript configurations, while each subproject extends these defaults to meet its own requirements.\n\n🤝 **Type-Safe API Layer**\n\n- The stack leverages \u003ca href=\"https://trpc.io\" target=\"_blank\"\u003eTRPC\u003c/a\u003e to create a type-safe bridge between the frontend and backend. This ensures that your IDE automatically provides type hints and autocompletion for API endpoints, eliminating the need for manual type definitions.\n\n⚙️ **Environment and Configuration**\n\n- Leverages \u003ca href=\"https://env.t3.gg\" target=\"_blank\"\u003eT3 Env\u003c/a\u003e type-safe environment variables validation in both backend and frontend\n- Contains Shared configuration file `shared-config.ts` that is extended by both Backend `backend-config.ts` and Frontend `frontend-config.ts` files for feature-focused settings\n\n🛢️ **Database**\n\n- The backend uses \u003ca href=\"https://orm.drizzle.team/\" target=\"_blank\"\u003eDrizzle ORM\u003c/a\u003e for interacting with a \u003ca href=\"https://www.mysql.com\" target=\"_blank\"\u003eMySQL\u003c/a\u003e database, providing a type-safe and developer-friendly API.\n- It also contains \u003ca href=\"https://docs.docker.com/reference/cli/docker/#option-types\" target=\"_blank\"\u003eDocker\u003c/a\u003e Image and a script `bin/docker/run-local-db.sh` to run the database locally.\n\n🔒 **Authentication and Authorization**\n\n- The stack provides passwordless registration and login through short verification PINs, secure JWT access tokens, and UUID-based refresh tokens. Additionally, frontend routes can be marked as protected in `routes.ts`, restricting them to authenticated users - this is evaluated in `middleware.ts`.\n\n🪲 **Validation and Error Handling**\n\n- The stack uses \u003ca href=\"https://zod.dev\" target=\"_blank\"\u003eZod\u003c/a\u003e for consistent input validation across the frontend and backend, integrated with \u003ca href=\"https://trpc.io\" target=\"_blank\"\u003eTRPC\u003c/a\u003e for type-safe error management.\n- Input is sanitized to prevent injection attacks.\n- Errors are categorized into client, server, and userland types for precise handling.\n- \u003ca href=\"https://tanstack.com/query/v5/docs/framework/react/overview\" target=\"_blank\"\u003eTanstack Query\u003c/a\u003e handles errors through a custom handler with callbacks for server, client, and userland errors.\n\n🔄 **State Management**\n\n- Uses \u003ca href=\"https://zustand-demo.pmnd.rs\" target=\"_blank\"\u003eZustand\u003c/a\u003e for lightweight, synchronous global state management, delivering a minimal overhead approach for storing and controlling shared data across the application.\n- Uses \u003ca href=\"https://tanstack.com/query/latest\" target=\"_blank\"\u003eTanstack Query\u003c/a\u003e for asynchronous data fetching and caching, providing an SSR-friendly solution that keeps the UI and server in sync.\n\n🌐 **Internationalization (i18n) and Localization**\n\n- A custom, lightweight solution handles localization using standalone functions that use \u003ca href=\"https://unicode-org.github.io/icu/userguide/format_parse/messages\" target=\"_blank\"\u003eICU message syntax\u003c/a\u003e.\n- Translation functions can be used anywhere in the stack (both backend and frontend).\n- The stack includes two scripts for message import (`pnpm import-messages`) and export (`pnpm export-messages`)\n- Frontend routes are fully translatable, defined in standalone .ts file, and dynamically evaluated at runtime through \u003ca href=\"https://nextjs.org\" target=\"_blank\"\u003eNext.js\u003c/a\u003e middleware.\n\n🪵 **Logging**\n\n- The stack employs \u003ca href=\"https://getpino.io\" target=\"_blank\"\u003ePino\u003c/a\u003e for lightweight and efficient logging across both backend and frontend. Its simple API and minimal overhead ensure clear, structured logs without impacting performance.\n\n✉️ **Mailing**\n\n- integrates \u003ca href=\"https://resend.com\" target=\"_blank\"\u003eResend\u003c/a\u003e for developer friendly e-mail sending.\n- Backend also contains email test router for email previews and testing.\n- Email templates are written in \u003ca href=\"https://handlebarsjs.com\" target=\"_blank\"\u003eHandlebars\u003c/a\u003e.\n\n🤖 **Testing**\n\n- The stack uses \u003ca href=\"https://playwright.dev\" target=\"_blank\"\u003ePlaywright\u003c/a\u003e for unified frontend and backend testing, ensuring consistency and reliability.\n- \u003ca href=\"https://malslurp.dev\" target=\"_blank\"\u003eMailslurp\u003c/a\u003e is used for receiving e-mails in tests.\n\n🐳 **DevOPS - Infrastructure and CI/CD**\n\n- Example Infrastructure and CI/CD for the ENT Stack is in a \u003ca href=\"https://github.com/ironexdev/ent-stack-devops\" target=\"_blank\"\u003eseparate repository\u003c/a\u003e.\n## Getting Started\n\nGet up and running with the \u003ca href=\"https://ent-stack.com\" target=\"_blank\"\u003eENT Stack\u003c/a\u003e in just two steps:\n\n**Prerequisites**\n- \u003ca href=\"https://nodejs.org\" target=\"_blank\"\u003eNode.js\u003c/a\u003e\n- \u003ca href=\"https://pnpm.io\" target=\"_blank\"\u003ePNPM\u003c/a\u003e\n- \u003ca href=\"https://docs.docker.com/reference/cli/docker/#option-types\" target=\"_blank\"\u003eDocker CLI\u003c/a\u003e (for local MySQL database)\n- A Unix-like shell environment (e.g., Bash, Zsh)\n\n💡 \u003ca href=\"https://ent-stack.com/ent-stack/setup/#-how-to-install-prerequisites-on-ubuntu-24\" target=\"_blank\"\u003eHow to install prerequisites on Ubuntu 24\u003c/a\u003e\n\n### 1/ 🚀 Create your project\n\n```bash\npnpm create ent-stack@latest\n```\n- Creates a new project (folder) based on specific version of this repository.\n- The version used is specified in the description of the \u003ca href=\"https://www.npmjs.com/package/create-ent-stack\" target=\"_blank\"\u003enpm package\u003c/a\u003e.\n\n### 2/ 🔥 Setup\n\n```bash\npnpm fire\n```\n- Installs dependencies\n- Starts the local database in a Docker container\n- Creates the database and tables\n- Runs dev environments for both the backend and frontend\n\nAt this point, your application should be up and running locally. But to enable email sending and testing, you need to follow the final step below.\n\n### 3/ 🧪 Configure Mailing and Run Tests\n\nTo enable mailing, you need to do the following:\n- **[Sign up for a free Resend account](https://resend.com/signup)** and set **SERVICE_EMAIL**, **SECURITY_EMAIL** and **RESEND_API_KEY** in `apps/backend/.env`\n  - Serves as a service for sending e-mails\n\u003ctable align=\"center\" width=\"100%\"\u003e\n  \u003ctr\u003e\n    \u003ctd width=\"50%\"\u003e\n      \u003cimg src=\"https://github.com/user-attachments/assets/57bc026b-dc0b-4c88-abc6-d4006b9ff8ae\" alt=\"Resend domain\" width=\"100%\"\u003e\n    \u003c/td\u003e\n    \u003ctd width=\"50%\"\u003e\n      \u003cimg src=\"https://github.com/user-attachments/assets/3b7975a9-8749-4729-97a5-efb136ad3622\" alt=\"Resend API Key\" width=\"100%\"\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n- **[Sign up for a free MailSlurp account](https://app.mailslurp.com/sign-up)** and set **MAILSLURP_INBOX_ID** and **MAILSLURP_EMAIL** in `apps/backend/.env`\n  - Serves as a service for receiving e-mails (for testing purposes)\n\u003ctable align=\"center\" width=\"100%\"\u003e\n  \u003ctr\u003e\n    \u003ctd width=\"50%\"\u003e\n      \u003cimg src=\"https://github.com/user-attachments/assets/41affe10-ad42-4d89-a2b3-f69dd8597997\" alt=\"MailSlurp inbox and inbox id\" width=\"100%\"\u003e\n    \u003c/td\u003e\n    \u003ctd width=\"50%\"\u003e\n      \u003cimg src=\"https://github.com/user-attachments/assets/60f53cd3-bede-4fb0-9175-7be92955a153\" alt=\"MailSlurp API Key\" width=\"100%\"\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e \n\nAfter that, make sure to **restart dev** environment, and then you can run the tests by executing the following commands:\n- Test Backend\n```bash\npnpm backend:test\n```\n- Test Frontend\n```bash\npnpm frontend:test\n```\n\nHere is the list of values that **MUST BE THE SAME** in both backend and frontend **.env** files:\n\n| Backend       | Frontend                  |\n|---------------|---------------------------|\n| SITE_NAME     | NEXT_PUBLIC_SITE_NAME     |\n| COOKIE_DOMAIN | NEXT_PUBLIC_COOKIE_DOMAIN |\n| BACKEND_URL   | NEXT_PUBLIC_BACKEND_URL   |\n| FRONTEND_URL  | NEXT_PUBLIC_FRONTEND_URL  |\n| JWT_SECRET    | JWT_SECRET                |\n\n## Documentation\n\nFor information about ENT Stack features go to the 📄 [Documentation](https://ent-stack.com/ent-stack/documentation/)\n\n## Troubleshooting\n\n1/ **IDE issues**\n```\n- Node interpreter is not set\n- Eslint/Prettier is not working on save\n- TypeScript highlights non-existent errors\n```\n- These issues can occur if your IDE is not properly configured. For reference, I'm attaching my PHPStorm (WebStorm) configuration on WSL2 with Ubuntu, showing the settings for ESLint, Prettier, and Node.js.:\n\u003ctable align=\"center\"\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://github.com/user-attachments/assets/6b509924-f8a7-4ec3-b569-721784527fc8\" width=\"250\" alt=\"Eslint Settings\"/\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"https://github.com/user-attachments/assets/2d60cea8-f295-4667-a0d8-7553dd863070\" width=\"250\" alt=\"Prettier Settings\" /\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\u003cimg src=\"https://github.com/user-attachments/assets/0e42aa53-f420-42ad-85ab-e61881ccc2e9\" width=\"250\" alt=\"Node.js Settings\"/\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n2/ **MySQL container name conflict**\n```\ndocker: Error response from daemon: Conflict. The container name \"/mysql\" is already in use by container\n```\n- Remove the existing container by running `docker rm mysql`\n- Or for more nuclear solution, run `bin/docker/cleanup.sh`\n  - this script forcefully cleans up Docker by removing all build caches, containers, images, and unused networks to free disk space and reset the environment.\n\n[npm-url]: https://www.npmjs.com/package/create-ent-stack\n[npm-image]: https://img.shields.io/npm/v/create-ent-stack?color=b45bf5\u0026logoColor=0b7285\n\n[setup-guide-url]: https://ent-stack.com/ent-stack/setup/\n[setup-guide-image]: https://img.shields.io/badge/setup_guide-726fff\n\n[documentation-url]: https://ent-stack.com/ent-stack/documentation\n[documentation-image]: https://img.shields.io/badge/documentation-726fff\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fironexdev%2Fent-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fironexdev%2Fent-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fironexdev%2Fent-stack/lists"}