Hi there! We are looking for a developer to help us with our ongoing and future projects.
Are you, or do you happen to know a full-stack developer, a WordPress/CMS developer, or a good old web developer looking for a new opportunity? Head over to Hasjob or AngelList to check out the job’s perks, responsibilities, and to apply for the position.
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 designing 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.
One of our recent projects, built on Craft CMS, required support for top-level user profile URLs like twitter.com/miranj and 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 resourceTrigger config setting are treated as a Resource request
All URIs beginning with the actionTrigger config 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 entry object.
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 craft/config/routes.php.
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.
Since this pattern is quite liberal and will match all top level URIs, we placed this as the last rule in our config/routes.php file. The templates/user/_profile.twig 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 templates/user/_profile.twig 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 templates/about/index.twig template should’ve been reachable via /about
The templates/contact.twig template should’ve been accessible via /contact
However both those URI requests resulted in a 404 response due to line number 6 of templates/user/_profile.twig. (Provided there were no users with about or 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' => [ 'template' => 'about/index' ] and 'contact' => [ 'template' => '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 templates/_vanity_router.twig 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.