Keep Umbraco Simple
At the 2016 London Umbraco Festival, Per Ploug gave a great talk on keeping Umbraco simple. His message was that over-complicating things deters new users from adopting Umbraco.
"Keep Umbraco simple... or I'll break your arm"
I can certainly agree with that, albeit without the threat of Per sending the Umbraco boot boys round. At Pixel to Code, around 50% of my time is spent helping agencies out with Umbraco sites they've built or inherited that have failed the user in some way. Sometimes the code isn't maintainable, sometimes the back-end is too complicated for editors to understand, and sometimes the designers just didn't deliver what the customer wanted.
Now I'm a bit of an Umbraco Luddite. I'll stick to vanilla Umbraco unless there's a compelling advantage for the user in using a package or external component. If possible I'll use just a set of generic and modular document types, the default data types, a minimal number of views, and a few tricks I've picked up over the years. One such is a kind of homemade Grid / Nested Content substitute, putting content elements into the tree and rendering them with a recursive script.
It's simple, but it works. It's fast, flexible, and scaleable (if you're careful), and it's easy for editors to get their heads around.
So Per's talk got me thinking. Just how simple could I make this? Like the old 5k challenge, what's the least code necessary to build a viable Umbraco site?
To find out, let's cook up a 30-minute website.
Just five document types, using compositions to share properties across the content types
A Master layout
A Page view, and a partial view for each of the other content types
A razor script to glue them together
In Document Types, create a composition called MainContent, with Heading, Intro, Image, and BodyText properties
Create document types, all using this composition, as following:
Page - all pages will use this doc type. Add properties for SEO and umbracoNaviHide.
Section - spans the full width of the page and contains other content items
Block - a cell within a section spanning a specified number of columns
Collection - a list of other items that may be sorted and paginated, and includes properties such as Items Per Row, etc
Article - a basic list item, that can be used or extended for particular duties such as a news item, so includes additional properties such as a Date
Set permissions so that allowed content on a Page includes Sections and Collections, Sections allow Blocks, and Collections allow Items.
Create a Master layout, perhaps based on the basic layout supplied by Bootstrap. Add code to render the header and footer using Macro Partial Views. If you like, use CachedPartial to speed things up.
The RenderBody() call renders the inherited content, which will be our Page view, the default template for the Page document type. After rendering the page properties (taking care to check for a value so the user can leave properties blank without rendering empty tags), insert code to call the following macro partial view:
Like eggs in a cake, BodyContent.cshtml binds the content together. It looks through the page's children, recursively, and renders each in turn using an associated Partial View named to match the document type. If needed, you can use a ViewDictionary with RenderPartial to pass parameters from the parent.
IEnumerable<IPublishedContent> selection = Model.Children.Where(c => c.DocumentTypeAlias!="page");
@foreach (IPublishedContent item in selection)
So let's say, a page has two Sections, each containing a number of Blocks. BodyContent will render the Page, then the first Section, then the Blocks in that Section, then the second Section, then its Blocks. The partial views for each of the content types contain just the code necessary to render the item and are all fairly similar, differing only where rendering specific properties. Each view calls the BodyContent partial on its own nested items.
In this way, page elements can be added within the content tree, and nested to as many levels as required. You can save using templates for what they were really intended for, where there are large numbers of pages with an identical layout.
The proof's in the pudding
For editors, it's easy to locate content as the structure on the page matches the structure in the content tree. All the Umbraco actions like Copy, Move, Delete and Rollback are available so editing is an intuitive process.
For developers, the added flexibility means you can prototype page layouts and change things quickly without changing code. Adding a new content type means just creating the new document type and view, and setting permissions to allow it to be used in the tree.
In total, the views and partial views are 35kb. Not quite 5k but not bad.
Here's one we made earlier, and you can even log in to the backend with login 'writer' and password 'pieceofcake'. I won't pretend that this is production-ready code, the actual codebase I use on new sites is more extensive but works on similar lines. There are modules for a bunch of common patterns like sliders, tabs, accordions, galleries, tables, etc; there are scripts for search, content re-use, pagination, forms and error alerts; and a number of standard page layouts and alternative content views. There's even some compiled code...
As Per said, there's nothing wrong with complexity, but you should be able to put it aside until you need it.