{"id":30918842,"url":"https://github.com/imjuni/nextjs-boilerplate","last_synced_at":"2025-09-10T00:29:39.259Z","repository":{"id":308017081,"uuid":"1031371379","full_name":"imjuni/nextjs-boilerplate","owner":"imjuni","description":null,"archived":false,"fork":false,"pushed_at":"2025-08-24T05:25:30.000Z","size":279,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-29T08:39:38.476Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/imjuni.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,"zenodo":null}},"created_at":"2025-08-03T15:46:49.000Z","updated_at":"2025-08-24T05:25:34.000Z","dependencies_parsed_at":"2025-08-03T17:34:51.589Z","dependency_job_id":"910ca388-2d4a-4bdb-87a5-cd04e58971e7","html_url":"https://github.com/imjuni/nextjs-boilerplate","commit_stats":null,"previous_names":["imjuni/nextjs-boilerplate"],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/imjuni/nextjs-boilerplate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imjuni%2Fnextjs-boilerplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imjuni%2Fnextjs-boilerplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imjuni%2Fnextjs-boilerplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imjuni%2Fnextjs-boilerplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imjuni","download_url":"https://codeload.github.com/imjuni/nextjs-boilerplate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imjuni%2Fnextjs-boilerplate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274390643,"owners_count":25276406,"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","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2025-09-10T00:29:38.287Z","updated_at":"2025-09-10T00:29:39.251Z","avatar_url":"https://github.com/imjuni.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Next.js Boilerplate\n\nModern Next.js Boilerplate\n\n## Todo\n\n- [x] i18n\n  - 현재 사용 기준을 보면 cookie, without url\n- [x] API client (axios, ky, fetch)\n  - jin-frame + axios\n~~ - [ ] SWR ~~\n  ~~ - data fetch 이 후 zustand까지 자연스럽게 바인딩 ~~\n  ~~ - 필요한 경우 데이터 바인딩 이 후 reflow까지 ~~\n- [x] prettier\n- [x] zustand\n- [x] react-hook-form\n- [x] zod\n- [x] shadcn\n- [ ] git hook (husky)\n- [x] tailwindCSS \u0026 custom css\n- [x] eslint v9 (with airbnb)\n- [x] eslint + lint-stage\n- [x] vitest - unit test\n- [ ] vitest - unit test with zustand\n- [ ] playwright - e2e test\n\n## SWR\n\n데이터 fetch에 SWR을 쓰려고 했다. 캐시도 잘되고 편리해보여서. 근데 SWR은 Hook으로 설계가 되어서 react-hook-form 처럼 자체적으로 store를 제공하는 경우 연동에 불편함이 있고 컴포넌트가 렌더링 될 때 useState처럼 사용해야 하기 때문에 미묘하게 사용하기 편해보이지 않았다. zustand가 data-fetch를 하는 부분을 추가한 느낌인데 이 것이 그리 편리해보이지 않았다.\n\n```ts\n  const form = useForm\u003cTForm\u003e({\n    defaultValues: {\n      name: '',\n    },\n    resolver: zodResolver(schema),\n  });\n\n  // data는 처음 렌더링 될 때는 undefined 값이고, error, isMutating도 마찬가지이다\n  const { trigger, data, error, isMutating } = useSWRMutation(\n    PokemonFrame.getEndpoint().pathname,\n    async () =\u003e {\n      const frame = PokemonFrame.of((b) =\u003e\n        // 여기에서 react-hook-form의 값을 가져와서 바인딩 한다\n        b.from({ name: form.getValues().name }),\n      );\n      return frame.execute();\n    },\n  );\n\n  const onSubmit: SubmitHandler\u003cTForm\u003e = async () =\u003e {\n    // submit이 되었을 때 trigger를 호출해서 useSWRMutation에서 결과 값으로 받은 data 객체에 바인딩을 시도한다. \n    await trigger();\n\n    // trigger는 비동기 함수 이지만 await 이 후 data 값이 반드시 바인딩 되는 것은 아니다.\n    // data 값은 state라서 자연스럽게 데이터가 채워지고, 채워진 데이터를 렌더링 하면 된다\n    console.log(data, error, isMutating);\n  };\n```\n\n일단 데이터가 바인딩 되는 시점을 명확하게 알 수 없는 것이 좀 불편했다. 그리고 뭔가 미묘하다고 생각한 점은 data를 읽은 이 후 재가공을 하거나, 결과에 맞춰서 전체 컴포넌트의 상태를 바꿀 때 복잡한 비즈니스 로직을 수행해야 할 수 있는데 바인딩만 하는 것이 미묘했다. 그래도 짧은 시간에 jotai보다 더 인기 있는 프레임워크가 된 것은 신기하기도 하고, 또 굉장히 잘 관리되고 있어서 발전 가능성도 높다고 생각한다. 변경이 많이 필요한 경우가 아니라면 정말 유용하게 쓸 수 있을 것이라고 생각한다.\n\n## Getting Started\n\nFirst, run the development server:\n\n```bash\nnpm run dev\n# or\nyarn dev\n# or\npnpm dev\n# or\nbun dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\nYou can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.\n\nThis project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.\n\n## Learn More\n\nTo learn more about Next.js, take a look at the following resources:\n\n- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.\n- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.\n\nYou can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!\n\n## Deploy on Vercel\n\nThe easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template\u0026filter=next.js\u0026utm_source=create-next-app\u0026utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimjuni%2Fnextjs-boilerplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimjuni%2Fnextjs-boilerplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimjuni%2Fnextjs-boilerplate/lists"}