Welcome to the Geeks & God Static Archive. Read more »

Generating a Dummy Front Page for Drupal

G&G Moderator
G&G Podcast Host
micah's picture
Joined: 06/21/2007

I was chatting with Rob Feature earlier this evening about how to best create a Drupal front page that contains no content. That is, we want to build front pages that don't contain normal Drupal node-based content. Our front pages are made up of blocks instead.

Rob's favored theming technique is to create a blank page and then add blocks to contain everything on the front page. My technique is similar, except that for my last site, I simply omitted rendering $content in my page-front.tpl.php file, and created a bunch of custom regions that only appeared there. So what's the problem?

The problem, my friends, is performance.

Rob's method requires a node_load to occur, even though the node contains no content. My method is even worse, because it not only has to run the default frontpage view to generate content it will never render, but I'm probably also rendering all of my blocks for every page, whether the target region exists or not. (I'll have to confirm that with the devel module or something, I guess.)

The blocks rendering is simple, even though regions only appear in specific templates, I should make sure to specify that they are only set to appear on the front page anyway.

Generating a blank page is a little trickier, but I think I've figured out how to override the default page functionality by adding some extra code to my custom site-specific module (see tutorial here).

/**
 * Implementation of hook_menu_alter().
 */
function nofront_menu_alter(&$items) {
  // Override default home page content.
  $items['node']['page callback'] = 'nofront_node_page_default';
}
 
/**
 * Menu callback for default page.
 */
function nofront_node_page_default() {
  drupal_set_title('');
  return '';
}

The net result should be that you can navigate to <front> on your site and see an empty page with only a title. Be sure to flush cached items on admin/settings/performance before testing this, or it won't work. The 'page callback' parameter is required, but can be null.

The hook_menu API documentation contains additional examples.

Revision 2: The original version of this post set up a custom permission. Thanks to Jeff Eaton for pointing out that 'access content' works just fine here.

Revision 3: Simplified even more by setting 'page callback' to null and removing a function that returned a null string.

Revision 4: Realized that setting 'page callback' to a null does not work, but also went after Matt's comment below about changing functionality versus theming. The goal of this hack is to change the default functionality of Drupal's main page by removing all content it generates. That's why I went after /node this time around, basing my changes on the default behavior in node.module. See API entries for node_menu and node_page_default for more information.

Revision 5: I realized some time ago that this module should use hook_menu_alter() instead of hook_menu() to make its changes. In my original version, I was attempting to completely overwrite the $items['node'] created by node.module. In fact, all that needs to happen here is to alter the 'page callback' parameter and create the function. Also, I renamed the callback function to better follow naming conventions.

This module is now available as a sandbox project on drupal.org.

Jeff Eaton
Jeff Eaton's picture
Even easier!

This seems a little cumbersome. For one thing, it requires adding a permission setting to view the front page, but it doesn't execute any database queries (other than a permission check, probably) to render, so I think it might be a reasonably good solution.

Actually, because that access check can be any valid access permission, "access content" can be used as well. That's on-by-default for anonymous users as well as registered users, so it shouldn't cause too many problems.

That also lets you do away with the hook_perm() impelementation.

G&G Moderator
G&G Podcast Host
micah's picture
Joined: 06/21/2007
Oh sweet!

Thanks Jeff! I'm going to update the original post with that change.

G&G Moderator
shrop's picture
Joined: 07/16/2007
custom module

I would like to point out that Micah is using a custom module for his site. This is a great practice when using Drupal. Many of my sites have a custom module like Micah's where I dump code that hacks/tweaks Drupal stuff to my liking. Cool thing is you can build up a library of hacks in a module and just install that module on new sites or as part of a Drupal profile...

:)

Mark Shropshire "shrop"
Geeks & God Forums Moderator
http://geeksandgod.com/users/shrop

G&G Moderator
G&G Podcast Host
micah's picture
Joined: 06/21/2007
Custom modules as part of theming

Good point, Shrop. I tweaked the wording to make that more clear.

This ties in to the upcoming Drupal Theming training announced in the latest podcast. Rob said that most Drupal training is either too basic (how to install a contributed theme) or goes way too deep into advanced topics like module development. I'd argue that another missing piece of the puzzle is module creation basics. I wrote a tutorial (linked above) to try to help fill that gap, because it was a stumbling block for me. I think it's important, because I generally use a custom module as part of my theming strategy.

Basic module development - creating a module, basics of hook_form_alter, hook_perm and hook_menu, etc - is one of those intermediate topics that doesn't seem to get a lot of coverage. I've learned that you don't have to be a hard-core PHP developer to take advantage of these tools, and they can work hand-in-hand with template.php to help tweak a site's appearance and provide a better experience for end users.

Micah

G&G Podcast Host
Rob Feature's picture
Joined: 06/01/2006
Nice Micah! (& question for Jeff)

Yahoo! A great solution. For years i've been using this "blank node" approach knowing that performance was suffering. It was only recently (um...yesterday) that I finally said "this is stupid...there's a better way". Thanks for working it out Micah.

@Jeff Eaton:
I'd be interested as to how you've produced your front pages on high traffic sites (assuming they're probably all blocks, and not a node). Is this the type of approach you'd take?

-Rob Feature
Geeks and God Co-Host
www.mustardseedmedia.com

G&G Podcast Host
Matt Farina's picture
Joined: 06/01/2006
Functionality not Theming

Custom modules shouldn't implement theming. But, I think they two can often be confused.

For example, the short module that micah wrote above is not for theming. It is for functionality. The functionality is to have a page that is blank. Now, the goal is to add blocks to that page which provide content. This is information architecture and using drupal to implement that. Again, not theming.

Theming is turning that information drupal spits out into a designed look. It's creating a new presentation/theme that displays a design. It may be specific for the information that's being spit out by drupal but it isn't about what the content is and what is used to put the content in the page.

So, a custom module shouldn't really be used to implement theming on a site.

Does that make sense?

Matt Farina
Geeks and God Former Co-Host
www.mattfarina.com

G&G Podcast Host
Rob Feature's picture
Joined: 06/01/2006
Altering forms is my only possibly crossover

I agree with you MF...what's here is a 'theming aid', not actual theming (we always debate where that line is, but it's an important debate)

The only place I see them really crossing over and getting really blurred is when modifying forms using hook_form_alter. The reason is because you can't "theme" forms (their layout, field sizes, even descriptions(though that's more clearly not theming)) by any means except modifying the form via hook_form_alter

To me, using that hook, since it's the only way to change the layout/style/design of the forms, is the only place I see that theming and module development get quite a bit more blurred.

-Rob Feature
Geeks and God Co-Host
www.mustardseedmedia.com

G&G Podcast Host
Matt Farina's picture
Joined: 06/01/2006
Altering Forms in Themes

You can alter forms in themes. There are a few things.

For example, theme_file is the function that renders the file upload field. If I want to alter it site wide I would create a function called myThemeName_file() and use the theme override to alter the file field.

You'll find a theme function for each of the fields in a form.

Now, if you want to alter individual forms there are options there as well. They have theme functions or templates that build them. If I want to alter a node form in my theme I would do this in my template.php file and override the function theme_node_form:

<?php
function themeName_node_form($form) {
 
// Change the form.
 
return drupal_render($form);
}
?>

or more likely for this case:

<?php
function themeName_node_form($form) {
 
// Change the form.
 
return theme_node_form($form);
}
?>

If you want to test this put this function in your template.php file, clear your cache (admin > settings > performance), and visit a node/add/[node type] page.

<?php
function phptemplate_node_form($form) {
  return
'test';
}
?>

You can find more details on this at http://11heavens.com/theming-the-node-form-in-Drup...

If the form altering is not about the functionality of the form but about the presentation of the form I'd suggest the way to theme the form is with a theme override call.

If there are modules that don't do this those modules should have issues filed in them. Additionally, you can add your own theme function in for these modules using hook_theme.

Matt Farina
Geeks and God Former Co-Host
www.mattfarina.com

G&G Moderator
G&G Podcast Host
micah's picture
Joined: 06/21/2007
Thanks, Matt, you're making my head hurt

Alrighty then.

If you go back to the top of this post, you'll see that we're now on revision 4. I'm going to play semantics with Matt now and say fine, we want to change the functionality of the site in order to theme it the way we want it. If you say it that way, I'll agree there's a distinction. In that case, we don't really want to add functionality to create a blank page that can be used as the front page, we want to make the front page blank.

So I went and did some digging and found out how the default home page is created. It's defined in node.module, where $items['node'] gets created in node_menu, and its content is generated in the nod_page_default callback module. My new revision overwrites $items['node'] and uses its own callback. As a bonus, I kept the call to drupal_set_title('') so the new page still displays the site name and slogan in the $head_title.

Now the functionality has been changed so the themer can do what they want with the new blank front page.

Hopefully this will be the last revision.

G&G Moderator
G&G Podcast Host
micah's picture
Joined: 06/21/2007
Drupal 5 Version of Blank Default Page

Here's a Drupal 5 version I just made for one of my sites:

function mysite_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array('path' => 'node',
      'title' => t('Content'),
      'callback' => 'node_page_default_blank',
      'access' => user_access('access content'),
      'type' => MENU_MODIFIABLE_BY_ADMIN);
  }
  return $items;
}
 
function node_page_default_blank() {
  drupal_set_title('');
  return '';
}

Note that you'll still have to clear caches for this to work, but that's a little trickier in Drupal 5. Check out http://drupal.org/node/152983 for a page you can create to do this. (Or create a fancy new callback using the code!)

G&G Moderator
Josiah's picture
Joined: 12/20/2007
Custom Regions?

Thanks for putting this together guys.

So when adding the modules, do you edit front-page.tpl.php to have a region that no other templates have for adding your blocks? Would this be another opportunity for performance improvement? When it comes to performance, I'm looking to understand things better. I've managed the same results by placing blocks it zen theme's #content-bottom and #content-top and then specifying the pages it should show on. Would you expect this to be slower? In my limited understanding of this flow, I'd expect more checks that resulted in nothing happening in my current method rather than the previous custom region that results in one check for the region instead of all the blocks.

Did I phrase that in a sensible manner? If you can understand it, am I headed in the right direction?

G&G Moderator
G&G Podcast Host
micah's picture
Joined: 06/21/2007
Custom Regions and Performance

Josiah,

This came into the conversation when we were working this out. I did custom regions on page-front.tpl.php for a site, but you need to set that up correctly or it can be a huge performance drain. Even though those blocks were only being rendered on the front page, they were being generated for every page. The fix there was to make sure to set those blocks to only display on <front> in block settings, and to set the other blocks to all pages except <front> so those queries won't execute.

Micah

Joined: 03/11/2008
This is great...

I'm trying to do exactly what you're talking about on my site, if it ever goes live (I need to find time to listen to the "Why Church Tech Projects Fail" podcast). Anyway, this will be very helpful, though I'll confess it's still making my head swim right now. I was surprised to find this was so hard to do.

There's one other piece that would be really nice to add to the mix. I'd like to have some block views that actually display on both the front page and other pages. A good example would be an "Upcoming Events" block view. On underlying ministry pages, the view would show only upcoming events associated with that ministry, pulled from the URL and defined in the required node taxonomy. But on the front page, the block view would show ALL events with "Promoted to Front Page" checked, regardless of taxonomy.

Can you guys think of any good way to define this behavior all within one view or would the best/only way be to have two separate views - one for the front page and one for everything else?

Clint "The Geekin' Deacon" Eaker
Webmaster - Chapel Hill Bible Church
Chapel Hill, NC

Joined: 07/26/2008
why so complex? just create a

why so complex? just create a url alias for "node".

G&G Podcast Host
Rob Feature's picture
Joined: 06/01/2006
Don't want 'node' content

Unfortunately, you can't just create an alias for /node...it will still spit out the 'promote to front page' content, exactly as /node does (at least I'm assuming it does). The purpose of this is to strip out all that content and give a blank slate on which to place blocks.

-Rob Feature
Geeks and God Co-Host
www.mustardseedmedia.com

Actually It was in my mind, but you got the job ;)

Thanks mate, I was looking for the same solution from a week, but I was looking for any module to handle these kind of messy things, I got module "front" but when I tried on custom anonymous page it cause other issue. Now I have resolved my problem.

Thanks
Blue Moon

Thanks

Thanks for the tip!

Couldn't you just...

comment out line 1773 in the node.module file in the /modules/node folder?
// $output = '

'. $default_message .'

';

sorry that didn't come out right...

//    $output = '<div id="first-time">'. $default_message .'</div>';

Emad Al-Shihabi
Jeff Eaton's picture
maybe?

another approch?

<?php
function node_page_default_blank() {
     
$node = new stdClass();
     
$node->title = '';
     
$node->body = '';
      return
node_page_view($node);
}
?>

G&G Moderator
G&G Podcast Host
micah's picture
Joined: 06/21/2007
Catching up on this thread

Just catching up on this thread a bit...

@Josiah: I think the custom regions issue can be handled using something like my Custom Media Page tutorial, which builds page content by specifically embedding views. I think I'd lean more towards that approach than doing page-front.tpl.php these days.

@clint: I've done this by using multiple block displays for the same view and overriding the filters for specific displays.

@deweydb: I thought about that, but I've heard "don't hack core" so many times that I couldn't bring myself to do it. This overrides the default without touching the original code, and does not need to be reapplied every time core is updated.

@Emad: I think I see where you're going with that, but content doesn't have to be a node to be displayed. (It took me a while to grasp that, since "content" in Drupal sites is made up of "nodes".) Returning an empty string is a lot cleaner than wrapping an empty string in all of the divs and formatting that would be generated by theming an empty node.

Joined: 05/19/2010
Empty Page module

Fyi, this module could be useful for solving this - http://drupal.org/project/empty_page

G&G Moderator
G&G Podcast Host
micah's picture
Joined: 06/21/2007
Revision 5 and Empty Page

It looks like Nick's Empty Page Module is a great way to create empty pages, and he's ported it to Drupal 7.

I've just created the fifth revision of this post. Sorry that the latest changes really make most of the comments in this thread irrelevant.

As noted in the revision notes on the post, I realized that by using hook_menu() to overwrite /node in my original example, I was abusing the menu system and not really taking advantage of what hook_form_alter() is meant to do. The current revision is the shortest and cleanest example I can think of for this solution.

I'm not going to modify my comment showing the Drupal 5 version. Drupal 5 is no longer supported.

Micah