SlideShare a Scribd company logo
1 of 188
Download to read offline
Content Management
   That Won’t Rot
     Your Brain
      Sean Cribbs
complicated



  http://flickr.com/photos/koolgary/2460635163/
Content management on the web can be pretty complicated.
hundreds



 http://flickr.com/photos/carowallis1/485124848/
There are hundreds of open-source content management systems to choose from,
in-completion



http://flickr.com/photos/yakobusan/2436481628/
all in various states of completion.
un-intuitive


     http://flickr.com/photos/mashed_potatoe/65823367/
Most of them have unintuitive user interfaces,
tangled



        http://flickr.com/photos/randomurl/440190706/
tangled content models,
ugly code
         http://flickr.com/photos/flickerbulb/187044366/
and opaque, poorly-architected and undocumented code that refuses to yield to
customization attempts.
content model



These include abominations like ezPublish, which is so in love with its content model
content model



that it seems they implemented the editing interface in the content model.
huh?



         http://flickr.com/photos/fdecomite/402499198/
Good luck figuring that one out.
pluggable


       http://flickr.com/photos/studiosmith/2085278030/
Or Xaraya, that despite its ultra-pluggable code modules with proscribed interfaces
bridge to nowhere



     http://flickr.com/photos/garlandcannon/3048731338/
doesn't seem to do anything it advertises.
template surgery


http://flickr.com/photos/soldiersmediacenter/1148977208/
Or Joomla & Mambo, which require template surgery to create a custom look and feel
everything to
                       everyone


             http://flickr.com/photos/twose/887903401/
while trying to be everything to everyone.
FTP is so 1971


          http://flickr.com/photos/daveseven/167903362/
Why is it so hard to publish a web page that I don't have to use FTP to edit?
web
                          standards



Why can't I use HTML, CSS and the other web standards I know and love?
ideal CMS



So what would I want in my ideal CMS?
#1 :
                                  simple



First, it would be simple to use and understand.
meta is overrated



I'm not impressed with hyper-abstract meta-content models, just make it work.
#2 :
           standards markup



Second, it would let me write markup and presentation in any format and structure I like,
design freedom



giving me the freedom to design my site the way I want.
#3 :
                   powerful tools



Third, it would have simple and powerful tools built-in to make most content-generation
tasks a breeze,
PHP not required



without needing plugin modules.
#4 :
                          clear code



Fourth, it would have a well-architected code design
easy customization



so I could understand and customize it easily.
drum roll please



Fortunately, there's a CMS that lets me do all these things.
It’s Radiant!



It's called Radiant, and it's written in our favorite language, Ruby.
APP DHH
                                   ROV
                                       ED




And yes, even David likes it.
#1 :
                 simple content
                     model


So how does Radiant meet my expectations? First, Radiant's content model is easy to
understand.
Pages



Every Radiant site is made up primarily of Pages,
acts_as_tree




which are arranged in a tree, much like a directory/file structure.
has_many
          :parts



Pages have many content pieces called parts,
logical pieces



which let you break your pages into logical sections
content_for



think quot;content_forquot; blocks in Rails views.
Page-Types
                           (STI)



Any page can have a special type, essentially a subclass of the Page model,
page-level
         plugins



that acts as a localized plugin, modifying the front-end behavior of that page.
Layouts



Pages also have layouts,
design details



which let you abstract common design details, just like Rails layouts,
Content-Type:
                     text/html



and also let you specify the content type - be it HTML
Content-Type:
        text/xml



XML
Content-Type:
                      text/css



CSS, or whatever.
Snippets



To round out the system are Snippets,
render :partial



which are kind of like Rails partials
repetitive



small pieces of common or repetitive content
contextual



that can be rendered in the context of many pages.
Filters



Pages and snippets can use text filters
Textile
                          Markdown
                             etc.


that let you write content in shortcut languages like Textile or Markdown.
template language



This is all tied together with a template language
Radius



called Radius
non-evaluating



that keeps code well-separated from your content.
#2 :
              complete design
                 control


Second, Radiant lets you design your site the way you want.
any text



It doesn't care whether you're publishing HTML, CSS, Javascript, plain text or whatever.
(no binary)



You probably don't want to put binary data in a page, but any kind of text is OK.
tags expose
                      functionality



Most built-in and plugin functionality is exposed through template tags, so you don't have to
worry that some feature will produce bad markup;
write your own
                     markup



you can write the markup yourself.
#3 :
                   powerful tools



Third, Radiant has powerful tools
over 50 tags



about 50 built-in template tags to help you accomplish many content-generation tasks.
navigation, sucker


You can use tags to generate navigation
row-striping



stripe table rows
feed me, Seymor



collate content into a feed
no logo for you!


         http://flickr.com/photos/rafastarix/2729553586/

or display the big company logo only on the homepage.
#4 :
                          clean code



Last but not least, our reason for being here
well-architected



Radiant is well-architected
developer goodies



and has plenty of goodies for developers.
show me the code



Since this is a technical talk, I'm going to gloss over the details of using Radiant to create a
site and focus on how we can customize Radiant to our own needs.
Extensions



To this end, Radiant has a souped-up plugin system called quot;extensionsquot;
plugins + awesome



which picks up where Rails plugins leave o.
merb-slices



Extensions are more like `merb-slices`
Rails Engines



or Rails Engines than plugins.
app/controllers
                  app/helpers
                  app/models
                  app/views

An extension can have its own quot;appquot; folder with controllers, helpers, models and views.
db/migrate




An extension can define database migrations
public



public files
vendor/plugins



and even its own plugins.
TATFT



Most importantly, you can quot;test all the timequot; in your extensions
RSpec



because Radiant provides a full RSpec harness
dataset :pages



a bunch of test datasets
@page.should render(“foo”)




and some nifty matchers to help out with Radiant-specific stu.
class FooExtension 
            Radiant::Extension




In addition to the directory and file structure, every extension is expressed as a singleton
class
def activate



that can provide some startup code in the quot;activatequot; method
define_routes do |map|
       map.resources :fuzzy_bears
     end




route definitions
description “My first extension.”
        url “http://foo.com”




and some metadata that is displayed in the user-interface.
TIMTOWTDI



Depending on the scenario, there are a number of dierent ways we can customize Radiant to
accomplish our goals, all of which can be nicely packaged up in extensions.
I could easily fill many hours talking about all the ways to tweak Radiant with extensions, so
I'm going to give you the 10,000-foot view of the primary techniques.
#1 :
                             new tags



The first and simplest way to add functionality is to define new Radius tags. As I said before,
Radius is the template language used to expose dynamic functionality to the designer and
content editor,
r:awesome /



through the use of these 'r'-prefixed XML-like tags.
(not) XML



The tags seem to imply an XML-structure, but I assure you they are strictly not XML and are
really just interpolated in-place.
r:




Radius tags are composed of four parts - the 'r' prefix;
r:children:each




the tag name, which may be colon separated;
r:children:each order=“desc”




the attributes;
r:children:each order=“desc”
          foo
        /r:children:each




any nested contents, and a closing tag. A few notes on these tag names: Radius will execute
the definition of each of those colon separated names in order and determine which
definitions to use based on context.
r:children
         r:each order=“desc”
           foo
         /r:each
         /r:children




The colon-separated version is just a shortcut for nesting them, so this snippet is logically
equivalent to the last one we saw.
r:children
         r:each order=“desc”
           foo
         /r:each
         /r:children




Also, the last named tag in the colon-separated list gets the attributes passed to its
definition.
r:stylesheet url=“/mine.css” /




So let's make a tag that generates some content - say a stylesheet link, and we'll make the
tag look like this.
module LazyTags



First, we'll make a module in our extension to hold the tag definition.
include Radiant::Taggable




Include quot;Radiant::Taggablequot; and we're ready to start defining tags.
tag ‘stylesheet’ do |tag|




Next we'll start our tag definition with the `tag` keyword, the tag name, and a block yielding
one parameter.
url = tag.attr[‘url’]




Inside our tag definition block, we'll grab the 'url' attribute o the tag,
%Q[link rel=”Stylesheet”
  type=”text/css” href=”#{url}” /]




and interpolate that into the proper place in the HTML `link` tag.
end



The return value of the tag-definition block is what is rendered, so we're done.
def activate
       Page.send :include, LazyTags
     end




Last, we mix the module into the Page model in the 'activate' method of our extension, and
we have access to our new tag definition.
|tag|



The yielded 'tag' object inside a definition is very powerful.
TagBinding === tag




It's your access to the contextual parsing environment, including what page is being
rendered, the request and response objects, and any variables set by surrounding tags.
tag.globals
                            everywhere



Its primary properties are 'globals', which gives you access to the global environment,
including the current page being rendered;
tag.locals
           cascading, contextual



‘locals' which is a cascading symbol-table of sorts, contextual to the current parsing
environment;
tag.attr
                               Hash


'attr', a hash of attributes placed on the current tag;
tag.double?
         r:footext/r:foo



'double?', which is true when the tag contains other tags or text,
tag.single?
                      r:bar /


and 'single?' which is true when the tag is self-closing.
be kind,
                      I’m sensitive



Because many tags are sensitive to their surrounding environment, you can easily do things
like iteration, changing some locals property on each step of the iteration, and causing
contained tags to use that property.
children.map do |child|
          tag.locals.page = child
          tag.expand
        end.join




This is essentially what the `r:children:each` tag does - iterate on each of the children,
changing `tag.locals.page` on each iteration, then joining the output. To trigger rendering of
a tag's contents, we just call `tag.expand`.
tag.render(“title”)




You can also directly invoke the rendering of another tag using `tag.render`. The result will
be returned to you as a string.
tag.block



One neat trick is capture the contents of a container tag and reuse it in multiple places with
`tag.block`.
r:navigation urls=”Foo:/foo |
   Bar: /bar”
   ...
   /r:navigation




The built-in `r:navigation` tag uses this to render navigation links depending on whether the
current page matches the URL being output.
tag.locals.hash = {}
       tag.expand
       # ...




First, it sets up a hash that can be used inside nested tags, then renders its contents.
tag ‘navigation:here’ do |tag|
      tag.locals.hash[:here] = tag.block
    end




The contained quot;navigation:herequot; tag assigns its block into the created hash.
# for each link...
        if url == page.url
          tag.locals.hash[:here].call
        end




Then the quot;navigationquot; tag calls the quot;herequot; block when the passed URL exactly matches the
current page's URL. It uses the same technique to render prefix-matching and non-matching
links by capturing blocks.
#2:
                             Admin UI



So now that we can customize page output with tag definitions, let's look at the next big area
of customization -- the admin UI.
class Widget 
           ActiveRecord::Base



Let's say you've built a model for widgets
r:widgets /



and some Radius tags to display them in a page,
CRUD



and now you need to create an interface for CRUDing them.
map.resources :widgets




The first thing you might want to do, after creating your controller,
Add “Widgets” Tab



is to add a tab to the interface so your widgets are navigable.
Extension.admin



Radiant exposes an quot;adminquot; object to every extension that lets you tweak the interface
admin.tabs.add “Widgets”,
       “/admin/widgets”




and easily add tabs. As well as letting you simply add tabs,
:before = “Layouts”




you can also specify where they occur in the tab order
:visibility = [:admin]




and who can see them. But that's just a simple case of how to customize the UI.
a dash of spice



Often what you want to do is just add a little piece to one view or another.
widget list



Say you need to be able to see your widget list while editing a page.
fine-grained
                         regions



Luckily, you can inject a view partial into any number of defined quot;regionsquot; in the view
template you want to modify, without overwriting the whole thing. This is enabled again
through the admin object.
app/views/admin/pages/
              _widget_list.erb




To add our widget list, we just put it in the app/views/admin/pages directory,
admin.pages.edit.add :form_top,
           ‘widget_list’




and add it to the proper region like so. In this case, we’re adding it to the form_top region of
the edit view for the pages controller.
include_stylesheet “widgets”
         include_javascript “widgets”




Inside your partial, in addition to simply rendering, you can add stylesheets and javascript
files to the head block in the layout so you can make your widget list look awesome.
brute-force
                         override



If you don't like the finessed approach, you can brute-force override any view template,
application.html.haml




including the default layout,
extensions
                       before core



by putting one of the same name in your extension, since extension view paths are searched
before Radiant's built-in paths.
#3:
                            front-end



So now you've got your admin interface doing cool things, but you want to provide a little
more functionality on the front-end.
page rendering



Let's take a look at the process of how a page is rendered.
map.connect “*url”




First, any request URL that doesn't match an admin or extension controller gets sent to the
splatted route
SiteController#show_page




assigned to SiteController.
request.get? or
                 request.head?
                  # read cache



If the request method is GET or HEAD, the controller checks whether the requested URL is
cached, populating the response if it is.
show_uncached_page(url)




Otherwise, it tries to show an uncached version of the page.
@page = find_page(url)




The controller tries to find the page by the given URL,
process_page(@page)




and then processes it if found
@page.process(request, response)




calling page.process with the request and response
@cache.cache_response(url,
             response)




caching the response where appropriate.
render :template =
                      “site/not_found”,
                        :status = 404




If it's not found, you get the default 404 page,
redirect_to welcome_path




and if there's no pages at all in the database, you get redirected to the login screen.
SiteController#find_page




So within this process are a number of extension points to play with - `find_page`,
SiteController#process_page




`process_page`,
Page#process(req, resp)




and `Page#process`.
conversion SEO



Let's say that we have an old site that has some existing URLs that we want to preserve for a
bit for SEO purposes.
choose a
                          Page class



Since when we create a new page in the interface, Radiant lets us choose the page class we
want,
redirect oldies



let's create a new Page class that performs a redirect from the old URL to our new location.
class RedirectPage  Page




So we'll choose to override the `process` method in our new subclass that we'll call
`RedirectPage`.
page.part(:body).content
               == “/old/url”




We'll assume that we put the new URL in the 'body' part of the page,
301 Moved
                     Permanently


and we'll want to consider this a permanent redirection.
def process(req, res)
      url = parse_object part(:body)




To accomplish this, inside we'll just render the body part to get our URL,
res.redirect url, “301 Moved
   Permanently”
   end




then cause the response to redirect.
def cache?; true; end




Believe it or not, a redirect can be cached!
5-minute cache
                 with headers



Radiant nicely captures the response headers and status when caching pages so, if we want
to cache this, it won't have to call our process method again for 5 minutes after the first
render.
GET HEAD
                             cache


Now you may have noticed that when I walked through the SiteController workflow, it only
checks for cached versions of a page on GET or HEAD requests.
POST PUT DELETE
              don’t cache


This means that when a page receives POST, PUT, or DELETE, you can do cool stu with the
data in the request.
mailer
                database_form



For example, the mailer and database_form extensions respectively process email forms and
store data to the database on POST requests,
seamless
                        experience



allowing a seamless front-end experience.
#4:
                 I want my MVC



This is great and all, but sometimes you'd just rather use a controller and views instead of a
page.
share_layouts



That's ok too, because there's a very popular extension called `share_layouts`.
ERb, Haml -
                 Radiant Layout



share_layouts lets you set a Layout, as in a Radiant Layout, within which your regular ERb or
Haml view will render.
content_for :side

                       part(:side)



Captured content blocks - using `content_for` - become page-parts,
@content_for_layout

                          part(:body)



and the default content becomes the body part, all of which are rendered in your Radiant
Layout via `r:content` tags.
@breadcrumbs
                     @title


You can also set the breadcrumbs and title that will be rendered inside our phantom page.
MOAR context
                  http://icanhascheezburger.com/2007/02/23/moar/
And should that not be good enough, and you need even better context, say, for rendering
localized navigation or an inherited sidebar,
endpoints



you can reify these phantom pages as quot;endpointsquot; in the page-tree,
“Application”
                      page-type



placing an quot;Applicationquot; page at the root of your controller route.
/widgets



That is, if your controller sits at '/widgets',
“widgets” slug



you'd make a page as a child of the root page with the slug 'widgets'.
just a
            spoonful of sugar



And that's just a smidgen of how you can customize Radiant.
Radiant
                                 Rails
                                 Ruby


Because it's built on Rails, nearly anything you can do with Ruby and Rails can be done inside
Radiant extensions.
workflow
                            lifecycle



You could play with the model workflow and lifecycle,
concurrent_draft
                    (working copies)




like the `concurrent_draft` extension that enables working copies,
scheduler
                      (timed publish)




or the `scheduler` extension that lets you specify dates for your pages to appear and
disappear from the site.
multi_site
                        (virtual hosts)




 Or you could modify built-in models and controllers, like the `multi_site` extension that
creates virtual hosts as multiple page-trees inside the same Radiant instance.
twitter
                      thirty_boxes



You could integrate with a third-party web-service, like the `twitter` and `thirty-boxes`
extensions.
file_system
                           DB - files




Or you could make design, development, and maintenance easier like the `file_system`
extension, which serializes models into text files,
import_export
                        (big YAML file)




or the `import_export` extension that dumps the whole database to a YAML file.
ext.radiantcms.org
And once you've completed your masterpiece, you can share it on the extension registry,
script/extension install




thereby enabling automatic installation scripts for your users.
The world is your oyster.
fin



I hope this has whet your appetite to use Radiant
r:questions:ask /




do you have any questions?

More Related Content

What's hot

Step into the SharePoint branding world, tools and techniques
Step into the SharePoint branding world, tools and techniquesStep into the SharePoint branding world, tools and techniques
Step into the SharePoint branding world, tools and techniquesBenjamin Niaulin
 
Master Pages And Navigation
Master Pages And NavigationMaster Pages And Navigation
Master Pages And NavigationAlfredo Cancino
 
Joomla Template Tutorial
Joomla Template TutorialJoomla Template Tutorial
Joomla Template Tutorialbrighteyes
 
1 Introduction to Drupal Web Development
1 Introduction to Drupal Web Development1 Introduction to Drupal Web Development
1 Introduction to Drupal Web DevelopmentWingston
 
Things I've learnt when skinning and customizing a SharePoint 2010 Site
Things I've learnt when skinning and customizing a SharePoint 2010 SiteThings I've learnt when skinning and customizing a SharePoint 2010 Site
Things I've learnt when skinning and customizing a SharePoint 2010 SiteJustin Lee
 
ASP.NET 06 - Customizing Your Sites Appearance
ASP.NET 06 - Customizing Your Sites AppearanceASP.NET 06 - Customizing Your Sites Appearance
ASP.NET 06 - Customizing Your Sites AppearanceRandy Connolly
 
Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
Blog It Up, Baby! Extending the new IBM Lotus Domino Blog TemplateBlog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
Blog It Up, Baby! Extending the new IBM Lotus Domino Blog TemplateSean Burgess
 
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog TemplateBP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog TemplateSean Burgess
 
Make Your IBM Connections Deployment Your Own: Customize It!
Make Your IBM Connections Deployment Your Own: Customize It!Make Your IBM Connections Deployment Your Own: Customize It!
Make Your IBM Connections Deployment Your Own: Customize It!Klaus Bild
 
Introduction to-concrete-5
Introduction to-concrete-5Introduction to-concrete-5
Introduction to-concrete-5ketanraval
 
Introduction to-concrete-5
Introduction to-concrete-5Introduction to-concrete-5
Introduction to-concrete-5Ketan Raval
 
Lotus Notes Blog Template
Lotus Notes Blog TemplateLotus Notes Blog Template
Lotus Notes Blog Templateprojectdxguy
 
CBIS 327 ~ Introduction
CBIS 327 ~ IntroductionCBIS 327 ~ Introduction
CBIS 327 ~ Introductionmwarrick
 
WEB DESIGNING MODULE
WEB DESIGNING MODULEWEB DESIGNING MODULE
WEB DESIGNING MODULEmar jun
 

What's hot (19)

web development
web developmentweb development
web development
 
Step into the SharePoint branding world, tools and techniques
Step into the SharePoint branding world, tools and techniquesStep into the SharePoint branding world, tools and techniques
Step into the SharePoint branding world, tools and techniques
 
Bootstrap share point 2013
Bootstrap share point 2013Bootstrap share point 2013
Bootstrap share point 2013
 
Master Pages And Navigation
Master Pages And NavigationMaster Pages And Navigation
Master Pages And Navigation
 
Dreaweaver cs5
Dreaweaver cs5Dreaweaver cs5
Dreaweaver cs5
 
Joomla Template Tutorial
Joomla Template TutorialJoomla Template Tutorial
Joomla Template Tutorial
 
1 Introduction to Drupal Web Development
1 Introduction to Drupal Web Development1 Introduction to Drupal Web Development
1 Introduction to Drupal Web Development
 
Things I've learnt when skinning and customizing a SharePoint 2010 Site
Things I've learnt when skinning and customizing a SharePoint 2010 SiteThings I've learnt when skinning and customizing a SharePoint 2010 Site
Things I've learnt when skinning and customizing a SharePoint 2010 Site
 
ASP.NET 06 - Customizing Your Sites Appearance
ASP.NET 06 - Customizing Your Sites AppearanceASP.NET 06 - Customizing Your Sites Appearance
ASP.NET 06 - Customizing Your Sites Appearance
 
Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
Blog It Up, Baby! Extending the new IBM Lotus Domino Blog TemplateBlog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
 
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog TemplateBP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
 
Make Your IBM Connections Deployment Your Own: Customize It!
Make Your IBM Connections Deployment Your Own: Customize It!Make Your IBM Connections Deployment Your Own: Customize It!
Make Your IBM Connections Deployment Your Own: Customize It!
 
TopicHero Descriptions Tutorial
TopicHero Descriptions TutorialTopicHero Descriptions Tutorial
TopicHero Descriptions Tutorial
 
Introduction to-concrete-5
Introduction to-concrete-5Introduction to-concrete-5
Introduction to-concrete-5
 
Introduction to-concrete-5
Introduction to-concrete-5Introduction to-concrete-5
Introduction to-concrete-5
 
Lotus Notes Blog Template
Lotus Notes Blog TemplateLotus Notes Blog Template
Lotus Notes Blog Template
 
HTML Guide
HTML GuideHTML Guide
HTML Guide
 
CBIS 327 ~ Introduction
CBIS 327 ~ IntroductionCBIS 327 ~ Introduction
CBIS 327 ~ Introduction
 
WEB DESIGNING MODULE
WEB DESIGNING MODULEWEB DESIGNING MODULE
WEB DESIGNING MODULE
 

Similar to Content Management That Won't Rot Your Brain

Viridians on Rails
Viridians on RailsViridians on Rails
Viridians on RailsViridians
 
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to DevelopmentWordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to DevelopmentEvan Mullins
 
Intro to mobile web application development
Intro to mobile web application developmentIntro to mobile web application development
Intro to mobile web application developmentzonathen
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on RailsAlessandro DS
 
Web Components
Web ComponentsWeb Components
Web ComponentsFITC
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Railsanides
 
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!Evan Mullins
 
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017 So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017 Evan Mullins
 
Html5 deciphered - designing concepts part 1
Html5 deciphered - designing concepts part 1Html5 deciphered - designing concepts part 1
Html5 deciphered - designing concepts part 1Paxcel Technologies
 
Oleksandr Krakovetskyi - Orchard CMS
Oleksandr Krakovetskyi - Orchard CMSOleksandr Krakovetskyi - Orchard CMS
Oleksandr Krakovetskyi - Orchard CMSCiklum Ukraine
 
JavaScript Presentation Frameworks and Libraries
JavaScript Presentation Frameworks and LibrariesJavaScript Presentation Frameworks and Libraries
JavaScript Presentation Frameworks and LibrariesOleksii Prohonnyi
 
Implementing Vanilla Web Components
Implementing Vanilla Web ComponentsImplementing Vanilla Web Components
Implementing Vanilla Web Componentssonumanoj
 
Websites Unlimited - Pay Monthly Websites
Websites Unlimited - Pay Monthly WebsitesWebsites Unlimited - Pay Monthly Websites
Websites Unlimited - Pay Monthly Websiteswebsiteunlimited
 
Wordpress Workflow
Wordpress Workflow Wordpress Workflow
Wordpress Workflow Filippo Dino
 
Introduce PlutoCMS
Introduce PlutoCMSIntroduce PlutoCMS
Introduce PlutoCMSxhan87
 

Similar to Content Management That Won't Rot Your Brain (20)

Viridians on Rails
Viridians on RailsViridians on Rails
Viridians on Rails
 
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to DevelopmentWordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
 
Wa html5-pdf
Wa html5-pdfWa html5-pdf
Wa html5-pdf
 
Wa html5-pdf
Wa html5-pdfWa html5-pdf
Wa html5-pdf
 
SiteMesh
SiteMeshSiteMesh
SiteMesh
 
INTRODUCTIONS OF HTML
INTRODUCTIONS OF HTMLINTRODUCTIONS OF HTML
INTRODUCTIONS OF HTML
 
Intro to mobile web application development
Intro to mobile web application developmentIntro to mobile web application development
Intro to mobile web application development
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Web Components
Web ComponentsWeb Components
Web Components
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!
WordCamp Asheville 2017 - So You Wanna Dev? Join the Team!
 
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017 So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017
So, You Wanna Dev? Join the Team! - WordCamp Raleigh 2017
 
Html5 deciphered - designing concepts part 1
Html5 deciphered - designing concepts part 1Html5 deciphered - designing concepts part 1
Html5 deciphered - designing concepts part 1
 
Oleksandr Krakovetskyi - Orchard CMS
Oleksandr Krakovetskyi - Orchard CMSOleksandr Krakovetskyi - Orchard CMS
Oleksandr Krakovetskyi - Orchard CMS
 
JavaScript Presentation Frameworks and Libraries
JavaScript Presentation Frameworks and LibrariesJavaScript Presentation Frameworks and Libraries
JavaScript Presentation Frameworks and Libraries
 
Implementing Vanilla Web Components
Implementing Vanilla Web ComponentsImplementing Vanilla Web Components
Implementing Vanilla Web Components
 
Websites Unlimited - Pay Monthly Websites
Websites Unlimited - Pay Monthly WebsitesWebsites Unlimited - Pay Monthly Websites
Websites Unlimited - Pay Monthly Websites
 
Wordpress Workflow
Wordpress Workflow Wordpress Workflow
Wordpress Workflow
 
Introduce PlutoCMS
Introduce PlutoCMSIntroduce PlutoCMS
Introduce PlutoCMS
 
Orchard
OrchardOrchard
Orchard
 

More from Sean Cribbs

Eventually Consistent Data Structures (from strangeloop12)
Eventually Consistent Data Structures (from strangeloop12)Eventually Consistent Data Structures (from strangeloop12)
Eventually Consistent Data Structures (from strangeloop12)Sean Cribbs
 
Eventually-Consistent Data Structures
Eventually-Consistent Data StructuresEventually-Consistent Data Structures
Eventually-Consistent Data StructuresSean Cribbs
 
A Case of Accidental Concurrency
A Case of Accidental ConcurrencyA Case of Accidental Concurrency
A Case of Accidental ConcurrencySean Cribbs
 
Embrace NoSQL and Eventual Consistency with Ripple
Embrace NoSQL and Eventual Consistency with RippleEmbrace NoSQL and Eventual Consistency with Ripple
Embrace NoSQL and Eventual Consistency with RippleSean Cribbs
 
Riak with node.js
Riak with node.jsRiak with node.js
Riak with node.jsSean Cribbs
 
Schema Design for Riak (Take 2)
Schema Design for Riak (Take 2)Schema Design for Riak (Take 2)
Schema Design for Riak (Take 2)Sean Cribbs
 
Riak (Øredev nosql day)
Riak (Øredev nosql day)Riak (Øredev nosql day)
Riak (Øredev nosql day)Sean Cribbs
 
Riak Tutorial (Øredev)
Riak Tutorial (Øredev)Riak Tutorial (Øredev)
Riak Tutorial (Øredev)Sean Cribbs
 
The Radiant Ethic
The Radiant EthicThe Radiant Ethic
The Radiant EthicSean Cribbs
 
Introduction to Riak and Ripple (KC.rb)
Introduction to Riak and Ripple (KC.rb)Introduction to Riak and Ripple (KC.rb)
Introduction to Riak and Ripple (KC.rb)Sean Cribbs
 
Schema Design for Riak
Schema Design for RiakSchema Design for Riak
Schema Design for RiakSean Cribbs
 
Introduction to Riak - Red Dirt Ruby Conf Training
Introduction to Riak - Red Dirt Ruby Conf TrainingIntroduction to Riak - Red Dirt Ruby Conf Training
Introduction to Riak - Red Dirt Ruby Conf TrainingSean Cribbs
 
Introducing Riak and Ripple
Introducing Riak and RippleIntroducing Riak and Ripple
Introducing Riak and RippleSean Cribbs
 
Round PEG, Round Hole - Parsing Functionally
Round PEG, Round Hole - Parsing FunctionallyRound PEG, Round Hole - Parsing Functionally
Round PEG, Round Hole - Parsing FunctionallySean Cribbs
 
Story Driven Development With Cucumber
Story Driven Development With CucumberStory Driven Development With Cucumber
Story Driven Development With CucumberSean Cribbs
 
Achieving Parsing Sanity In Erlang
Achieving Parsing Sanity In ErlangAchieving Parsing Sanity In Erlang
Achieving Parsing Sanity In ErlangSean Cribbs
 
Of Rats And Dragons
Of Rats And DragonsOf Rats And Dragons
Of Rats And DragonsSean Cribbs
 
Erlang/OTP for Rubyists
Erlang/OTP for RubyistsErlang/OTP for Rubyists
Erlang/OTP for RubyistsSean Cribbs
 

More from Sean Cribbs (19)

Eventually Consistent Data Structures (from strangeloop12)
Eventually Consistent Data Structures (from strangeloop12)Eventually Consistent Data Structures (from strangeloop12)
Eventually Consistent Data Structures (from strangeloop12)
 
Eventually-Consistent Data Structures
Eventually-Consistent Data StructuresEventually-Consistent Data Structures
Eventually-Consistent Data Structures
 
A Case of Accidental Concurrency
A Case of Accidental ConcurrencyA Case of Accidental Concurrency
A Case of Accidental Concurrency
 
Embrace NoSQL and Eventual Consistency with Ripple
Embrace NoSQL and Eventual Consistency with RippleEmbrace NoSQL and Eventual Consistency with Ripple
Embrace NoSQL and Eventual Consistency with Ripple
 
Riak with node.js
Riak with node.jsRiak with node.js
Riak with node.js
 
Schema Design for Riak (Take 2)
Schema Design for Riak (Take 2)Schema Design for Riak (Take 2)
Schema Design for Riak (Take 2)
 
Riak (Øredev nosql day)
Riak (Øredev nosql day)Riak (Øredev nosql day)
Riak (Øredev nosql day)
 
Riak Tutorial (Øredev)
Riak Tutorial (Øredev)Riak Tutorial (Øredev)
Riak Tutorial (Øredev)
 
The Radiant Ethic
The Radiant EthicThe Radiant Ethic
The Radiant Ethic
 
Introduction to Riak and Ripple (KC.rb)
Introduction to Riak and Ripple (KC.rb)Introduction to Riak and Ripple (KC.rb)
Introduction to Riak and Ripple (KC.rb)
 
Riak with Rails
Riak with RailsRiak with Rails
Riak with Rails
 
Schema Design for Riak
Schema Design for RiakSchema Design for Riak
Schema Design for Riak
 
Introduction to Riak - Red Dirt Ruby Conf Training
Introduction to Riak - Red Dirt Ruby Conf TrainingIntroduction to Riak - Red Dirt Ruby Conf Training
Introduction to Riak - Red Dirt Ruby Conf Training
 
Introducing Riak and Ripple
Introducing Riak and RippleIntroducing Riak and Ripple
Introducing Riak and Ripple
 
Round PEG, Round Hole - Parsing Functionally
Round PEG, Round Hole - Parsing FunctionallyRound PEG, Round Hole - Parsing Functionally
Round PEG, Round Hole - Parsing Functionally
 
Story Driven Development With Cucumber
Story Driven Development With CucumberStory Driven Development With Cucumber
Story Driven Development With Cucumber
 
Achieving Parsing Sanity In Erlang
Achieving Parsing Sanity In ErlangAchieving Parsing Sanity In Erlang
Achieving Parsing Sanity In Erlang
 
Of Rats And Dragons
Of Rats And DragonsOf Rats And Dragons
Of Rats And Dragons
 
Erlang/OTP for Rubyists
Erlang/OTP for RubyistsErlang/OTP for Rubyists
Erlang/OTP for Rubyists
 

Recently uploaded

The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 

Recently uploaded (20)

The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 

Content Management That Won't Rot Your Brain