{"id":15573153,"url":"https://github.com/htdangkhoa/react-ssr-starter","last_synced_at":"2025-10-08T14:51:02.380Z","repository":{"id":37014663,"uuid":"396080302","full_name":"htdangkhoa/react-ssr-starter","owner":"htdangkhoa","description":"🔥 ⚛️ A React boilerplate for a universal web app with a highly scalable, offline-first foundation and our focus on performance and best practices.","archived":false,"fork":false,"pushed_at":"2025-05-22T17:52:30.000Z","size":2581,"stargazers_count":58,"open_issues_count":18,"forks_count":5,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-22T19:04:45.601Z","etag":null,"topics":["best-practices","boilerplate","docker","es6","framework","isomorphic","jest","performance","pwa","react","react-hooks","react-router","redux","redux-toolkit","seo","server-side-rendering","supertest","swc","testing-library-react","webpack"],"latest_commit_sha":null,"homepage":"https://reactssrstarter.herokuapp.com","language":"JavaScript","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/htdangkhoa.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,"zenodo":null}},"created_at":"2021-08-14T17:31:38.000Z","updated_at":"2025-02-15T06:26:34.000Z","dependencies_parsed_at":"2024-12-18T17:10:59.497Z","dependency_job_id":"7b29f886-1b97-4882-aa17-7bfd9463ba1b","html_url":"https://github.com/htdangkhoa/react-ssr-starter","commit_stats":{"total_commits":186,"total_committers":3,"mean_commits":62.0,"dds":"0.048387096774193505","last_synced_commit":"647f2697293bc0e2dab41dacdc853eb88ef0b6cb"},"previous_names":[],"tags_count":22,"template":true,"template_full_name":null,"purl":"pkg:github/htdangkhoa/react-ssr-starter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Freact-ssr-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Freact-ssr-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Freact-ssr-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Freact-ssr-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/htdangkhoa","download_url":"https://codeload.github.com/htdangkhoa/react-ssr-starter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Freact-ssr-starter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278963747,"owners_count":26076542,"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-10-08T02:00:06.501Z","response_time":56,"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":["best-practices","boilerplate","docker","es6","framework","isomorphic","jest","performance","pwa","react","react-hooks","react-router","redux","redux-toolkit","seo","server-side-rendering","supertest","swc","testing-library-react","webpack"],"created_at":"2024-10-02T18:10:54.933Z","updated_at":"2025-10-08T14:51:02.357Z","avatar_url":"https://github.com/htdangkhoa.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ereact-ssr-starter\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/15341301/131251228-40d7de86-ea0a-4cae-89a3-9a74e7f3b280.png\" alt=\"banner\" \u003e\n\u003c/p\u003e\n\n\u003cp align='center'\u003e\n  \u003ca href='https://depfu.com/github/htdangkhoa/react-ssr-starter?project_id=30809'\u003e\n    \u003cimg src='https://badges.depfu.com/badges/f269ac566de71c1081d497d42daec0d6/count.svg' alt='Depfu' /\u003e\n  \u003c/a\u003e\n\n  \u003ca href='https://github.com/htdangkhoa/react-ssr-starter/actions/workflows/ci.yml'\u003e\n    \u003cimg src='https://github.com/htdangkhoa/react-ssr-starter/actions/workflows/ci.yml/badge.svg' alt='CI' /\u003e\n  \u003c/a\u003e\n\n  \u003ca href=\"https://www.codefactor.io/repository/github/htdangkhoa/react-ssr-starter\"\u003e\n    \u003cimg src=\"https://www.codefactor.io/repository/github/htdangkhoa/react-ssr-starter/badge\" alt=\"CodeFactor\" /\u003e\n  \u003c/a\u003e\n\n  \u003ca href='https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base'\u003e\n    \u003cimg src='https://img.shields.io/badge/eslint-airbnb-4B32C3.svg' alt='Eslint: airbnb' /\u003e\n  \u003c/a\u003e\n\n  \u003ca href='https://github.com/prettier/prettier'\u003e\n    \u003cimg src='https://img.shields.io/badge/formatter-prettier-ff69b4.svg' alt='Formatter: prettier' /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003eThis is a boilerplate inspired \u003ca href=\"https://create-react-app.dev\"\u003eCRA\u003c/a\u003e. Designed with high scalability, an offline-first foundation, and a focus on performance and best practices.\u003c/p\u003e\n\n## Prerequisites\n\n- [Node.js](https://nodejs.org/en/download/): `^14.17.0` or `\u003e=16.0.0`\n\n## Getting Started\n\n```sh\ngit clone https://github.com/htdangkhoa/react-ssr-starter\n\nyarn install # or npm install\n\nyarn dev # or npm run dev\n```\n\n## Highlight\n\nUsing [SWC](https://swc.rs) will give build times **1.5x** faster for the server and **2.2x** for the client instead of using Babel.\n\n| Babel                                                                                                           | SWC                                                                                                           |\n| --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |\n| ![Babel](https://user-images.githubusercontent.com/15341301/140147312-322db462-9374-4da0-a8f9-e04fd10e7430.png) | ![Swc](https://user-images.githubusercontent.com/15341301/140154139-a71b21e3-d800-4ecd-8fa4-5329e563c05b.png) |\n\n## Features\n\n- [React](https://reactjs.org) - A JavaScript library for building user interfaces.\n- [Redux](https://redux.js.org) - A Predictable State Container for JS Apps.\n- [Redux Toolkit](https://redux-toolkit.js.org) - The official, opinionated, batteries-included toolset for efficient Redux development.\n- [React Router](https://github.com/remix-run/react-router) - Declarative routing for React.\n- [pure-http](https://github.com/htdangkhoa/pure-http) - The simple web framework for Node.js with zero dependencies.\n- [axios](https://github.com/axios/axios) - Promise based HTTP client for the browser and node.js.\n- [Webpack](https://webpack.js.org) - App bundling.\n- [SWC](https://swc.rs) - A super-fast compiler written in rust, producing widely-supported javascript from modern standards and typescript.\n- [React Refresh](https://github.com/facebook/react/tree/main/packages/react-refresh) - Fast refresh components without losing their state.\n- [react-helmet](https://github.com/nfl/react-helmet) - A document head manager for React.\n- [react-helmet-async](https://github.com/staylor/react-helmet-async) - Thread-safe Helmet for React 16+ and friends.\n- [loadable-component](https://github.com/gregberge/loadable-components) - The recommended Code Splitting library for React.\n- [dotenv](https://github.com/motdotla/dotenv) - Loads environment variables from `.env` for nodejs projects.\n- [Webpack Dev Middleware](https://github.com/webpack/webpack-dev-middleware) - Serves the files emitted from webpack over the Express server.\n- [Webpack Hot Middleware](https://github.com/webpack-contrib/webpack-hot-middleware) - Allows you to add hot reloading into the Express server.\n- [ESLint](https://eslint.org) - Find and fix problems in your JavaScript code.\n- [Prettier](https://prettier.io/) - Format code and style.\n- Integrate [Jest](https://jestjs.io/) with [Supertest](https://github.com/visionmedia/supertest), [Nock](https://github.com/nock/nock) and [React Testing Library](https://github.com/testing-library/react-testing-library) as the solution for writing unit tests with code coverage support.\n\n## Scripts\n\n| Script              | Description                                                                       |\n| ------------------- | --------------------------------------------------------------------------------- |\n| `dev`               | Runs your app on the development server at `localhost:9090`. HMR will be enabled. |\n| `build`             | Bundles both server-side and client-side files.                                   |\n| `build:server`      | Bundles server-side files in production mode and put it to the `build`.           |\n| `build:client`      | Bundles client-side files in production mode and put it to the `public`.          |\n| `start`             | Runs your app after bundled.                                                      |\n| `test`              | Runs testing.                                                                     |\n| `docker`            | Builds then run docker.                                                           |\n| `docker:build`      | Builds docker.                                                                    |\n| `docker:run`        | Runs docker.                                                                      |\n| `gen` or `generate` | Generate React component automatic based on template.                             |\n\n## Environment Variables\n\nYour project can consume variables declared in your environment as if they were declared locally in your JS files. By default you will have `NODE_ENV` defined for you, and you can define any other variables that you want but for the React app, your variables name must be have `REACT_APP_` prefix.\n\n\u003e WARNING: Do not store any secrets (such as private API keys) in your React app!\n\u003e\n\u003e Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.\n\nTo define permanent environment variables, create a file called .env in the root of your project:\n\n```\n# For node\nPRIVATE_CODE=123456\n\n# For React app\nREACT_APP_NOT_SECRET_CODE=abcdef\n```\n\n\u003e NOTE: You need to restart the development server after changing `.env` files.\n\n### What other `.env` files can be used?\n\n- `.env`: Default.\n- `.env.local`: Local overrides. This file is loaded for all environments except test.\n- `.env.development`, `.env.test`, `.env.production`: Environment-specific settings.\n- `.env.development.local`, `.env.test.local`, `.env.production.local`: Local overrides of environment-specific settings.\n\nOr you can add custom `.env` path in `webpack/webpack.config.base.js`:\n\n```js\nconst DotenvWebpackPlugin = require('./plugins/dotenv-webpack-plugin');\n\n// webpack config\n{\n  ...,\n  plugins: [\n    ...,\n    new DotenvWebpackPlugin({\n      path: './custom-env',\n      isWeb: true|false,\n    }),\n  ],\n}\n```\n\nPlease refer to the [dotenv](https://github.com/motdotla/dotenv) documentation for more details.\n\n### Expanding Environment Variables In .env\n\nExpand variables already on your machine for use in your .env file (using [dotenv-expand](https://github.com/motdotla/dotenv-expand)).\n\nFor example, to get the environment variable npm_package_version:\n\n```\nREACT_APP_VERSION=$npm_package_version\n# also works:\n# REACT_APP_VERSION=${npm_package_version}\n```\n\nOr expand variables local to the current .env file:\n\n```\nDOMAIN=www.example.com\nREACT_APP_FOO=$DOMAIN/foo\nREACT_APP_BAR=$DOMAIN/bar\n```\n\n\u003e **NOTE:** Support [Google Search Console verification code](https://www.youtube.com/watch?v=RktlwdM3k1s) with `GOOGLE_SITE_VERIFICATION` environment variable.\n\n## Configurations\n\n### Basic\n\nYou can store your configurations in `src/configs/client.js` for client-side, `src/configs/server.js` for server-side. `src/configs/constants.js` is for constants.\n\nYou can access the correct configuration with:\n\n```js\nimport configs from 'configs/client'; // for client-side\nimport configs from 'configs/server'; // for server-side\nimport constants from 'configs/constants';\n\n// ...\n```\n\n### Advanced\n\nYou can adjust various development and production settings by setting environment variables in your shell or with [.env](#environment-variables).\n\n\u003e Note: You do not need to declare `REACT_APP_` before the below variables as you would with custom environment variables.\n\n| Variable                  | Development | Production | Usage                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |\n| ------------------------- | ----------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `BROWSER`                 | ✅ Used     | 🚫 Ignored | By default, Create React App will open the default system browser, favoring Chrome on macOS. Specify a [browser](https://github.com/sindresorhus/open#app) to override this behavior, or set it to `none` to disable it completely. If you need to customize the way the browser is launched, you can specify a node script instead. Any arguments passed to `npm start` will also be passed to this script, and the url where your app is served will be the last argument. Your script's file name must have the `.js` extension. |\n| `BROWSER_ARGS`            | ✅ Used     | 🚫 Ignored | When the `BROWSER` environment variable is specified, any arguments that you set to this environment variable will be passed to the browser instance. Multiple arguments are supported as a space separated list. By default, no arguments are passed through to browsers.                                                                                                                                                                                                                                                          |\n| `PORT`                    | ✅ Used     | 🚫 Ignored | By default, the development web server will attempt to listen on port 9090 or prompt you to attempt the next available port. You may use this variable to specify a different port.                                                                                                                                                                                                                                                                                                                                                 |\n| `IMAGE_INLINE_SIZE_LIMIT` | ✅ Used     | ✅ Used    | By default, images smaller than 10,000 bytes are encoded as a data URI in base64 and inlined in the CSS or JS build artifact. Set this to control the size limit in bytes. Setting it to `0` will disable the inlining of images.                                                                                                                                                                                                                                                                                                   |\n| `ESLINT_NO_DEV_ERRORS`    | ✅ Used     | 🚫 Ignored | When set to `true`, ESLint errors are converted to warnings during development. As a result, ESLint output will no longer appear in the error overlay.                                                                                                                                                                                                                                                                                                                                                                              |\n| `DISABLE_ESLINT_PLUGIN`   | ✅ Used     | ✅ Used    | When set to `true`, [eslint-webpack-plugin](https://github.com/webpack-contrib/eslint-webpack-plugin) will be completely disabled.                                                                                                                                                                                                                                                                                                                                                                                                  |\n\n## Adding Styles\n\nThe starter supports CSS, SASS and [CSS modules](https://github.com/css-Modules/css-Modules) is auto enabled for all files the `[name].module.*` naming convention. I use [PostCSS](https://github.com/webpack-contrib/postcss-loader) plugin to parse CSS and add autoprefixer to your stylesheet. You can access your stylesheet with two ways.\n\n```css\n/* custom button style */\n\n.Button {\n  padding: 20px;\n}\n```\n\n### With CSS modules\n\n```jsx\nimport styles from './styles.module.scss';\n\nfunction Button() {\n  return \u003cdiv className={styles.Button} /\u003e;\n}\n```\n\n### Without CSS modules\n\n```jsx\nimport './styles.scss';\n\nfunction Button() {\n  return \u003cdiv className='Button' /\u003e;\n}\n```\n\nYou can also add the vendor CSS frameworks or global styles, just import it through the `src/client/app/index.jsx` file (app root component). For example:\n\n```jsx\nimport 'bootstrap/dist/css/bootstrap.min.css';\nimport '\u003cyour-global-styles\u003e.css';\n\nfunction App() {\n  // ...\n}\n```\n\n## Adding Images, Fonts, and Files\n\nWith webpack, using static assets like images and fonts works similarly to CSS.\n\nYou can **`import`** **a file right in a JavaScript module**. This tells webpack to include that file in the bundle. Unlike CSS imports, importing a file gives you a string value. This value is the final path you can reference in your code, e.g. as the `src` attribute of an image or the `href` of a link to a PDF.\n\nTo reduce the number of requests to the server, importing images that are less than 10,000 bytes returns a [data URI](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) instead of a path. This applies to the following file extensions: bmp, gif, jpg, jpeg, and png. SVG files are excluded for sprite. You can control the 10,000 byte threshold by setting the `IMAGE_INLINE_SIZE_LIMIT` environment variable.\n\nHere is an example:\n\n```js\nimport React from 'react';\nimport logo from './logo.png'; // Tell webpack this JS file uses this image\n\nconsole.log(logo); // /70a4f6b392fa19ff6912.png\n\nfunction Header() {\n  // Import result is the URL of your image\n  return \u003cimg src={logo} alt='Logo' /\u003e;\n}\n\nexport default Header;\n```\n\nThis ensures that when the project is built, webpack will correctly move the images into the build folder, and provide us with correct paths.\n\nThis works in CSS too:\n\n```css\n.Logo {\n  background-image: url(./logo.png);\n}\n```\n\n### Adding SVGs\n\nOne way to add SVG files was described in the section above. You can also import SVGs directly as React components. You can use either of the two approaches. In your code it would look like this:\n\n```js\nimport { ReactComponent as Logo } from './logo.svg';\n\nfunction App() {\n  return (\n    \u003cdiv\u003e\n      {/* Logo is an actual React component */}\n      \u003cLogo /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n## Generators\n\n### Usage\n\n- npm\n\n  ```sh\n  npm run gen component \"\u003ccomponent_name\u003e\"\n\n  npm run generate component \"\u003ccomponent_name\u003e\"\n  ```\n\n- Yarn\n\n  ```sh\n  yarn gen component \"\u003ccomponent_name\u003e\"\n\n  yarn generate component \"\u003ccomponent_name\u003e\"\n  ```\n\n### Example\n\n```sh\nyarn gen component \"hello world\"\n\n# or npm run gen component \"hello world\"\n```\n\nOutput: `/src/client/components/HelloWorld/index.jsx` will be generated. `/src/client/components/HelloWorld/__tests__/index.test.jsx` will be generated if you want add the unit testing.\n\n### Custom\n\nYou can add template in `generators` directory, please read more at [plopjs](https://github.com/plopjs/plop).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtdangkhoa%2Freact-ssr-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhtdangkhoa%2Freact-ssr-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtdangkhoa%2Freact-ssr-starter/lists"}