Giter VIP home page Giter VIP logo

test-fullstack's Introduction

Lightning Talks Polling App

Wireframe & Design

Checkout lightning-talks-polling.fig, use Figma to open it. Or use this view only link.

This app was designed in a Mobile First approach.

API

API Documentation: open-api.yaml, or use this view only link.

Run This Project

Configuration

Edit .env as well as server/.env:

# Configure frontend
cp .env.sample .env

# Configure backend
cd server
cp .env.sample .env
# Or specify environment variables in docker run config

Setting Authorization callback URL: https://<DOMAIN>/login/oauth/callback.

Mind that you will need to specify API_SERVER for frontend and FRONTEND_BASE_URL for backend.

You can build the project locally and run it, or you can use the pre-built docker images to run.

Pre-built Docker Image

npm run start:docker
# Then navigate to http://localhost:8000 in your browser

Build

npm run start
# Then navigate to http://localhost:1234 in your browser

Containerization

This project includes Dockerfiles for each sub-project (client, server), and have a docker-compose.yml which you can use to quickly spin up an instance.

Deployment

For deployment, I'm using this tool(reverse-proxy) I created to put it online.

If you are trying to use docker-compose.yml provided in this repo to deploy, keep in mind to add additional configs with a docker-compose.override.yml config.

For example:

version: '3.6'
services:
  frontend:
    labels:
      - 'traefik.enable=true'
      - 'traefik.backend=talks'
      - 'traefik.frontend.rule=Host:***.com'
      - 'traefik.port=80'
  api:
    environment:
      - 'OAUTH_GITHUB_CLIENT_ID=<OAUTH_GITHUB_CLIENT_ID>'
      - 'OAUTH_GITHUB_CLIENT_SECRET=<OAUTH_GITHUB_CLIENT_SECRET>'
      - 'FRONTEND_BASE_URL=<FRONTEND_BASE_URL>'
    labels:
      - 'traefik.enable=true'
      - 'traefik.backend=talks-api'
      - 'traefik.frontend.rule=Host:<FRONTEND_DOMAIN>'
      - 'traefik.port=<PORT>'

Tech Stack

Form Validation

For form data validation, I'm using Yup as the schema validator, it works on both frontend and backend, compares to Joi, it's lighter and generally more friendly to use in browsers, and it supports backend as well, and it supports multiple languages.

In addition to that, I'm using Formik to manage my form state and validates against schemas.

Error Handling

Server side: Heavily influenced by this repo Wiredcraft/service-error. it's what I considered a good practice. Extend from ExtendableError is easier to work with than extending from Error itself.

ID Generation

Use cuid(by ericelliott) instead of uuid/v1 or uuid/v4. UUID is like USB Type-C connector, the shape looks the same but the implementation can be vastly different. cuid offers the same functionality as uuid/v1, so for this particular project I'll just use cuid for better recognizability.

Similar to MongoDB's Object ID, it also breaks down into different parts which is faster for binary search since some parts in the front won't change that often.

The implementation of ID generation can be easily swapped, checkout server/src/utils/id.js.

Database

Using Redis as the only database, it works great for current requirement, but it's not so easy to work in the future. I haven't defined any database migration logic yet.

Authentication

Using Github as OAuth provider, since it doesn't support implicit grant yet, I'm implementing OAuth web application flow instead.

  • When a user login with GitHub, the api server will redirect the user to Github's authorize page
  • Then redirect back to api server with the authorization code
  • Then api server will try to obtain access_token for this user with that authorization code
  • Then api server will use the access token to get user's profile, which contains a login(username), and use that login as username in our system.
  • The api server then generates a new access token(jwt) for the user, the user will need to use this token for future requests
  • Till now, the only step which is missing is to pass that access token back to client side
    • Method 1 [Selected]: Redirect to frontend app with access token in the URL query parameter, this is similar to implicit grant, which has its own security issue
    • Method 2: Use session (not ideal, since it's not stateless).

Testing

  • Frontend: use Enzyme to test stateless components
  • Backend: use Jest to test services, models, data-access layers.

Frontend Overall Architecture

Using React Hooks in conjunction with useReducer(), useContext() to manage application state.

Backend Overall Architecture

Applying practices of Uncle Bob's clean architecture, but due to limited time I have to design the API system, the implementation is not so "clean" after all(e.g., db part) and should be considered twice if it's gonna be used in production in large scale.

It looks like Dependency Injection in a way, under each layer(folder), there is an index.js to configure the dependencies for other functions in the same layer.

The benefits: Separation of concern and high flexibility for changing implementation of each layer, for example if we want to add another talks db layer, we can just add it in data-access layer and configure it under services layer's index.js file.

The drawback is there are much more boilerplate code, just to take care of different layers of a simple create talk action, it takes hundreds lines of code compares to tens of lines if we just want something quick.

JavaScript Code Style

On top of some of the best practices, here are a few opinionated JavaScript code style used in this project:

  • Use named exports over default exports
  • Normal functions and arrow functions both can be used, function keyword for easier naming and arrow functions for easier management of this scope.

test-fullstack's People

Contributors

rankun203 avatar makara avatar fraserxu avatar flyingant avatar

Stargazers

Roman avatar  avatar

Watchers

James Cloos avatar

test-fullstack's Issues

Ranging method performance issue

zrevrangebyscore([ 'talk:index:votes', '+inf', '-inf' ]) +22ms
  • Need to check if it's some code between log is taking time or it's Redis operation which is taking time.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.