🎭 A Full-stack Meme Generator with React Hooks + Express 🪐
Tags: showdev, webdev, react
Published: 2020-06-02 09:52:19

Hey guys :smiley:

I finally released the first version of my personnal project called [Meme Studio](https://www.meme-studio.io), a __simple__ and __fast__ website to __create and share memes__. It's been created in __Typescript__ (and a little bit of Javascript) with __React.js__ for the frontend, and __Express.js__ for the backend.

2 languages available : __English__ and __French__

Website : https://www.meme-studio.io
Github repository : https://github.com/viclafouch/meme-studio

![Meme Studio](https://dev-to-uploads.s3.amazonaws.com/i/zejyo6eslr4d6y4zjjj8.gif)

Here a list of some packages I use for __Meme Studio__ : 

- [React](https://github.com/facebook/react) - For building user interfaces
- [React-Helmet](https://github.com/nfl/react-helmet) - Manage the document head (`title`, `meta-description`, `lang`, etc..)
- [React-i18next](https://github.com/i18next/react-i18next) - Internationalization
- [React-Router](https://github.com/ReactTraining/react-router) - Declarative routing for React
- [React-Loadable](https://github.com/jamiebuilds/react-loadable) - Loading components with promises (code splitting)
- [Immer](https://immerjs.github.io/immer/docs/introduction) - Create a immutable state by mutating the current one
- [ExpressJS](https://expressjs.com) - Server side
- [Sequelize](https://sequelize.org) - Database

The development lasted about 7 months, I wanted to create something quite complete and to be able to improve my skills in React and more precisely with the Hooks (the current version is the __16.13.1__).

Below are a few lines of interesting code for the development of the application (__available on desktop and mobile__). 

## Backend

### Database tables (3)

A __Meme by definition__:

![Model Meme](https://dev-to-uploads.s3.amazonaws.com/i/7hjzzww9nsjb1rnwwd4h.png)

A meme can be customized with texts and we can change its color, font size, shadow, text align, etc...

We can also change a position of a text by moving it. A text can be duplicated, removed or added.

A __Text Box by definition__:

![Model TextBox](https://dev-to-uploads.s3.amazonaws.com/i/o5oga8m9j24yfgq4p6mz.png)

And for the translation, I created another table with a relation to a Meme model (So we can search for a meme in the application).

![Model Translations](https://dev-to-uploads.s3.amazonaws.com/i/rzknq667wpf7cazs7i4d.png)

A Meme Model can have multiple translations (FR, EN_GB, etc..) and text boxes.

Here the relationships : 

![Sequelize hasMany](https://dev-to-uploads.s3.amazonaws.com/i/xy5p0ge8y15a1cntbnb2.png)

### REST API

It's a simple __REST API__ and I'm only using 2 routes using [Express.js](https://expressjs.com) :

* `/memes` to get the list of meme available.
* `/meme/:id` to get details of the selected meme including its text boxes.

The API also uses [express-validator](https://express-validator.github.io/) to check the parameters sent in the request. For example, for my pagination, check that the `page` parameter is a number ; check that the `id` parameter of a meme exists in the database; ...

![Express Validator](https://dev-to-uploads.s3.amazonaws.com/i/a17rc7ns8x2ffc7c4tf4.png)

## Frontend

Front side, that's the part that took the longest time.

I had to create a global state because the components were getting deeper and deeper. I used the __React Context API__, using [Immer.js](https://immerjs.github.io/immer/docs/introduction) to manage the immutability of my objects.

Below the interface of my editor state (everything related to the canvas display):

![React Context API](https://dev-to-uploads.s3.amazonaws.com/i/b6vd94zwnzgx4uaf3kaf.png)

To create the textual content of a meme, I use the `<canvas>` element.

`<canvas>` is an HTML element which can be used to draw graphics via scripting (usually JavaScript). This can, for instance, be used to draw graphs, combine photos, or create simple (and not so simple) animations. I use this element for creating a combination of text + photo.

Take a look at the documentation of the `<canvas>` element [here](https://developer.mozilla.org/fr/docs/Web/HTML/Element/canvas).

Note that each time you customize the meme (example: edit the text color), the canvas need to redraw everything from 0. 

Below is the effect hook to draw the meme customization.

![React useLayoutEffect](https://dev-to-uploads.s3.amazonaws.com/i/uc6olaovkcrxtrh2tfaq.png)

For those who use canvas in their project, I strongly advise you to follow [these recommendations](https://developer.mozilla.org/fr/docs/Tutoriel_canvas/Optimizing_canvas) in order to optimize the performance of your application.

After creating your meme, you have 3 choices (for now) : 

* __Download the image as a PNG file__
* __Copy your image to the clipboard__
* __Share directly on Twitter__

![Developer Meme](https://dev-to-uploads.s3.amazonaws.com/i/td3yefvdo65yd6zeddhv.gif)

You've seen some of the application code, but you can have a detailed look at this GitHub link: https://github.com/viclafouch/meme-studio.

[Meme Studio](https://www.meme-studio.io) is an open source project that you are free to contribute.

I appreciate any feedback and suggestions.

Take care !