Personal Website
Ongoing — Eric Canam

I wanted to create an online resource for potential employers to see a more detailed résumé than can fit on one 8.5" × 11" page. It needed to show consistently colour-styled code samples in various languages, present my contact information securely, and appear visually appealing on both desktop and mobile devices.

Information Security

The whole site is served over HTTPS, but I also offer visitors the ability to see my email and phone number in case they're inclined to call and offer me a job interview. (I'm currently searching!)

To keep this information from being easily obtained by web scrapers and other types of bots, I don't serve it with the initial web response. Instead, visitors are asked to complete a reCAPTCHA. The results are verified with a remote API Gateway, and if it all looks good then the information is sent in a separate secure response.

Asynchronous function to request & show contact info
// tries to validate reCaptcha request
function sendReCaptcha(e){
    e.preventDefault(); // don't submit that form
    document.getElementById("reCAPTCHA").style.opacity = 0.4;
    
    fetch('https://h9x8ss1w06.execute-api.ca-central-1.amazonaws.com/verify_captcha', {
        method: "POST",
        mode: "cors",
        body: JSON.stringify({"grcr": e.target.elements["g-recaptcha-response"].value})
    }).then(async response => {
        if(response.ok){
            let info = await response.json();
            // populate email/phone fields
            document.getElementById("phone").innerHTML = info["phone"];
            document.getElementById("email").innerHTML = info["email"];

            // set download PDF link
            document.getElementById("download_pdf_button").setAttribute("href", "https://h9x8ss1w06.execute-api.ca-central-1.amazonaws.com/get_resume?dtoken="+info["token"]);

            // update visibility of screens in contact page
            document.getElementById("reCAPTCHA").style.display = "none";
            document.getElementById("contact-card").style.display = "block";
        }else{
            // oops! show error splash
            document.getElementById("reCAPTCHA").style.display = "none";
            document.getElementById("captcha-error").style.display = "block";
        }
    });
}

Once the server has validated that the request is genuine, and associated with a likely-human reCAPTCHA score, it sends the information back in JSON.

Also included in the response is a single-use token that is generated to allow visitors to download a PDF copy of my résumé. The page is updated with a link to download the file, which will be valid for 20 minutes and a maximum of one request.

Colour-Styled Code Samples

Code samples showed on this site are auto-formatted on DOM load with a JavaScript function that takes into account the language of the code. This makes page responses way smaller and allows me to update the code without worrying about stylizing it for web browsers.

HTML for a code sample
Inception
...<!-- code sample goes here! --> ...

As the page loads, a JavaScript function parses the DOM for these code blocks, and re-writes their contents using a formatting filter based on rules written for the language specified in the tag attributes.

JavaScript code sample rules
JavaScript: {
    keywords: [
        'abstract', 'arguments', ..., 'with', 'yield'
    ],
    numvals: ['true', 'false', 'null'],
    strings: ['"', "'"],
    comments: ["//"], // more inception?
    closeComments: [["/*", "*/"]],
    brackets: ["{", "}", "[", "]", "(", ")"],
    formatFunc: function(t){
        return formatCode(t, this);
    }
}

Ultra-Compatible Style

The site should work 90% as well for the hyper-vigilant with JavaScript disabled as it does for those with JavaScript enabled. The smooth transitions, seamless pagination and all the element positioning all work purely with CSS.

Smooth CSS transitions and some pagination
@keyframes roll-up{
    0%      {margin-top: 0pt;}
    100%    {margin-top: calc(0pt - (48pt + 2in + 4pt + 16pt));}
}

input#intro:not(:checked) ~ div#in{display: none;}
input#intro:not(:checked) ~ div.head{
    animation: roll-up 1s 1;
    margin-top: calc(0pt - (48pt + 2in + 4pt + 16pt));
}
input#resume:not(:checked) ~ div#re{display: none;}
input#projects:not(:checked) ~ div#pr{display: none;}

Additionally, this website should look just as good on a wide screen as it does on a handheld device. It was designed to show as much detail as possible on various sizes of screen, while reducing clutter on the smaller ones.

CSS stlye modifications for small screens
@media screen and (max-width: 18cm) {
    ...
}