In this post, I will describe my team’s website (CS 3043 Social Implications of Information Processing) from the technical side.
Before getting into details, a few words about the project itself. As a final term project, each team (4 people) had to choose an emerging technology and analyze it from the class’ topic perspective (ethics, privacy, intellectual property, etc) and come up with some conclusions about the potential future impact of the technology on society. The output of this work is a website and a presentation. In this post, however, I will mostly talk about the technical aspect of the website - what technologies are being used, what frameworks and libraries are used, etc.
Server side
The backend technology used is NodeJS with ExpressJS framework. The reason we have chosen this stack is because NodeJS is lightweight, but yet powerful enough to let us use MVC, view engines and database. We used MVC paradigm, used Handlebars view engine and PostgeSQL DBMS (although eventually we did not need database).
We host the website on our own server (provided by DigitalOcean).
We use NGINX as a reverse proxy solution.
NGINX listens to incoming requests to ports 80 (http
) or 443 (https
) and passes the request to the node server.
We also use encryption on our website for security reasons.
Although we do not ask user for any sensitive information (like passwords or credit card numbers), TLS still protects a user from some attacks, like Man-in-the-Middle attack.
We use LetsEncrypt DV (domain validation) certificates to enable https
connection.
Here is the excerpt from the NGINX configuration file.
server {
server_name socialimps.dbogatov.org;
# redirect to HTTPS automatically
include /etc/nginx/snippets/http_redirect.conf;
}
server {
access_log /var/log/nginx/socialimps.dbogatov.org.out.log;
error_log /var/log/nginx/socialimps.dbogatov.org.err.log;
ssl_certificate /etc/letsencrypt/live/socialimps.dbogatov.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/socialimps.dbogatov.org/privkey.pem;
server_name socialimps.dbogatov.org;
# ciphers
include /etc/nginx/snippets/ssl_config.conf;
location / {
proxy_pass http://localhost:5003;
# headers
include /etc/nginx/snippets/proxy_pass.conf;
}
# make .wel-known location available, so that letsencrypt can renew certificates
include /etc/nginx/snippets/letsencrypt.conf;
}
We used to use PostgeSQL database, but we eventually decided we did not need DBMS. Most of the content on the website is static, and database has some technical costs, like
- connection overhead
- security threats
- installation requirement (site will not run, unless valid connection string provided)
- migrations
Client side
Handlebars view engine was chosen as it is well-documented and we were familiar with it at the time.
We have master page main.handlebars
which has head, header and footer.
Each .handlebars
page is then combined with master page to produce a valid .html
.
We use Google Analytics (and state it explicitly in our Cookie Policy) to understand how users behave on our website, so that we can improve user experience.
Pre-processing
We are planning to pre-process our assets to optimize the load time. Although no implemented by the time of writing, we will use Gulp to run task like:
css
,js
minificationless
compilation- TypeScript compilation
- concatenation
Bower components
We make use of third-party JS/CSS libraries for various tasks:
bootstrap
- general layout (our main client side framework)cookieconsent
- have a banner on the bottom asking users to read our Cookie Policyundesrscore
-template
feature (bootstrap timelines, media cards)amstock3
- BitCoin price chart on the home pageMathJax
- display equationscomponents-font-awesome
- icons
Bitocin Chart
As a bonus feature, we have implemented a real-time BitCoin price chart.
It gets data from our server (which, in turn requests it from two different APIs), and displays it in a beautiful form (thanks, amstock3
).
The data gets computed every time user requests a page, therefore, we call it real-time.
Underscore template
Some pages on out website, like timeline, topics or popular media, contain a number of similar nice looking elements (usually, cards).
As true programmers, we hate code repetition (and repetition in general), so we decided to use underscore
library, and specifically, template
routine.
This routine lets us define a template, like this:
var template = _.template(" \
<!-- Timeline item starts --> \
<div class=\"timeline-item\"> \
<!-- Timeline circle --> \
<div class=\"timeline-circle bg-blue\"> \
<!-- Date --> \
<span><%= month %></span><%= year %> \
</div> \
<!-- Content --> \
<div class=\"timeline-content\"> \
<h4><%= content %></h4> \
<p> \
<% if (reference !== \"#\") { %> \
<a target=\"_blank\" href=\"<%= reference %>\">Reference</a> \
<% } else { %> \
<br /> \
<% } %> \
</p> \
</div> \
<div class=\"clearfix\"></div> \
</div> \
<!-- Timeline item ends --> \
");
and generate html
with certain data like this:
[{
month: "Nov",
year: 2013,
content: "Bitcoin reaches a value of $1000",
reference: "http://www.theverge.com/2013/11/27/5151396/bitcoin-hits-1000"
}, {
month: "Dec",
year: 2014,
content: "Microsoft begins to accepts Bitcoin",
reference: "https://blogs.microsoft.com/firehose/2014/12/11/now-you-can-exchange-bitcoins-to-buy-apps-games-and-more-for-windows-windows-phone-and-xbox/"
}, {
month: "Sep",
year: 2016,
content: "Our team started working on the Bitcoin project",
reference: noref
}]
.forEach(function (element, index, array) {
$container.append(template(element));
});
This way we not only avoid code repetition, but also keep code more maintainable.
For example, if we want to change some html
for all cards, we modify code once.
Conclusion
This was a high-level overview of the technical side of our work. There are more little nice software things we did not mention (like continuous integration, for example), but you are welcome to check it out source.
Finally, let us show off a little bit:
- Speed: we are scored 99% on gtmetrix.com
- Strucutre: we pass (no errors, no warnings) W3C Validator
- Security: we are scored A+ on ssllabs.com