{"id":16925067,"url":"https://github.com/hiroppy/web-app-template","last_synced_at":"2025-04-05T15:03:23.846Z","repository":{"id":222497459,"uuid":"757451156","full_name":"hiroppy/web-app-template","owner":"hiroppy","description":"A minimal web service template 🎃  \"npx create-app-foundation@latest\" !","archived":false,"fork":false,"pushed_at":"2025-03-31T13:58:44.000Z","size":4985,"stargazers_count":138,"open_issues_count":3,"forks_count":9,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-31T14:57:48.137Z","etag":null,"topics":["next","next-auth","nextjs-template","opentelemetry","prisma-orm","react-hook-form","scaffolded","stripe","taiwindcss","templates","typescript"],"latest_commit_sha":null,"homepage":"https://hiroppy.github.io/web-app-template/","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/hiroppy.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":"2024-02-14T14:22:06.000Z","updated_at":"2025-03-31T13:58:47.000Z","dependencies_parsed_at":"2024-04-21T11:36:22.423Z","dependency_job_id":"848240bf-ae69-4f0e-a1c9-098137210533","html_url":"https://github.com/hiroppy/web-app-template","commit_stats":{"total_commits":390,"total_committers":2,"mean_commits":195.0,"dds":"0.16410256410256407","last_synced_commit":"2153b82674698cbcfeb0d760f85c81f374b1553a"},"previous_names":["hiroppy/web-app-template"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiroppy%2Fweb-app-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiroppy%2Fweb-app-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiroppy%2Fweb-app-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiroppy%2Fweb-app-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hiroppy","download_url":"https://codeload.github.com/hiroppy/web-app-template/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247353729,"owners_count":20925329,"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":["next","next-auth","nextjs-template","opentelemetry","prisma-orm","react-hook-form","scaffolded","stripe","taiwindcss","templates","typescript"],"created_at":"2024-10-13T20:08:46.292Z","updated_at":"2025-04-05T15:03:23.813Z","avatar_url":"https://github.com/hiroppy.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003c!-- 👉 remove --\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003e️️A minimal template for web app 🎃\u003c/h1\u003e\n  \u003cimg src=\".internal/site/src/public/images/icon.png\" alt=\"icon\" width=\"120\"\u003e\n  \u003cp\u003eFrom Zero to Service, Build with Best Practices, Minimal Code, and Essential Tools\u003c/p\u003e\n  \u003cbr /\u003e\n  \u003ca href=\"https://hiroppy.github.io/web-app-template/\"target=\"_blank\" \u003e📜 Read The Docs 📜\u003c/a\u003e\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n\u003c/div\u003e\n\nInstalling this template automatically sets up the following libraries/tools. By saving you significant effort, it allows you to focus entirely on writing your product code.🤗\n\n|             |                                                                                                                                            |                                                                                                                                                      |                                                                                                                                       |                                                                                                                                                     |\n| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **App**     | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/nextjs.png\" alt=\"nextjs\" width=\"44\"\u003e\u003cbr\u003eNext.js\u003c/div\u003e                  | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/tailwind.png\" alt=\"tailwind\" width=\"44\"\u003e\u003cbr\u003eTailwind CSS\u003c/div\u003e                   | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/next-auth.png\" alt=\"next-auth\" width=\"44\"\u003e\u003cbr\u003eNextAuth.js\u003c/div\u003e   | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/react-hook-form.png\" alt=\"react-hook-form\" width=\"44\"\u003e\u003cbr\u003eReact Hook Form\u003c/div\u003e |\n|             | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/zod.svg\" alt=\"zod\" width=\"44\"\u003e\u003cbr\u003eZod \u003c/div\u003e                           | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/otel.png\" alt=\"otel\" width=\"44\"\u003e\u003cbr\u003eOpenTelemetry\u003c/div\u003e                          | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/prisma.png\" alt=\"prisma\" width=\"44\"\u003e\u003cbr\u003ePrisma\u003c/div\u003e              | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/postgresql.png\" alt=\"postgresql\" width=\"44\"\u003e\u003cbr\u003ePostgreSQL\u003c/div\u003e                |\n|             | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/stripe.png\" alt=\"stripe\" width=\"44\"\u003e\u003cbr\u003eStripe\u003c/div\u003e                   |                                                                                                                                                      |                                                                                                                                       |\n|             |                                                                                                                                            |                                                                                                                                                      |                                                                                                                                       |\n| **Tools**   | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/typescript.png\" alt=\"typescirpt\" width=\"44\"\u003e\u003cbr\u003eTypeScript\u003c/div\u003e       | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/pnpm.svg\" alt=\"pnpm\" width=\"44\"\u003e\u003cbr\u003epnpm\u003c/div\u003e                                   | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/biome.png\" alt=\"biome\" width=\"44\"\u003e\u003cbr\u003eBiome \u003c/div\u003e                | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/prettier.png\" alt=\"prettier\" width=\"44\"\u003e\u003cbr\u003e Prettier\u003c/div\u003e                     |\n|             | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/knip.png\" alt=\"knip\" width=\"44\"\u003e\u003cbr\u003eKnip\u003c/div\u003e                         | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/editorconfig.png\" alt=\"editorconfig\" width=\"44\"\u003e\u003cbr\u003e EditorConfig \u003c/div\u003e         | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/lefthook.png\" alt=\"lefthook\" width=\"44\"\u003e\u003cbr\u003e lefthook\u003c/div\u003e       | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/docker.png\" alt=\"docker\" width=\"44\"\u003e\u003cbr\u003e Docker \u003c/div\u003e                          |\n|             |                                                                                                                                            |                                                                                                                                                      |                                                                                                                                       |\n| **Testing** | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/vitest.png\" alt=\"vitest\" width=\"44\"\u003e\u003cbr\u003e Vitest\u003c/div\u003e                  | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/testing-library.png\" alt=\"testing-library\" width=\"44\"\u003e\u003cbr\u003e Testing Library\u003c/div\u003e | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/playwright.png\" alt=\"playwright\" width=\"44\"\u003e\u003cbr\u003e Playwright\u003c/div\u003e | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/testcontainers.png\" alt=\"testcontainers\" width=\"44\"\u003e\u003cbr\u003e Testcontainers\u003c/div\u003e   |\n|             |                                                                                                                                            |                                                                                                                                                      |\n| **Others**  | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/github-actions.png\" alt=\"actions\" width=\"44\"\u003e\u003cbr\u003e GitHub Actions\u003c/div\u003e | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/renovate.png\" alt=\"renovate\" width=\"44\"\u003e\u003cbr\u003e Renovate\u003c/div\u003e                      | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/vscode.png\" alt=\"vscode\" width=\"44\"\u003e\u003cbr\u003e VSCode\u003c/div\u003e             | \u003cdiv align=\"center\"\u003e\u003cimg src=\".internal/site/src/public/images/libs/copilot.png\" alt=\"copilot edits\" width=\"44\"\u003e\u003cbr\u003e Copilot Edits\u003c/div\u003e            |\n\nPlease read the features provided by this template first! 👉\n[Challenges Solved](https://hiroppy.github.io/web-app-template/introduction/challenges-solved.html)\n\n## Prerequisites\n\n- Node.js v20 or higher\n- [Docker](https://docs.docker.com/engine/install/)\n\n## Installation\n\nWhen installing the repository, you can skip the setup section, as the init script will do the equivalent of setup.\n\n### Using CLI (recommended)\n\n```sh\n$ npx create-app-foundation@latest\n```\n\nThe CLI creates a project directory and run internal/init script so it's easy to get started.\n\n### Using GitHub Template\n\nThis repo is a GitHub template, so click the [\"Use this template\"](https://github.com/new?template_owner=hiroppy\u0026template_name=web-app-template) button to create your repo. Then, you need to execute the below to finish setting it up.\n\n```sh\n$ node .internal/setup/init.mjs\n```\n\n### Opt-out\n\nThe following items will be asked whether they are required when the project is initialized:\n\n- Sample Application Code\n- Dockerfile\n- E2E Testing\n- Observability feature\n- Stripe\n\n\u003c!-- ######## --\u003e\n\n## Setup\n\n```sh\n# enable corepack\n$ npm run setup\n# install deps\n$ pnpm i\n# create \".env\" and modify environment variables\n$ cp .env.sample .env\n```\n\n## Development\n\n```sh\n$ pnpm dev\n```\n\n\u003c!-- start: stripe --\u003e\n\n### Debugging Stripe\n\n1. Create a subscription [here](https://dashboard.stripe.com/test/products?active=true\u0026create=product\u0026source=product_list) and get `price_id`.\n\n2. Modify the environment variables. The test API key is [here](https://dashboard.stripe.com/test/apikeys).\n\n```\nSTRIPE_SECRET_KEY=\nSTRIPE_WEBHOOK_SECRET=\nSTRIPE_PRICE_ID=\n```\n\n3. [Install stripe CLI](https://docs.stripe.com/stripe-cli) to bypass the webhook.\n\n4. Execute the following command in another terminal.\n\n```sh\n$ stripe listen --forward-to localhost:3000/api/payment/webhook\n```\n\n5. After signing in, you can go to the `http://localhost:3000/me/payment` page to see how to make a payment.\n\n\u003c!-- end: stripe --\u003e\n\n## Production\n\n```sh\n$ pnpm db:up\n$ pnpm build\n$ pnpm start\n```\n\n\u003c!-- start: otel --\u003e\n\n### Observability\n\nThis template uses Jaeger as a tracing platform. The local environment doesn't require `TRACE_EXPORTER_URL` environment value.\n\n```sh\n# open Jaeger\n$ open http://localhost:16686/\n```\n\n\u003c!-- end: otel --\u003e\n\n## Test\n\n### Unit Test\n\n```sh\n$ pnpm test\n$ pnpm test:watch\n```\n\n\u003c!-- start: e2e --\u003e\n\n### E2E Test\n\nA build task must be executed before running tests to bypass JWT logic.\n\n```sh\n# install chrome\n$ pnpm exec playwright install chrome\n# build using test environments since it needs to change encode/decode functions of next-auth\n$ pnpm build:test\n\n$ pnpm test:e2e\n$ pnpm test:e2e:ui\n```\n\n\u003c!-- end: e2e --\u003e\n\n## Database\n\n```sh\n$ pnpm db:migrate\n$ pnpm db:reset\n# view the database items\n$ pnpm db:studio\n```\n\n## Links\n\n- [Database ER diagram](/prisma/schema/ERD.md)\n- [Web App Template](https://hiroppy.github.io/web-app-template/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhiroppy%2Fweb-app-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhiroppy%2Fweb-app-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhiroppy%2Fweb-app-template/lists"}