{"id":20466003,"url":"https://github.com/atolye15/cra-recipe","last_synced_at":"2025-04-13T08:55:24.428Z","repository":{"id":98693157,"uuid":"177958894","full_name":"atolye15/cra-recipe","owner":"atolye15","description":"Step-by-step guide to bootstrap a CRA app from scratch.","archived":false,"fork":false,"pushed_at":"2020-10-04T14:22:30.000Z","size":651,"stargazers_count":174,"open_issues_count":5,"forks_count":9,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-27T00:33:58.223Z","etag":null,"topics":["create-react-app","react","storybook","typescript"],"latest_commit_sha":null,"homepage":null,"language":null,"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/atolye15.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}},"created_at":"2019-03-27T09:16:17.000Z","updated_at":"2024-08-10T21:31:12.000Z","dependencies_parsed_at":"2023-04-22T12:22:04.573Z","dependency_job_id":null,"html_url":"https://github.com/atolye15/cra-recipe","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/atolye15%2Fcra-recipe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atolye15%2Fcra-recipe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atolye15%2Fcra-recipe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atolye15%2Fcra-recipe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atolye15","download_url":"https://codeload.github.com/atolye15/cra-recipe/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248688544,"owners_count":21145763,"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":["create-react-app","react","storybook","typescript"],"created_at":"2024-11-15T13:21:06.406Z","updated_at":"2025-04-13T08:55:24.421Z","avatar_url":"https://github.com/atolye15.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# CRA Recipe\n\nThis is a step-by-step guide to customize CRA for Atolye15 projects. You can review [CRA Starter](https://github.com/atolye15/cra-starter) project to see how your application looks like when all steps followed.\n\nYou will get an application which has;\n\n* TypeScript\n* Sass\n* Linting\n* Formatting\n* Testing\n* CI/CD\n* Storybook\n\n## Table of Contents\n\n* [Step 1: Creating a new app](#step-1-creating-a-new-app)\n* [Step 2: Removing CRA example files](#step-2-removing-cra-example-files)\n* [Step 3: Make TypeScript more strict](#step-3-make-typescript-more-strict)\n* [Step 4: Installing Prettier](#step-4-installing-prettier)\n* [Step 5: Installing ESLint](#step-5-installing-eslint)\n* [Step 6: Enabling Sass](#step-6-enabling-sass)\n* [Step 7: Installing stylelint](#step-7-installing-stylelint)\n* [Step 8: Setting up our test environment](#step-8-setting-up-our-test-environment)\n* [Step 9: Enabling hot reloading](#step-9-enabling-hot-reloading)\n* [Step 10: Organizing Folder Structure](#step-10-organizing-folder-structure)\n* [Step 11: Adding Storybook](#step-11-adding-storybook)\n* [Step 12: Adding React Router](#step-12-adding-react-router)\n* [Step 13: Enabling code-splitting](#step-13-enabling-code-splitting)\n* [Step 14: Adding CircleCI config](#step-14-adding-circleci-config)\n* [Step 15: Auto-deploy to Surge.sh](#step-15-auto-deploy-to-surgesh)\n* [Step 16: Github Settings](#step-16-github-settings)\n* [Step 17 Final Touches](#step-17-final-touches)\n* [Step 18: Starting to Development \u003cg-emoji class=\"g-emoji\" alias=\"tada\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f389.png\"\u003e🎉\u003c/g-emoji\u003e](#step-18-starting-to-development-)\n\n## Step 1: Creating a new app\n\nFirst of all, we need to initialize our codebase via CRA command.\n\n```sh\nnpx create-react-app cra-starter --template typescript\ncd cra-starter\nyarn start\n```\n\n## Step 2: Removing CRA example files\n\nIn order to create our stack, we need to remove unnecessary CRA files.\n\n## Step 3: Make TypeScript more strict\n\nWe want to keep type safety as strict as possibble. In order to do that, we update `tsconfig.json` with the settings below.\n\n```jsonc\n\"noImplicitAny\": true,\n\"noImplicitReturns\": true,\n```\n\n## Step 4: Installing Prettier\n\nWe want to format our code automatically. So, we need to install Prettier.\n\n```sh\nyarn add prettier --dev\n```\n\n`.prettierrc`\n\n```jsonc\n{\n  \"printWidth\": 100,\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\"\n}\n```\n\n`.prettierignore`\n\n```ignore\nbuild\n```\n\nAlso, we want to enable format on save on VSCode.\n\n`.vscode/settings.json`\n\n```json\n{\n  \"editor.formatOnSave\": true,\n}\n```\n\nFinally, we update `package.json` with related format scripts.\n\n```json\n\"format:ts\": \"prettier --write 'src/**/*.{ts,tsx}'\",\n\"format\": \"yarn run format:ts\",\n\"format:check\": \"prettier -c 'src/**/*.{ts,tsx}'\"\n```\n\n## Step 5: Installing ESLint\n\nWe want to have consistency in our codebase and also want to catch mistakes. So, we need to install ESLint.\n\n```sh\nyarn add eslint @atolye15/eslint-config --dev\n```\n`.eslintrc`\n\n```jsonc\n{\n  \"extends\": [\n    \"@atolye15/eslint-config\"\n  ]\n}\n```\n\n`.eslintignore`\n\n```ignore\npublic\nbuild\nreact-app-env.d.ts\n```\n\n`.vscode/settings.json`\n\n```json\n{\n  \"eslint.validate\": [\"javascript\", \"javascriptreact\", \"typescript\", \"typescriptreact\"]\n}\n```\n\nWe need to update `package.json` for ESLint scripts.\n\n```json\n\"lint\": \"yarn run lint:ts\",\n\"lint:ts\": \"tsc \u0026\u0026 yarn lint:eslint\",\n\"lint:eslint\": \"eslint 'src/**/*.{ts,tsx}'\",\n\"format:ts\": \"prettier --write 'src/**/*.{ts,tsx}' \u0026\u0026 yarn lint:eslint --fix\",\n```\n\n## Step 6: Enabling Sass\n\nCRA comes with Sass support out of the box. In order to enable it, we only add `node-sass` to our project.\n\n```sh\nyarn add node-sass --dev\n```\n\n## Step 7: Installing stylelint\n\nWe also want a linter for our sass files. We need to install `stylelint`.\n\n```sh\nyarn add stylelint stylelint-config-prettier stylelint-prettier @atolye15/stylelint-config --dev\n```\n\n`.stylelintrc`\n\n```jsonc\n{\n  \"extends\": [\"@atolye15/stylelint-config\", \"stylelint-prettier/recommended\"]\n}\n```\n\nFinally, we need to update `package.json` and `.vscode/settings.json`\n\n`package.json`\n\n```json\n\"lint:css\": \"stylelint --syntax scss \\\"src/**/*.scss\\\"\",\n\"lint\": \"yarn run lint:ts \u0026\u0026 yarn run lint:css\",\n\"format:css\": \"stylelint --fix --syntax scss \\\"src/**/*.scss\\\"\",\n\"format\": \"yarn run format:ts \u0026\u0026 yarn run format:css\"\n```\n\n## Step 8: Setting up our test environment\n\nWe'll use `jest` with `enzyme`.\n\n```sh\nyarn add enzyme enzyme-adapter-react-16 react-test-renderer --dev\nyarn add @types/enzyme @types/enzyme-adapter-react-16 --dev\n```\n\nAlso we need to install `enzyme-to-json` for simpler snapshosts.\n\n```sh\nyarn add enzyme-to-json --dev\n```\n\nWe update our `package.json` for jest configuration.\n\n```json\n\"scripts\": {\n  \"coverage\": \"yarn run test --coverage\"\n},\n\"jest\": {\n  \"snapshotSerializers\": [\n    \"enzyme-to-json/serializer\"\n  ],\n  \"collectCoverageFrom\": [\n    \"src/**/*.{ts,tsx}\",\n    \"!src/index.tsx\",\n    \"!src/setupTests.ts\",\n    \"!src/components/**/index.{ts,tsx}\",\n    \"!src/components/**/*.stories.{ts,tsx}\"\n  ],\n  \"coverageThreshold\": {\n    \"global\": {\n      \"branches\": 80,\n      \"functions\": 80,\n      \"lines\": 80,\n      \"statements\": 80\n    }\n  }\n}\n```\n\nAnd finally, we need to add the `coverage` to `.gitignore` and `.prettierignore`.\n\n`.eslintignore`\n\n```ignore\n# ...\ncoverage\n```\n\n`.prettierignore`\n\n```ignore\n# ...\ncoverage\n```\n\nBefore the testing, we need to add our setup file to initialize enzyme.\n\n`src/setupTests.ts`\n\n```ts\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-react-16';\n\nconfigure({ adapter: new Adapter() });\n```\n\nWith this config, we are able to run tests with snapshots and create coverage. Let's add a simple test to verify our setup.\n\n`src/App.test.tsx`\n\n```tsx\nimport React from 'react';\nimport { shallow } from 'enzyme';\nimport App from './App';\n\nit('runs correctly', () =\u003e {\n  const wrapper = shallow(\u003cApp /\u003e);\n\n  expect(wrapper).toMatchSnapshot();\n});\n```\n\nAlso, verify coverage report with `yarn coverage`.\n\n## Step 9: Enabling hot reloading\n\nWe want to take advantage of hot reloading and don't want to lose React's current state. In order to do that we can use react hot loader. Since, we use CRA and don't want to eject it, we need to use `customize-cra` package.\n\n```sh\nyarn add react-app-rewired customize-cra @hot-loader/react-dom --dev\n```\n\nAfter the installation we need to update `package.json` scripts to use `react-app-rewired`\n\n```json\n\"start\": \"react-app-rewired start\",\n\"build\": \"react-app-rewired build\",\n\"test\": \"react-app-rewired test\",\n\"eject\": \"react-app-rewired eject\"\n```\n\nNow, we can install `react-hot-loader`.\n\n```sh\nyarn add react-hot-loader\n```\n\nAlso we need to update hot reloader config.\n\n`src/index.tsx`\n\n```tsx\nimport { setConfig } from 'react-hot-loader';\n\nsetConfig({\n  ignoreSFC: true,\n  pureRender: true,\n});\n```\n\nIn order to update babel config for hot loader, we need to create a `config-overrides.js` file on the root.\n\n```ts\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { override, addBabelPlugin, addWebpackAlias } = require('customize-cra');\n\nmodule.exports = override(\n  addBabelPlugin('react-hot-loader/babel'),\n  addWebpackAlias({\n    'react-dom': '@hot-loader/react-dom',\n  }),\n);\n```\n\nLastly, we need to use hot HOC.\n\n`src/App.tsx`\n\n```tsx\nimport React from 'react';\nimport { hot } from 'react-hot-loader/root';\n\nexport default hot(App);\n```\n\n## Step 10: Organizing Folder Structure\n\nOur folder structure should look like this;\n\n```\nsrc/\n├── App.test.tsx\n├── App.tsx\n├── __snapshots__\n│   └── App.test.tsx.snap\n├── components\n│   └── Button\n│       ├── Button.scss\n│       ├── Button.stories.tsx\n│       ├── Button.test.tsx\n│       ├── Button.tsx\n│       ├── __snapshots__\n│       │   └── Button.test.tsx.snap\n│       └── index.ts\n├── containers\n│   └── Like\n│       ├── Like.tsx\n│       └── index.ts\n├── fonts\n├── img\n├── index.tsx\n├── react-app-env.d.ts\n├── routes\n│   ├── Feed\n│   │   ├── Feed.scss\n│   │   ├── Feed.test.tsx\n│   │   ├── Feed.tsx\n│   │   ├── index.ts\n│   │   └── tabs\n│   │       ├── Discover\n│   │       │   ├── Discover.scss\n│   │       │   ├── Discover.test.tsx\n│   │       │   ├── Discover.tsx\n│   │       │   └── index.ts\n│   │       └── MostLiked\n│   │           ├── MostLiked.test.tsx\n│   │           ├── MostLiked.tsx\n│   │           └── index.ts\n│   ├── Home\n│   │   ├── Home.scss\n│   │   ├── Home.test.tsx\n│   │   ├── Home.tsx\n│   │   └── index.ts\n│   └── index.ts\n├── setupTests.ts\n├── styles\n│   └── index.scss\n└── utils\n    ├── location.test.ts\n    └── location.ts\n```\n\n## Step 11: Adding Storybook\n\nWe need to initialize the Storybook on our project.\n\n```sh\nnpx -p @storybook/cli sb init --type react\n```\n\nWe also need to add `info` addon and `react-docgen-typescript-loader` package to show component props on our stories (Optional but recommended).\n\n```sh\nyarn add @storybook/addon-info react-docgen-typescript-loader --dev\n```\n\nWe have to use the [custom Webpack config in full control mode, extending default configs](https://storybook.js.org/docs/configurations/custom-webpack-config/#full-control-mode--default) by creating a `webpack.config.js` file in our Storybook configuration directory (by default, it’s `.storybook`):\n\n`.storybook/webpack.config.js`\n\n```js\nmodule.exports = ({ config, mode }) =\u003e {\n  config.module.rules.push({\n    test: /\\.(ts|tsx)$/,\n    use: [\n      {\n        loader: require.resolve('babel-loader'),\n        options: {\n          presets: [require.resolve('babel-preset-react-app')],\n        },\n      },\n      require.resolve('react-docgen-typescript-loader'),\n    ],\n  });\n  config.resolve.extensions.push('.ts', '.tsx');\n  return config;\n};\n```\n\nSince we use `typescript`, we can change the file extensions (`addons` and `config`) to `.ts` in `.storybook` folder. Then we need to update storybook config to register info addon, and stories directory.\n\n`.storybook/config.ts`\n\n```ts\nimport { configure, addDecorator } from '@storybook/react';\nimport { withInfo } from '@storybook/addon-info';\n\n// automatically import all files ending in *.stories.tsx\nconst req = require.context('../src/components', true, /.stories.tsx$/);\n\nfunction loadStories() {\n  addDecorator(withInfo);\n  req.keys().forEach(req);\n}\n\nconfigure(loadStories, module);\n```\n\n\u003e We will place the stories inside component folders, you can delete the `stories` folder which is created by storybook initialization process.\n\nLet's create a story for our Button component.\n\n`src/components/Button/Button.stories.tsx`\n\n```tsx\nimport React from 'react';\nimport { storiesOf } from '@storybook/react';\n\nimport Button from './Button';\n\nstoriesOf('Button', module)\n  .add('Primary', () =\u003e \u003cButton primary\u003ePrimary Button\u003c/Button\u003e)\n  .add('Secondary', () =\u003e \u003cButton secondary\u003eSecondary Button\u003c/Button\u003e);\n```\n\nRun storybook\n\n```\nyarn storybook\n```\n\n## Step 12: Adding React Router\n\nAs usual, we want to use `react-router` for routing.\n\n```\nyarn add react-router-dom\nyarn add @types/react-router-dom --dev\n```\n\nThen, we need to encapsulate our root component with `BrowserRouter`.\n\n```tsx\n// src/index.tsx\n\nimport React, { FunctionComponent } from 'react';\nimport ReactDOM from 'react-dom';\nimport { setConfig } from 'react-hot-loader';\nimport { BrowserRouter } from 'react-router-dom';\n\nimport App from './App';\n\nsetConfig({\n  ignoreSFC: true,\n  pureRender: true,\n});\n\nconst Root: FunctionComponent = () =\u003e (\n  \u003cBrowserRouter\u003e\n    \u003cApp /\u003e\n  \u003c/BrowserRouter\u003e\n);\n\nReactDOM.render(\u003cRoot /\u003e, document.getElementById('root'));\n```\n\n```tsx\n// src/routes/Routes.tsx\n\nimport React, { FunctionComponent } from 'react';\nimport { Switch, Route } from 'react-router-dom';\n\nimport Home from './Home';\nimport Feed from './Feed';\n\nconst Routes: FunctionComponent = () =\u003e (\n  \u003cSwitch\u003e\n    \u003cRoute path=\"/\" exact component={Home} /\u003e\n    \u003cRoute path=\"/feed\" exact component={Feed} /\u003e\n  \u003c/Switch\u003e\n);\n\nexport default Routes;\n```\n\n```tsx\n// src/App.tsx\n\nimport React, { FunctionComponent, Fragment } from 'react';\nimport { hot } from 'react-hot-loader';\n\nimport Routes from './routes';\n\nconst App: FunctionComponent = () =\u003e (\n  \u003cFragment\u003e\n    \u003cheader\u003eHeader\u003c/header\u003e\n    \u003cRoutes /\u003e\n    \u003cfooter\u003eFooter\u003c/footer\u003e\n  \u003c/Fragment\u003e\n);\n\nexport default hot(module)(App);\n```\n\n## Step 13: Enabling code-splitting\n\nWe want to make route based code-splitting in order to prevent a huge bundled asset. When we done with this, only relevant assets will be loaded by our application. Let's install `react-loadable`.\n\n```\nyarn add react-loadable\nyarn add @types/react-loadable --dev\n```\n\nNow, let's convert our routes to dynamically loaded.\n\n```tsx\n// src/routes/Home/index.ts\n\nimport Loadable from 'react-loadable';\n\nimport Loading from '../../components/Loading';\n\nconst LoadableHome = Loadable({\n  loader: () =\u003e import('./Home'),\n  loading: Loading,\n});\n\nexport default LoadableHome;\n```\n\n```tsx\n// src/routes/Feed/index.ts\n\nimport Loadable from 'react-loadable';\n\nimport Loading from '../../components/Loading';\n\nconst LoadableFeed = Loadable({\n  loader: () =\u003e import('./Feed'),\n  loading: Loading,\n});\n\nexport default LoadableFeed;\n```\n\n## Step 14: Adding CircleCI config\n\nWe can create a CircleCI pipeline in order to CI / CD.\n\n```yaml\n# .circleci/config.yml\n\nversion: 2\njobs:\n  build_dependencies:\n    docker:\n      - image: circleci/node:10\n    working_directory: ~/repo\n    steps:\n      - checkout\n      - attach_workspace:\n          at: ~/repo\n      - restore_cache:\n          keys:\n            - dependencies-{{ checksum \"package.json\" }}\n            - dependencies-\n      - run:\n          name: Install\n          command: yarn install\n      - save_cache:\n          paths:\n            - ~/repo/node_modules\n          key: dependencies-{{ checksum \"package.json\" }}\n      - persist_to_workspace:\n          root: .\n          paths: node_modules\n\n  test_app:\n    docker:\n      - image: circleci/node:10\n    working_directory: ~/repo\n    steps:\n      - checkout\n      - attach_workspace:\n          at: ~/repo\n      - run:\n          name: Lint\n          command: yarn lint\n      - run:\n          name: Format\n          command: yarn format:check\n      - run:\n          name: Test\n          command: yarn test\n      - run:\n          name: Coverage\n          command: yarn coverage\n\nworkflows:\n  version: 2\n  build_app:\n    jobs:\n      - build_dependencies\n      - test_app:\n          requires:\n            - build_dependencies\n```\n\nAfter that we need to enable CircleCI for our repository.\n\n## Step 15: Auto-deploy to Surge.sh\n\nFirst of all, we need to retrieve our Surge.sh token.\n\n```\nsurge token\n```\n\nAfter copying the value, we need to add it as a dev dependency.\n\n```\nyarn add surge --dev\n```\n\nWe need to add surge token to CircleCI as an environment variable for our project. Please update project name in the url;\n\n*https://circleci.com/gh/atolye15/{PROJET_NAME}/edit#env-vars*\n\nOn the page, we'll add `SURGE_LOGIN` and `SURGE_TOKEN` envs with the email and token we got before. We're almost ready. Let's update our CircleCI config.\n\n```yaml\n# .circleci/config.yml\n\nversion: 2\njobs:\n  build_dependencies:\n    docker:\n      - image: circleci/node:10\n    working_directory: ~/repo\n    steps:\n      - checkout\n      - attach_workspace:\n          at: ~/repo\n      - restore_cache:\n          keys:\n            - dependencies-{{ checksum \"package.json\" }}\n            - dependencies-\n      - run:\n          name: Install\n          command: yarn install\n      - save_cache:\n          paths:\n            - ~/repo/node_modules\n          key: dependencies-{{ checksum \"package.json\" }}\n      - persist_to_workspace:\n          root: .\n          paths: node_modules\n\n  test_app:\n    docker:\n      - image: circleci/node:10\n    working_directory: ~/repo\n    steps:\n      - checkout\n      - attach_workspace:\n          at: ~/repo\n      - run:\n          name: Lint\n          command: yarn lint\n      - run:\n          name: Format\n          command: yarn format:check\n      - run:\n          name: Test\n          command: yarn test\n      - run:\n          name: Coverage\n          command: yarn coverage\n\n  deploy_app:\n    docker:\n      - image: circleci/node:10\n    working_directory: ~/repo\n    steps:\n      - checkout\n      - attach_workspace:\n          at: ~/repo\n      - run:\n          name: Deploy\n          command: yarn deploy\n\nworkflows:\n  version: 2\n  build_app:\n    jobs:\n      - build_dependencies\n      - test_app:\n          requires:\n            - build_dependencies\n      - deploy_app:\n          requires:\n            - test_app\n          filters:\n            branches:\n              only: master\n```\n\nLet's add deploy script to our `package.json`.\n\n```\n\"deploy\": \"sh deploy.sh\"\n```\n\nFinally, we need to create a `deploy.sh` file.\n\n```sh\necho 'Building application...'\nyarn build\n\necho 'Copying index.html as 404.html'\ncp build/index.html build/404.html\n\necho 'Deploying...'\nnode_modules/.bin/surge --project ./build --domain cra-starter.surge.sh\n\necho 'Deployed 🚀'\n```\n\n\u003e *NOTE: Of course, you can replace Surge.sh with anything else. For this, you only need to update Surge.sh parts.*\n\n## Step 16: Github Settings\n\nWe want to protect our `develop` and `master` branches. Also, we want to make sure our test passes and at lest one person reviewed the PR. In order to do that, we need to update branch protection rules like this in GitHub;\n\n![github-branch-settings](https://user-images.githubusercontent.com/1801024/55028896-df2a3300-5019-11e9-9827-a984fcfa29af.png)\n\n## Step 17 Final Touches\n\nWe are ready to develop our application. Just a final step, we need to update our `README.md` to explain what we add a script so far.\n\n```md\nThis project was set up with following [CRA Recipe](https://github.com/atolye15/cra-recipe).\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `yarn start`\n\nRuns the app in the development mode.\u003cbr\u003e\nOpen [http://localhost:3000](http://localhost:3000) to view it in the browser.\n\nThe page will hot reload if you make edits.\u003cbr\u003e\nYou will also see any lint errors in the console.\n\n### `yarn test`\n\nLaunches the test runner in the interactive watch mode.\u003cbr\u003e\nSee the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.\n\n### `yarn coverage`\n\nLaunches coverage reporter. You can view the details from `coverage` folder.\n\n### `yarn lint`\n\nRuns ESLint and StyleLint. If any lint errors found, then it exits with code 1.\n\n### `yarn format`\n\nFormats TypeScript and Sass files.\n\n### `yarn format:check`\n\nCheckes if any formatting error has been made.\n\n### `yarn storybook`\n\nLaunches Storybook application.\n\n### `yarn build`\n\nBuilds the app for production to the `build` folder.\u003cbr\u003e\nIt correctly bundles React in production mode and optimizes the build for the best performance.\n\nThe build is minified and the filenames include the hashes.\u003cbr\u003e\nYour app is ready to be deployed!\n\n### `yarn deploy`\n\nDeploys app to given platform according to instuctions in `deploy.sh`\n\n## Learn More\n\nYou can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).\n\nTo learn React, check out the [React documentation](https://reactjs.org/).\n```\n\n## Step 18: Starting to Development 🎉\n\nEverything is done! You can start to develop your next awesome React application now on 🚀\n\n## Related\n\n* [crna-recipe](https://github.com/atolye15/crna-recipe) - React Native App Creation Recipe\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatolye15%2Fcra-recipe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatolye15%2Fcra-recipe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatolye15%2Fcra-recipe/lists"}