We’d long known that the web was about embracing flexibility and about a dynamic, infinite canvas rather than fixed paper sizes. There were a fair share of designers practising this too by desiging fluid, scalable websites. To the mainstream however, embracing flexibility meant little beyond supporting a few different browsers and two different screen resolutions.
That was then. It’d been three years since the iPhone’s release. Tablets had made their debut, but smartphones were about to reach critical mass. Diversity in the shape, size and form factor of devices accessing the web was now a ripe reality. And Ethan struck on hot metal with the idea to “design for an optimal viewing experience” by querying for and adapting to the user’s environment.
While responsive design might’ve initially arrived as a primer on using media queries, it feels more like a philosophy than a specific technique. The philosophy being, to recognise and build for web design’s known unknowns, to secede certain control to the user, meet them in their environment of choice rather than dictate one particular context on to them via your design choices.
The responsive web design philosophy fits so well with the principles of the web that it is now as ingrained in our processes as using CSS instead of
<table>s for layout.
If you’re getting a new site made, or getting one revamped, go read “How Long Should Your Website Last” by Mike Swartz. Few are clear in their heads if their website is an investment or an expense. This article does a great job at setting the right direction.
Your website has got three core layers: content storage, content management interface, and forward-facing user experience.
The forward facing experience is what most people think of as their “website”. It’s the layer that goes out of fashion merely in 18 months. Another other important take away from that article is that the choice of CMS becomes very critical to determine longevity of investment.
A typical content management system controls all three layers together, and they move in lock-step. Not ideal, but that is how things are. Through the life of a website the content types & storage probably won’t change much. Big perceivable changes happen in other two layers. Therefore the content storage layer must be very well considered. A CMS switch later is expensive, especially the data migration effort.
Hopefully this will be discussed in the upcoming CMS Conference.
One of our recent projects, built on Craft CMS, required support for top-level user profile URLs like
instagram.com/_basestation (also commonly known as vanity URLs). While Craft offers a fair amount of flexibility for routing requests, implementing vanity URLs wasn’t particularly straightforward. This post is a run-through of how we worked our way around it.
To begin with, the routing precedence in Craft is as follows:
- All URIs beginning with the
resourceTriggerconfig setting are treated as a Resource request
- All URIs beginning with the
actionTriggerconfig setting (or POST parameter) are treated as an Action request
- Any direct URI matches with Entry or Category (or any other Element) object URIs are treated as an Entry/Category/Element request, wherein the corresponding Entry template is loaded with a pre-populated
- The first successful URI match against user declared regular expressions. Craft calls these dynamic routes, and the routes can be declared either via the Control Panel or in
- All URIs that match a file in the template folder(s) when interpreted as a template path.
Given this precedence, the ideal scenario for supporting a user profile page for each User object was to assign our desired URI to the User object. The routing would’ve automatically been handled at the third level (as an Entry/Category/Element request). However, the URI field appears to be unsupported for User objects and we couldn’t figured out a way to change or override that behaviour.
We were left then with the fourth level (dynamic routes). So we added a rule to match all top-level URIs and direct those requests to the user profile template page.
'(?P<username>[^/]+)$' => 'user/_profile',
Since this pattern is quite liberal and will match all top level URIs, we placed this as the last rule in our
craft/config/routes.php file. The
craft/templates/user/_profile.html template looked something like this:
With these two components in place, we started seeing the desired results. Requesting any valid user profile page like
/batman loaded the
craft/templates/user/_profile.html template for Bruce Wayne. So far, so good.
The problem we ran into here was that we had broken template path based routes (level 5) for top level URIs. For instance:
- The template
craft/templates/about/index.htmlshould’ve been reachable via
- The template
craft/templates/contact.htmlshould’ve been accessible via
However both those URI requests resulted in a 404 response due to line number 6 of
craft/templates/user/_profile.html. (Provided there were no users with
contact as their username. (Always a good idea to maintain a username blacklist when dealing with vanity URLs.))
Now one option was to simply declare dynamic routes for
'about' => 'about/index' and
'contact' => 'contact' and place them before the user profile routing rule. This would’ve worked if we had only a handful of templates with top-level URIs, but it would not have scaled very well for a large number of template path routes.
So how did we get around this? By altering the logic to look for a template path match before looking for a username match. We introduced an intermediate template file
craft/templates/_vanity_router.html to achieve this.
And we modified the dynamic route to hand off control to the intermediate template file:
Template paths now take higher precedence than vanity URLs, and that is exactly the behaviour we were going for.
Hope you find this useful for adding vanity URLs to your Craft project. If you’ve taken a different approach or have any feedback on this approach, we’d love to know.
Hear, hear! Maciej Cegłowski (of Pinboard fame) on the bloat prevalent in contemporary web design (even for text-based content). Hardware and networks seem to be getting faster and cheaper, while websites appear to be getting slower, heavier, and more expensive to access.
A Craft CMS plugin to route requests to pages with a filtered, pre-loaded list of entries. Developed by us and spawned off during our IndiaBioscience project. The plugin now handles URL routing for the many varied filters on sections such as Jobs, Events, Grants (and more) on the IndiaBioscience website. Also listed on Straight Up Craft.
Our friend and interface designer Abhishek Nandakumar writes about the value of designing with prototypes instead of static mockups. He uses the example of Google Maps to demonstrate how working prototypes can often reveal counter-intuitive improvements in an interface, like increasing the number of clicks:
Most time is spent navigating and scanning through the interface, but if the interface and the path to your eventual goal are both clear, clicks might not matter, because you’ve reduced a majority of the cognitive load associated with scanning.
We’ve felt the same for a long time, and hence prefer designing our sites in the browser as often as we can.