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://ļ¬‚ickr.com/photos/mashed_potatoe/65823367/
Most of them have unintuitive user interfaces,
tangled



        http://ļ¬‚ickr.com/photos/randomurl/440190706/
tangled content models,
ugly code
         http://ļ¬‚ickr.com/photos/ļ¬‚ickerbulb/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://ļ¬‚ickr.com/photos/fdecomite/402499198/
Good luck ļ¬guring that one out.
pluggable


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



     http://ļ¬‚ickr.com/photos/garlandcannon/3048731338/
doesn't seem to do anything it advertises.
template surgery


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


             http://ļ¬‚ickr.com/photos/twose/887903401/
while trying to be everything to everyone.
FTP is so 1971


          http://ļ¬‚ickr.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/ļ¬le 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 ļ¬lters
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://ļ¬‚ickr.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 deļ¬ne database migrations
public



public ļ¬les
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-speciļ¬c stu.
class FooExtension 
            Radiant::Extension




In addition to the directory and ļ¬le 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 deļ¬nitions
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 ļ¬ll 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 ļ¬rst and simplest way to add functionality is to deļ¬ne 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'-preļ¬xed 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' preļ¬x;
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 deļ¬nition of each of those colon separated names in order and determine which
deļ¬nitions 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
deļ¬nition.
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 deļ¬nition.
include Radiant::Taggable




Include quot;Radiant::Taggablequot; and we're ready to start deļ¬ning tags.
tag ā€˜stylesheetā€™ do |tag|




Next we'll start our tag deļ¬nition with the `tag` keyword, the tag name, and a block yielding
one parameter.
url = tag.attr[ā€˜urlā€™]




Inside our tag deļ¬nition 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-deļ¬nition 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 deļ¬nition.
|tag|



The yielded 'tag' object inside a deļ¬nition 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 preļ¬x-matching and non-matching
links by capturing blocks.
#2:
                             Admin UI



So now that we can customize page output with tag deļ¬nitions, 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 ļ¬rst 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 deļ¬ned 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
ļ¬les 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 ļ¬nessed 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 ļ¬nd 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 - `ļ¬nd_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 ļ¬rst
render.
GET HEAD
                             cache


Now you may have noticed that when I walked through the SiteController workļ¬‚ow, 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 workļ¬‚ow 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 `ļ¬le_system`
extension, which serializes models into text ļ¬les,
import_export
                        (big YAML file)




or the `import_export` extension that dumps the whole database to a YAML ļ¬le.
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

Master Pages And Navigation
Master Pages And NavigationMaster Pages And Navigation
Master Pages And Navigation
Alfredo Cancino
Ā 
1 Introduction to Drupal Web Development
1 Introduction to Drupal Web Development1 Introduction to Drupal Web Development
1 Introduction to Drupal Web Development
Wingston
Ā 
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
Justin Lee
Ā 
CBIS 327 ~ Introduction
CBIS 327 ~ IntroductionCBIS 327 ~ Introduction
CBIS 327 ~ Introduction
mwarrick
Ā 

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

Wa html5-pdf
Wa html5-pdfWa html5-pdf
Wa html5-pdf
Selvaraj V
Ā 

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

Riak (Ƙredev nosql day)
Riak (Ƙredev nosql day)Riak (Ƙredev nosql day)
Riak (Ƙredev nosql day)
Sean 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
Ā 

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

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(ā˜Žļø+971_581248768%)**%*]'#abortion pills for sale in dubai@
Ā 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
Ā 

Recently uploaded (20)

Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
Ā 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
Ā 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
Ā 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
Ā 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
Ā 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
Ā 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
Ā 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
Ā 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
Ā 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
Ā 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
Ā 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
Ā 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Ā 
Scaling API-first ā€“ The story of a global engineering organization
Scaling API-first ā€“ The story of a global engineering organizationScaling API-first ā€“ The story of a global engineering organization
Scaling API-first ā€“ The story of a global engineering organization
Ā 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
Ā 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
Ā 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
Ā 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
Ā 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
Ā 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
Ā 

Content Management That Won't Rot Your Brain