my $tree = Continuity::Widget::DomNode->create( html => [ head => [ style => { src => '/css/style.css' }, script => { language => 'javascript', src => '/js/jquery.js' }, script => { language => 'javascript', src => '/js/app.js' }, ], body => [ $header->render, $content->render, $footer->render, ] ] ); So now we have this DOM thingie. Beautiful. What else can we do with it? One thing is to look at those render methods. Rather than returning a DomNode, lets say they return a subref. What we'll do is traverse the tree again, and replace whatever they gave us with the new thing. This is a way for nodes to delay their rendering until they can get some more context. So... in $content->render we might have: sub render { my ($self) = @_; return map { my $child = $_; sub { $child->render_on(@_) } } @{$self->children}; } # or sub render { my ($self) = @_; return sub { $self->render_on(@_) }; } The body could be re-written directly as: body => [ sub { $header->render_on(@_) }, sub { $content->render_on(@_) }, sub { $footer->render_on(@_) }, ] Though that wouldn't be as much fun. A subref could return either a list of DomNodes (often just one) or a list that can be passed to DomNode->create (including subrefs). The subref will be passed the parent (context) node, or perhaps a dummy node for its exact location. In render_on we can then use CSS-like thingies to determine some context-specific settings. Lets say we have some magical CSS like: .edit EPFarms::User .field { mode: edit; } .edit * { mode: edit; } then we have sub render_on { my ($self, $node) = @_; $self->set_context($node); if($self->attr('mode') eq 'edit') { return (input => { type => 'text', name => $self->htmlname, value => $self->val }); } if($self->attr('mode') eq 'view') { return ( $self->val ); } } So... when does subref expansion happen? It could be explicit, or it could be implicit as part of to_string for actual sending to the browser: $tree->expand_subs; $str = $tree->to_string; # or $str = $tree->to_string;