/paint-app

A paint app with front end in React and backend in NodeJS

Primary LanguageJavaScript

paint-app

A MERN stack paint app

How to use

Note: Instructions are currently only verified with MacOS.

Pre-requisites

Make sure you have

  • mongodb-community installed
    brew install mongodb-community
    brew services start mongodb-community
  • npm installed
    brew install node

You can install MongoDB Compass to view the collections for paint-app on a UI.

Steps to Run

Once in the project folder -

  • To run the React app -
cd client
npm install
npm run start
  • To run the ExpressJS app -
cd server
npm install
npm run dev

Project Features

Register page [ /register ]

Alt text

This screen lets a user register

  • User can register using email and password.

Login page [ /login ]

Alt text

This screen lets a user login

  • Login using email, password returns a jwt.
  • Redirect to login if unauthenticated user accesses protected routes.
  • Verify login status for protected route using jwt from local storage on page load.

Home page [ / ]

Alt text

This screen shows a gallery list of all drawings that are owned by the user and those that are publically/privately shared with the user.

  • Show the user’s details (email currently).
  • Show all user drawings and other drawings(publically available or privately shared with them). Features for each gallery list item:
    • Show creation timestamp.
    • Show time it took to draw.
    • Show thumbnail of the drawing itself.
    • Allow a user to delete their drawing.
    • Allow a user to share their drawing.

Paint page [ /paint ]

Alt text

This screen allows the user to create drawings and save them as publicly available or private drawings.

  • User is able to choose colors (at least five).
  • User is able to change the brush’s stroke width.
  • Special “Eraser” brush.
  • User is able to choose whether this drawing is public or private.
  • Create video of first 4 seconds of drawing once started. To access scroll down on the paint page. [Not complete]

Main Technical choices

  • Wrapped the App component with a Auth context provider exported using a custom hook. This allows for us to globally provide authentication state to every component that needs it. (explain)
  • Local storage to store user data and access token. This was done to provide for a simpler way of getting user data and JWT.
  • Chose Mongodb as the database solution on the basis of ease of setup and use with modiying data model schemas based on requirement and ease of querying in real time.

Design decisions made in the interest of time

  • Paint page route is protected and navigates you to login page if user is not authenticated instead of requiring auth only when user is trying to save drawing.
  • All routes in expressJS app are in the index.js page instead of routes based on paths managed by a router.
  • Used mongodb as persistence layer for images. Drawings are stored as a string that is Base64 encoded in png format. Prioritized the handling rasterization, it's persitence and working with rasterized drawings based on device display sizes as an enhancement.
  • Focused more on web experience than mobile experience.

General Architechture

Alt text

APIs

- POST /api/register 
    - body: { email, password}
- POST /api/login
    - body: { email, password}
- POST /api/uploadDrawing
    - header: { x-access-token }
    - body: { name, type, img, drawTime }
- POST /api/shareDrawing
    - body: { userShareEmail }
- GET /api/drawing/:id
    - header: { x-access-token }
- GET /api/getDrawings
    - header: { x-access-token }
- DELETE /api/deleteDrawing/:drawingId
    - header: { x-access-token }

How can I make it better?

Image Peristence

  • Use fabricJS to handle rasterization of html canvas to SVGs while saving canvas.
  • Generate multiple qualities of SVGs while saving to handle different display sizes - small, medium and large.
  • Store canvas svgs in blob storage and metadata including urls for blobs containing SVGs of different quality for the canvas in Mongodb.
  • Here's a comic for why srcset will be good for use here.

React App

  • Making home page a public route where publically accessible drawings can be seen and adding the requirement for protected route where user is needed to be recorgnized for persisting and fetching information on and from the backend.
  • Better styling using bootstrap, styled components.
  • Validation for inputs used across the application.
  • Make painting canvas into a custom hook instead of the current functional component to separate out logic further and make general component look cleaner.
  • Scale pixels for the canvas with devicePixelRatio to make sure canvas looks good on high dpi screens like MacBook's Retina display.
  • Error/Exception handling with better error messaging and UI instead of just try catch blocks.
  • Based on how mouse events are handled on desktop devices for the canvas, handle touch events in a similar way to mobile touch screen devices for the canvas to work for mobile devices.
  • Use quadratic curves for points on the canvas to make it look smoother. More research needed on that and other options to achieve the same.
  • Find opportunities to use Memoized components, debouncing.
  • Analyze re-renders and network utilization for the app for optimization.

ExpressJS App

  • Validation for api inputs/outputs and api documentation using something like Swagger.
  • Save passwords in an encrypted way instead of String using something like bcrypt.
  • Make route separations based on main url path as route folders/files and use a router to handle api verbs for each route.
  • Error/Exception handling with better error messaging instead of just try catch blocks.

What else for production use?

Well, that depends on a lot of things. But considerations can include -

  • Handling authentication/authorization in a completely different way with a separate database table to handle sessions, refresh tokens etc. Also, switching to cookies instead of using local storage for storing jwt tokens.
  • Using a reverse proxy to handle error pages, compression, caching, serving files, and load balancing among other things.
  • Serve images using blob storage service like s3.
  • Host static website.
  • Parameterize global variables into secrets for the front end and backend and store it in a secrets vault.
  • CI/CD process for deploying front end and backend APIs.
  • Logging and monitoring services for client and server.