Skip to content

psych0der/resin-photon

Repository files navigation

Photon

Sample home automation light controlling system using Resin mock API

This project was bootstrapped with Create React App since it provides simple and battle-tested boilerplate with many goodies built in. However, this is an ejected version as I wanted some features not available by default

Table of contents


This project uses node version 8. It is advisable to use nvm. Project root contains .nvmrc file.

This project requires a working mock API server which can be found here. Details of the API, namely HOST and PORT should be set in .env. Default values are already provided in .env.sample

  • Copy requirement file from .env.sample cp .env.sample .env
  • Install dependencies: yarn install
  • Start development server: yarn run start
  • Create a production build: yarn run build
  • Run Test cases: yarn run test
  • Start Storybook development server: yarn run start-storybook
  • Build Storybook: yarn run build-storybook

  • Added support for CSS-modules. This avoids the major headache of maintaining distinct class names across all the components

  • Used Scss instead of CSS, as I feel using a superset of CSS will increase my developer productivity. All the SCSS files are compiled to CSS files only. So in the source code, only CSS files are imported.

    • This decision allows other developers to switch to CSS if they like and the code will look same
  • Add Flow type checking. This allows writing code more confidently.

  • Add Prettier code formatting. I am using VSCode and there's an excellent plugin for prettier that formats code on save

  • I have also added a git pre-commit hook using Husky that formats the code before committing it. So that you don't have to use VSCode to get automatic code formatting ;)

  • I have added Redux for simple state management. This will also help in standardizing error handling for remote calls. I'll explain this another section.

  • Use React router for declarative routing. Although, we have a single page right now. But why not use a standardized way of creating route paths?


This project uses environment variables for configurations like HTTP endpoint of the light bulb API. This allows the code to be decoupled from the configuration and configurables to be frozen at build time. At the build time, this project looks for the .env file in the project root directory. This setup was done by create-react-app automatically while setting up this project. Look here for more info. This project contains .env.sample file to describe environment variables required by project. Don't add any confidential values in this sample file. Original .env file is not checked in git for security reasons.

Create a .env file by copying it from .env.sample before running this project [cp .env.sample .env]


I have used REDUX for state management. This allows for a single source of truth about application state. As there is scope for functionality addition which will require the state to be maintained at the application level, this is good to have added in this project. Specifically, I have added REDUX for having a central and out of the box support for error handling of network requests. As all network requests have 3 states, namely in-progress, success, and failed, having a REDUX middleware at the application level that will handle all network calls allows to write error handling logic only once and the listen for different states to update UI. Whenever a remote call is made, it has to be done through REDUX action creators, which will dispatch the relevant actions on a state change of network call.

Redux Devtools is enabled by default in development.

If you have the Redux DevTools chrome extension installed it will automatically be used on the client-side instead.

DevTools are not enabled during production.

I have used new Fetch API for network calls in this project instead of AJAX. Since Fetch is a relatively newer API, it is not supported on older browsers. To overcome this limitation a polyfill for Fetch has been used. This just wraps older XMLHttp method in Promise and exposes interface similar to native Fetch. Please note that this does not simplify or modify the interface that of native Fetch. It just adds support for older browsers.


Storybook is a UI development and testing library. I have integrated storybook as this will provide required support for developing new UI components. To run storybook, type this command -> yarn run storybook, and it will run a development server for the storybook. For more options visit the link mentioned above.

The storybook configuration will load files with extension .stories.js inside the src directory.


resin-photon
├──.storybook
│   ├── config.js
│   └── webpack.config.js
├──config
│   ├── env.js
│   ├── paths.js
│   ├── polyfills.js
│   ├── webpack.config.dev.js
│   ├── webpack.config.prod.js
│   └── webpackDevServer.config.js
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── scripts
│   ├── build.js
│   ├── start.js
│   └── test.js
├── src
│   ├── components
│   ├── containers
│   │   ├── App
│   │   │   ├── App.test.js
│   │   │   └── index.js
│   │   ├── Home
│   │   │   ├── index.css
│   │   │   ├── index.js
│   │   │   └── index.scss
│   │   └── index.js
│   ├── redux
│   │   ├── middlewares
│   │   │   └── augmentorMiddleware.js
│   │   ├── reducers
│   │   │   ├── index.js
│   │   │   └── sample.js
│   │   └── store.js
│   ├── index.css
│   ├── index.js
│   ├── index.scss
│   └── registerServiceWorker.js
├── .eslintrc
├── .flowconfig
├── .gitignore
├── .nvmrc
├── .prettierrc
├── README.md
├── package.json
└── yarn.lock
  • All of the application source resides inside src directory.
  • All Redux related code is inside src/redux
    • Reducers should reside in src/redux/reducers
  • Containers/Stateful components should have a directory inside src/containers. Expose the default container using index.js file inside the folder
  • Dumb/fully controlled components should have a directory inside src/components/
  • All the static assets used by components/containers should be contained inside their respective directories. This is done to isolate their assets and dependencies
  • Each component/container should contain their .story.js and .test.js files inside their directories

ALl webpack related configs, and polyfills reside inside config directory


  • I loved building Radial slider, as I got to brushen up my geometry and SVG skills. I spent considerable time on that part but it was worth it
  • I loved building redux integration and data shape. It is optimized for frequent data edits.

I have started building this project by setting a sane development environment that will allow faster iterations, easy updates and better maintainability.

  • Eslint is configured to inherit default practices from react-app
  • Flow is configured to allow for type checking inside JS code
  • Storybook is configured to allow UI level testing
  • Jest is integrated to provide integrated testing environment with lots of goodies out of the box

I have followed bottom-up approach while developing the application code. This allows developing basic components in isolation and then composing smaller, well tested components to form larger components and containers. This approach also encourages better composition and maintainability as it is easier to focus on smaller components individually instead of larger and monolith components

About

Experimental SPA for home bulb automation

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published