How to create a signature-generating app with React

Alexandr Lavrentyev
Level Up Coding
Published in
6 min readMar 29, 2021

--

Remember when business cards were a big thing? And when I say big, I mean — BIG. Even movies sometimes had a whole scene concentrated on a business card only.

No, I don’t mean it’s not a thing anymore. Rather, I suppose you can safely say that it loses a bit of the charm in the new era. Of course, it’s not the same everywhere — at least in Japan, they’re still serious about meishi. Sometimes, however, business cards became something different and a very unique thing — when they’re trying to get away from boring pieces of paper.

And here is the most interesting point. What could be used as an electronic business card today? The most straightforward answer is — email signature! It’s a very simple yet effective way to receive additional or even primary data about the sender. For example, it could be a company name, position, skype, telephone number, et cetera.

Why would you even need the email signature? To tell it super-shortly — to increase your business value. You can easily impress people with it in the same way you could impress them with a business card. You, your brand, and your company can become more well-recognizable with an interesting email signature. Finally, a distinctive email signature can help you with growing trust by letting people know who exactly maintains email correspondence with them and it could be a kind of auxiliary security feature. And don’t forget about saving trees!

How could you create an email signature as a person and as a company? There are 3 ways to do it:
1. Create it right in the Gmail settings section, using provided visual redactor — far away from being called user-friendly. Also a very time-consuming process.
2. Utilizing some HTML-signature template, created by someone else. Not bad, but where and how would you store that template?
3. Create a web application for that case!

So, now we’re going to build a signature-generating app (a kind of internal site for some fictional company), using React and Material UI (I choose it just for faster development, you can use a different framework or don’t use a framework at all and work directly with СSS). It would be capable to generate two types of signatures, based on provided information — with and without a photo. Other info would include full name, position, telephone, skype, and social networks links.

Let’s create a project with the create-react-app tool. I would also like to use typescript and yarn package manager. Of course, you can use npm and plain javascript. Go to your designated projects directory and type npx create-react-app signature-generator — template typescript — use-yarn. You do have node (in this project I used v12.14.1) installed, right?

Navigate into the signature-generator directory. You can safely remove the logo.svg file and remove all content in the files App.tsx, App.css and index.css. The next step is the installation of Material-UI core—type yarn add @material-ui/core. We must also use Roboto font — go into public folder and add <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" /> to index.html (put it into the <head> tag). And the last thing is Material-UI icons — type yarn add @material-ui/icons. Finally, preparation is over, it’s time to code.

First of all, let’s create our state interface and initialState:

export interface PhotoSignatureProps {
fullName: string;
position: string;
skype: string;
phone: string;
photo: string;
}

interface State extends PhotoSignatureProps {
withPhoto: boolean;
copied: boolean;
}

const initialState: State = {
fullName: "",
position: "",
skype: "",
phone: "",
photo: "",
withPhoto: false,
copied: false,
};

and hooks for that:

const [state, setState] = React.useState<State>(initialState);

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.name === "withPhoto") {
setState((prevState) => ({
...prevState,
[event.target.name]: event.target.checked,
}));
} else {
setState((prevState) => ({
...prevState,
[event.target.name]: event.target.value,
}));
}
};

As you can see, for the sake of simplicity, the photo is actually the URL of some image, withPhoto is a flag of photo existence, and copied is a flag for visual approval of copy operation. The other fields are pretty straightforward.

Then it is time for form with input fields:

<form className={classes.root} noValidate autoComplete="off">
<TextField
fullWidth={true}
required
label="Full Name"
value={state.fullName}
name={"fullName"}
onChange={handleChange}
autoFocus={true}
/>
<TextField
fullWidth={true}
required
label="Position"
value={state.position}
name={"position"}
onChange={handleChange}
/>
<TextField
fullWidth={true}
required
label="Skype"
value={state.skype}
name={"skype"}
onChange={handleChange}
/>
<TextField
fullWidth={true}
required
label="Telephone"
value={state.phone}
name={"phone"}
onChange={handleChange}
/>
...
</form>

Let’s choose a logo. I used this one and place it into assets folder. I’ve also added social network links and logos — for Twitter, LinkedIn, Facebook, and Behance.

Few hints:
If you're using static images (like in this project):
a) no SVGs - gmail proxy block it and gmail generally don't support it;
b) no base64 - gmail don't support it and don't forget about global limit of 10000 symbols for web-based clients and 12000 for desktop ones (and base64 are usualy really long)
c) don't forget to disable react-scripts\webpack function of converting small images to base64 utilizing environment variable IMAGE_INLINE_SIZE_LIMIT
d) don't forget to write homepage in package.json or use PUBLIC_URL environment variable

Finally, it’s time for a signature template. Here are useful tips for that.

Hint:
Forget about complex fancy divs. Mr. table is our best friend here.

To make it simpler, we would have a logo or photo on the left side, then a long vertical line and 5 rows with full name, position, skype, telephone, and social networks links (my links are just home URLs of them), something like that:

<table cellPadding={0} cellSpacing={0} className={"signature"}>
<tbody>
<tr>
<td rowSpan={5}>
<img
className={"main-image"}
src={props.photo === "no-photo" ? Logo : props.photo}
alt={""}
/>
</td>
<td rowSpan={5}>
<div
className={"vertical-line"}
/>
</td>
<td>{props.fullName}</td>
</tr>
<tr>
<td colSpan={3}>{props.position}</td>
</tr>
<tr>
<td colSpan={3}>Telephone: {props.phone}</td>
</tr>
<tr>
<td colSpan={3}>Skype: {props.skype}</td>
</tr>
<tr>
<td colSpan={3}>
<div className={"social-logos-frame"}>
<a href={"https://twitter.com/"}>
<img src={TwitterLogo} alt={""}/>
</a>
<a href={"https://www.linkedin.com/"}>
<img src={LinkedInLogo} alt={""}/>
</a>
<a href={"https://www.facebook.com/"}>
<img src={FacebookLogo} alt={""}/>
</a>
<a href={"https://www.behance.net/"}>
<img src={BehanceLogo} alt={""}/>
</a>
</div>
</td>
</tr>
</tbody>
</table>

And don’t forget to add some CSS so it would look better!

Hints:
1. Not all fonts are supported by gmail. Do your research before.
2. All hyperlinks would be displayed in default way. Try to use an image as a link.

Last, but not least — put things in order in public folder, README.md and package.json. Serious guys have their own favicons and all descriptions, isn’t it? And you’re done! This is the result:

And the signatures — with company logo and with photo:

The full code can be found here. And the working example is here.

Thoughts:
1. Email signature isn’t really simple but it’s far away from being a very complicated thing.
2. This project is still pretty much the skeleton of the completed product. You can (and probably should) offer users different templates in various designs, give them the freedom to add more stuff, handle photos as files, and many more.
3. React is a very easy, useful, and powerful instrument. Just like always.

Well, thanks for reading! Please, share your opinion in the comments and follow me for more. And don’t be afraid to ask questions, if something is not clear.

--

--

Traveler, dreamer, programmer. I'm interested in thousands of different things, from data visualization to seasteading.