Bootstrapping a CMS in 24 Hours
IntroductionMy name is Andre Alves Garzia and I am 31 years old. I started coding in LiveCode when I was 23, my first big personal project was creating a Web Server written 100% in LiveCode. This project got me visibility and was very fun to work. After that I started working more and more with CGI and server side stuff to the point where I basically cornered myself as a "server guy" which was OK by me, I liked working with servers (before my Mac, my main machine was a NetBSD).
After some time I started consulting for clients that wanted to build CGIs with LiveCode. I developed my own set of libraries for CGI development and they were put to good use into production environments with great success. My business flourished and I purchased a domain with my name and built a simple page. The page was static. The page was not built with LiveCode at all. I was selling LiveCode web stuff but I was not using it on my own page. My explanation was that I didn't need any dynamic content on my website, so it was easier to create it using just a Text Editor then to force LiveCode into it.
Over the years, I've built CMS, Web Editors and more to many clients but my website was still static, no CMS. I've built toy and real content management systems for a living but I was not using my own creations, mostly because they were all custom made to specific needs of clients and would require a lot of reworking to be used by myself alone. I made plans and projects of the perfect CMS to use on my site and started building it many times just to abandon it when I could not longer allocate the time and effort to bring those plans into reality. Every time I looked into my own website I was secretly ashamed of it, not because something was wrong with it but because it could be so much more.
Time marched on and Runtime Revolution released RevServer (now LiveCodeServer aka The Miracle aka Andres Dream). RevServer was an engine like the old CGI/Command line engine but with it you could mix and match HTML and LiveCode Script, you also had access to some really useful functions and variables such as $_POST. Hours after RevServer was released, I created the first CMS for it. It was called Tomato CMS and it worked fine for a piece of couple hours work. But in my infinite wisdom, I didn't used it for my own site, don't ask me why, I don't have a good answer.
As I've said, the fact that my site was not using any of my own creations was bad for me, specially because every now and then I wanted to create something on the site and had no way to do it. On July 8th, I decided I had enough, my site last update was four years in the past, this was enough, I was going to build myself a new website and CMS using LiveCode Server and I decided it would be ready in 48h...
Choosing the tools of the tradeThe project started with a 48h deadline because if I allowed myself infinite time, the project would never ever be ready. Since time was of essence, I decided against reinventing the wheel and went on to evaluate the current web frameworks available for LiveCode Server:
The first option was insanity, the code would soon turn into spaghetti and would be unmanageable from the start.
The second option was at the same time comfortable and stupid. It was comfortable because I am the author of the framework. I know every line there so it is fairly easy for me to debug and extend based on my own needs. It was also stupid because I created that framework not for building web sites but web services. I mean web services used for faceless APIs like Twitter API, Facebook API and the like. RevSpark excels on creating web services to be consumed by other tools, it has no features for building web pages, databases, sessions or other high level stuff. It is a very good framework for small tools and for building APIs but it is not aimed into building full blown CMS. If I went with RevSpark, the amount of features that I would need to add to it would basically duplicate RevIgniter and that brings us to...
The third option was a framework that I was not the author. RevIgniter is the child of Ralf Bitter and what a beautiful child it is. Ralf raised the bar on the state of the art in LiveCode web frameworks. Inspired by PHP CodeIgniter, he went on to create RevIgniter. I will not enter in details of RevIgniter but basically it has everything, it has a solid design and the best documentation in any LiveCode project. I think I was one of the very first users of RevIgniter. I made many projects with it and am now as comfortable inside it as if I was Ralf. Actually, I fell so comfortable inside it that once I was coding in PHP CodeIgniter for a client and found a bug in CodeIgniter, I knew in which file the bug was because I was so familiar with RevIgniter and they are so similar that my knowledge was instantly transferable but that is another story. Armed with RevIgniter as my main tool, I went on to ignite my new website.
Choosing what NOT to useThe very first thing I decided was not to design the template for the website from the scratch. Even though I work in a company famous for its design work, we were all full of projects there for me to pressure one of our designers to create a design for me in 48h.
I went on a popular template site and purchased a template to work as a starting point. The template came in a zip file with all the XHTML, CSS, JS and PSD files needed. It took me some hours to customize it to my taste.
Wise choice: instead of designing template from scratch (it would take more than 48h) or asking one of our designers (it would take him more than 48h to be able to stop and help me), I purchased a template and worked from there. Saved me hours.
My second choice of something not to use was Databases. Don't get me wrong, I know how to use databases, I just did not see the need for a database on my CMS. If you decide to store your pages inside a database then you need to build the following things:
There was no way I was going to do all that in 48h. There was no advantage at all in the use of databases. We often overuse and over-engineer technologies. Even the most simple websites have lots of XML and Databases in them.
Wise choice: By not using databases when they are not needed, you cut a lot of complexity.
The planI had a clear picture of what I wanted and had made my decisions on what technology to use (RevIgniter) and what not to use (MySQL or any other SQL). The next step was to make a simple plan so that I would have something to compare my work with.
My plan was to have a main page that would "advertise" my works and services and a subpage strategy where I could create subpages and pin them to some navigation thus creating a site with a lot of content. This process of creating a new page and pinning them to navigation should be easy or I would end up not using my new site at all.
Architecture note: First thing to do is to decide how you will store your content and how you will retrieve the data back so that it is easy to work with.
If there is one place where LiveCode is King it is text manipulation. I decided without any doubt that I would store my website content using plain text files and would use LiveCode to pick those plain text files, process them and glue them back into the template. All my web pages would simply be ".txt" files in a special data folder.
It was also obvious that the first page, the main page, the one advertising my works and services would not be a simple plain text file. The design needs of that page were too different than the rest of the website, I decided to use a special RevIgniter view just for the main page.
Above I show all my views. The site is broken in three stacked components:
The view main.irev is the one with the little slideshow and the grid with services. The container.irev is the one used when we need to glue our plain text content into the website.
Storing the pagesEvery page is stored in a data folder called "data". When you request a page, a RevIgniter controller called Page.irev looks for the page inside that data folder. If it is present then it loads the file and glues it into container.irev view.
It soon became obvious that I needed more than plain text. I could insert HTML inside the plain text files to make items bold or italic and the like but I wanted more than what simple HTML could provide. I wanted dynamic sidebar menus, text and more. If I simply placed the necessary HTML to build the sidebars inside the plain text files, I would break the reusability of those files if the design changed. Also writting a lot of HTML inside text files is boring.
To solve that I created what I call @commands (in portuguese I call them arrobolhas, it sounds fun in portuguese). "@commands" appear alone in their lines, they are always the first word in the line. Like this:
My page parser would locate the commands and place them inside the correct place in the template, if I change the template, I don't need to change my source content files.
Wise choice: creating design agnostic file formats makes it easy to change things later.
For example the box above is an @command, look:
Now using these @commands, I can create all the page elements I need such as boxes, menus inside the page and more. The simple textual styling is done with HTML and CSS.
Page loading workflow:
Thanks to this architecture decision, creating new web pages is as easy as placing a new text file in the data folder. Deletion and editing are obvious operations too.
NavigationFor a while I pondered about how to do the navigation. The first thing I coded were my own RevIgniter routes so that when you accessed a URL like:
It would go to the Page controller and the correct command. With sane and obvious URLs such as the one above, it was easy to decide on how to store the navigation. I followed my database decision and decided to cut dynamic navigation generation out of my CMS. Think about it, why create code to go somewhere and figure out what the menus should be when I know from the start what they should be? All the navigation is in views/common/top.irev and views/common/footer.irev, those files are just HTML. When I need a new menu item, I just open those files and edit them. There is no need for complex menu generation from database or something similar, this is a simple site.
Is built from:
It is all very simple, I just add, remove or delete items from an HTML Unordered list and thru CSS magic they became the menu.
Wise choice: Avoid complexity. If there is a simple way of doing something and you are comfortable with it, there is no need to over-engineer it to cover some feature you will never use.
I am comfortable with HTML so it is OK for me to have my menus as hard coded HTML lists. If this was a site for someone else, I might make different choices but remember, this is not a general purpose CMS, this is a specific solution for myself. LiveCode enables us to create customized software really quickly. I went from deciding on RevIgniter to my text file format and navigation in less than 10 hours.
RecapThe whole website is built with RevIgniter from three stacked components — top navigation, page content, footer — of these components the top and footer are simple hard coded HTMLs. The page contents are dynamically built from source text files that contain a mixture of plain text, HTML and @commands developed to avoid hardcoding HTML display things in the source file.
All this took about six or seven hours of work and most of those hours were used to fine tune the template. but if you look into the site navigation you will spot something that was not covered before:
Before explaining how the Blog component of the site is built, let me explain why this is important. Actually this is so important that it deserves its own H2 title.
BlogThe main problem with my static site was it was really hard to update and add new content. My new website with its text file easiness made it all quite simple but there was still a problem, how would users find new content? If I created a new menu entry for every page I add, I would soon end up with impossibly long menus or infinite-matrioska nested menus, both options would badly harm my site. These days, sites need to have fresh content as often as possible. This is needed if you want your users to keep coming back. The best option for always fresh content is to have a blog inside your website. Whenever you have something interesting to talk about, you can post a new item to your blog, users will keep checking your site, waiting for your articles. Blogs don't need their entries to appear in the main navigation so they keep your menus clean. I think everyone should have a blog.
I already had a working website and decided to add a blog to it. I could embed some third party system such as Wordpress on my website and be done with it but I am a LiveCode developer selling custom made LiveCode server tools. I've got to eat my own dog food! One option was to create a new RevIgniter controller for the Blog and a new system and the navigation would link to this other controller. This would be a good option depending on my needs but I still wanted to finish my site in 48h and I had already created a very flexible system with the text files and the @commands. There was no reason to throw all this away and build a blog from the scratch.
Wise choice: Instead of a brand new blog system, I just used what I had in the form of plain text files and @commands.
Every post in my blog, including this page, is just a text file in the same place as the rest of the pages in the website. There is no difference between a blog post and a normal web page in the site but I am not linking to the blog posts inside the menus, so the entries don't appear in the navigation.
When you click Blog in the menu you load the blog page, it is just a text file with @commands in it but it has something more, it has some dynamic LiveCode script in it that opens all the text files in the data folder and loops looking for @blog command in them. If it finds this command, it includes the page in the blog display, thats all. The only thing that a blog post has that the other pages don't is the @blog command inside it. I also created an @cut command so that the blog display will show all the content from the entry up to the @cut command and then it will display a Read more link. A blog entry looks like this:
This file would be picked by the blog page and its first paragraph would be shown. If the user clicked the read more link, he would be redirected to the Page controller displaying the post content just like a normal page.
With just that, I harnessed the power of my simple plain text file storage and created a simple blog system. The only extra code is the loop that builds the blog page dynamically.
To order the blog posts in reverse chronological order I use a shell() call. Instead of using the files to get a list of files in the data folder, I use shell("ls -rt") which lists the files in reverse chronological order, I just loop through the results. To pick the dates for display, I use shell("stat").
And that was how the most complex part of the website was built. The blog will keep my content fresh and in reality it is the same as the other pages, just a little bit more dynamic because it creates an index of posts based on a reverse chronological list of files.
ConclusionI was so afraid that I would not be able to finish the site in 48h that I made decisions that would enable me to work quickly and maximize my code reuse. I've opted for RevIgniter instead of rolling my own CMS grade web framework, I've opted for text file as a storage medium instead of databases to avoid all the time consuming tasks of building and administration interface, I've opted to create a simple blog system that lists tagged files in reverse chronological order and reuses the simple text file storage for all its needs.
In the end the whole system was created in less than 24h, I think that I worked in it for about 12 hours during my late hours. I am really happy with it.
Word of warning: This is a system that suits my needs, but it might not suit someone elses needs. Being able to build exactly what your client needs is one of the strong points about LiveCode.
Thanks for reading!