{"id":17967376,"url":"https://github.com/peteryangio/rsc-and-csharp","last_synced_at":"2025-06-25T00:33:34.844Z","repository":{"id":62853038,"uuid":"561199288","full_name":"PeterYangIO/rsc-and-csharp","owner":"PeterYangIO","description":"React Server Components connected to a C# dotnet backend with automatically generated TypeScript clients using Swagger. All connected with docker for development and deployment!","archived":false,"fork":false,"pushed_at":"2022-11-12T05:11:15.000Z","size":282,"stargazers_count":9,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-19T23:42:03.540Z","etag":null,"topics":["docker","dotnet","nextjs","react","swagger","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":false,"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/PeterYangIO.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}},"created_at":"2022-11-03T07:01:26.000Z","updated_at":"2025-01-18T14:19:30.000Z","dependencies_parsed_at":"2023-01-22T17:15:33.476Z","dependency_job_id":null,"html_url":"https://github.com/PeterYangIO/rsc-and-csharp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterYangIO%2Frsc-and-csharp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterYangIO%2Frsc-and-csharp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterYangIO%2Frsc-and-csharp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterYangIO%2Frsc-and-csharp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PeterYangIO","download_url":"https://codeload.github.com/PeterYangIO/rsc-and-csharp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245426232,"owners_count":20613311,"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":["docker","dotnet","nextjs","react","swagger","typescript"],"created_at":"2024-10-29T14:08:29.396Z","updated_at":"2025-03-25T08:31:17.403Z","avatar_url":"https://github.com/PeterYangIO.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Server Components + C#\nThis project shows a more end-to-end implementation of how React Server Components (RSC) would look in a full-stack application. Some highlights are:\n- Integration with a non-JS backend + generating strongly typed API clients using Swagger and TypeScript\n- Securely handling JWT authentication\n- Easy setup of development and deployment environments with docker\n\nJump to [Deep dive](#deep-dive) to see all the components this project can teach you.\n\n# Running the project\n## Codespaces\nAs all GitHub users will now receive 60 hours of free Codespaces per month, I strongly recommend using this as a way to quickly try out this demo project. Prebuilds are configured so you should have an instance spun up in a matter of seconds.\n\n![creating a new codespace](readme-resources/codespaces.jpg)\n\nAfter creating a new Codespace, it will default launch in a web browser. You should follow the prompt to launch in desktop VS Code instead as this will make the port mapping easier to work with.\n\n### Frontend\n`/frontend` folder and `npm run dev`\n### Backend\n`/backend` folder and `dotnet run`\n\n## Devcontainer\nFollow the official VS Code docs on [how to install dev containers](https://code.visualstudio.com/docs/devcontainers/containers#_installation).\n\n### Frontend\n`/frontend` folder and `npm run dev`\n### Backend\n`/backend` folder and `dotnet run`\n\n## Manually\n- Use node.js v18+\n  - `/frontend` folder\n  - `npm i`\n  - `npm run dev`\n- Use `.NET Core 6+`\n  - `/backend`\n  - `dotnet restore`\n  - `dotnet tool restore`\n  - `dotnet run`\n- Will also require postgres running in the background. See `/backend/appsettings.Development.json` for the connection string\n\n\n# Deep dive\n## Suspense\nClicking on the \"Suspense\" item in the navigation will show you how server components can concurrently render separate parts of the page at once. Additionally, interactive client side components can be ready while the server is still rendering this data as seen through the \"Click me\" button.\n\nCompare this to traditional SSR by removing the `\u003cSuspense /\u003e` tags in the `AwaitSuspense` function of `/frontend/app/suspense/page.tsx`. Reload and see how a blank page is rendered for up to 10 seconds because your SSR is blocking on a slow backend promise.\n\n## Regular Expression Denial of Service (Regex DoS)\nClicking on the \"RegEx DoS\" item in the navigation will show you how having a server component can expose you to security risks. From the dropdown, you can see \"Regular email\" and \"Long email\" run in ~ 0.1ms where as \"No domain\" can take upwards of 30,000x or more times longer! This is due to a `O(2^n)` runtime in the bad regex with a back-reference in certain situations. Selecting \"Crash me\" will cause the server to hang indefinitely, blocking other requests as well.\n\nMany developers coming from Create React App or other CSR only solutions may generally ignore security vulnerabilities such as RegEx DoS ones. See the following for more details:\n- https://github.com/facebook/create-react-app/issues/11174\n- https://overreacted.io/npm-audit-broken-by-design/\n\n## Conditional Server Rendering\nWhen components are conditionally rendered on the server, only the necessary components are streamed to the client, whereas with CSR, the entire JSX has to be loaded.\n\nIn `/frontend/app/page.tsx` you can see with `{user \u0026\u0026 \u003cNewPost/\u003e}` that the `NewPost` component will only be sent to the client if they are authenticated.\n\n## Authentication\n`next-auth` was in active development for supporting server components when this demo project was created so I made my own proxy server under `/frontend/pages/api/[...route].ts`. The proxy server will ensure the token received from the C# backend be stored in an http-only cookie, and thus never exposed to the client. Many developers using Create React App / other CSR solutions will likely be storing tokens in `localStorage` or `sessionStorage` which exposes your application to XSS risk. Introducing a frontend server for http-only cookies reduces this risk.\n\nA future update to this demo project will likely use `next-auth` for an easier solution.\n\n## API Clients with TypeScript\nIn the `package.json` there is a `swagger-gen` command will generates a TypeScript client under `/frontend/api-client`. A closer look into `APIClient.ts` shows a thin wrapper around this auto-generated code so the exact same client can be used on server components and client components. Take note of the `isServer()` function which enables the shareability.\n\n## CodeBlock.tsx\nThis component shows a couple of things:\n- `prismjs` and `sanitizeHtml` are used to render a code block to the user, but because it is rendered with a server component, these two packages are not added to the bundle that gets sent to the client\n- Looking closer into `CodeExecution.tsx` shows how devs can get very creative now that they have access to the the frontend server. Here, we have a React component calling a docker command, and then uses the power of `\u003cSuspense\u003e` to wait on that result before rendering it to the client\n\n## Deployment\nThere are two small docker files in `backend/Dockerfile` and `frontend/Dockerfile` which gets combined in `/docker-compose.yml` (not to be confused with `/.devcontainer/docker-compose.yml`). From the root directory you can run `docker compose build` which gives you a production ready build that can be hosted on your favorite provider. Locally, you can test it by running `docker compose up`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeteryangio%2Frsc-and-csharp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeteryangio%2Frsc-and-csharp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeteryangio%2Frsc-and-csharp/lists"}