Yiota Tsakiri, a Product Architect at oDesk, helped lead the development side of oDesk’s recent site redesign. She and her team worked tirelessly to launch the new site—which includes the new blog you see here! Here is an inside look at some of the changes they made.
One of the reasons I love my job at oDesk is because I actually have the freedom to choose and implement technologies I like, while at the same time having the opportunity to impact the lives of millions of people around the world who use our site for their work. In my time at oDesk so far, the visitor site redesign was one of the most challenging and exciting projects I have worked on.
We had to essentially rewrite the entire visitor site, and as a first step of this process, we had to move our homegrown CMS into a more robust and full-featured one. Knowing that we'll eventually need to develop the rest of the visitor site in the same infrastructure, and after benchmarking drupal vs django-cms (see here for the analysis), we picked django-CMS. So currently, all of our static pages are built via our django-CMS installation.
Building static pages with reusable SCSS components
One of our primary goals was to be able to use reusable CSS components in our static pages, so we don't end up with a high level of customized CSS in our static pages. We were using Compass to define CSS components but we wanted to expose them in our CMS also, so we had to create a custom plugin for django-CMS. The plugin includes five basic fields, which you can see here:
And the way this works is as follows:
class SassStylesheetPlugin(CMSPlugin): name = models.CharField(...) css_media = models.CharField(...) scss_body = models.TextField(...) compiled_css_body = models.TextField(...) upload = models.BooleanField(...) def _get_compiled_css(self): compiled_body = scss_compiler.compile_scss(self.scss_body) content = '<style type="text/css" media="%s">%s</style>' % ( self.css_media, compiled_body) if not self.upload: return content return compressor.output() def save(self, commit=False): self.compiled_css_body = self._get_compiled_css() return super(SassStylesheetPlugin, self).save(commit=commit)
Writing static pages this way in our CMS becomes easier and less messy. CMS administrators can @import reusable SCSS components that are globally defined in our stylesheets and use them in their pages. As a result, we can have static pages that are using less CSS code and actually look and feel similar to the rest of the site.
Using S3 as a shared resource
One of the things we always have in mind while developing the visitor site is that we are operating in a distributed environment in the cloud—our services are replicated on multiple EC2 instances in multiple availability zones. As a result, a single server instance failure or even a whole availability zone failure should not impact our reliability.
When admins create static pages or upload content such as images, these files need to be stored in a central location so that they can be accessed by all servers. S3 provides an ideal solution for this, as it is a storage service that can also serve the content directly to the visitors.
Every time a page on the CMS is modified we automatically compile the SCSS to CSS, we create a file and upload it to S3 (just as we do with images and other files) and then just append in the HTML of the page a link to the stylesheet.