Add your own content to node I've created a module that adds custom content to a node; I'd like to display this custom content in the node view. I think hook_node_view() is the right hook to use, but my content doesn't get displayed.

what I got so far is the following code:

function mymodule_node_view($node, $view_mode = 'full', $langcode = NULL) {
$node-&gt;content['mymodule']['#items'][0] = array(
    'value' =&gt; theme('mymodule_output', array('mymodule_cid' =&gt; $node-&gt;mymodule_cid)),
    'summary' =&gt; '',
    'format' =&gt; 'full_html',
    'safe_value' =&gt; theme('mymodule_output', array('mymodule_cid' =&gt; $node-&gt;mymodule_cid)),
    'safe_summary' =&gt; '',
);
$node-&gt;content['mymodule']['#weight'] = 12; 
}


Can anybody help?
TL;DR: The hook is correct, but $node-&gt;content['mymodule']['#items'][0] should at least contain one of these array indexes/properties: "#markup" or "#theme"; if you don't use one of them, Drupal will not output anything.

If the array indexes you use are for properties handled by your theme function, then you should use # at the beginning; for example "format" would become "#format" (the same is true for the other properties).

Anyway, there is no need to use "format" as you do (whatever meaning it has); the function just output HTML, as done in the example shown in the hook_node_view() example.

function hook_node_view($node, $view_mode, $langcode) {
  $node-&gt;content['my_additional_field'] = array(
    '#markup' =&gt; $additional_field, 
    '#weight' =&gt; 10, 
    '#theme' =&gt; 'mymodule_my_additional_field',
  );
}


If you want some more concrete examples of that hook implementations, you can look at book_node_view(), statistics_node_view(), and translation_node_view().

function book_node_view($node, $view_mode) {
  if ($view_mode == 'full') {
    if (!empty($node-&gt;book['bid']) &amp;&amp; empty($node-&gt;in_preview)) {
      $node-&gt;content['book_navigation'] = array(
        '#markup' =&gt; theme('book_navigation', array('book_link' =&gt; $node-&gt;book)), 
        '#weight' =&gt; 100,
      );
    }
  }

  if ($view_mode != 'rss') {
    book_node_view_link($node, $view_mode);
  }
}


As side note, I will add that you should use the # character only for properties, or you are going to confuse Drupal, which expects that character to be used only for properties.
In fact, element_children(), which returns the list of child elements of the element passed as argument, uses the following code:

  foreach ($elements as $key =&gt; $value) {
    if ($key === '' || $key[0] !== '#') {
      $children[$key] = $value;
      if (is_array($value) &amp;&amp; isset($value['#weight'])) {
        $sortable = TRUE;
      }
    }
  }


As you see, elements whose key value starts with # are not taken to be child elements; differently, Drupal would not be able to handle a case like this one (the code is really implemented by a Drupal module, the Search module):

  $form['#action'] = url($action);
  // Record the $action for later use in redirecting.
  $form_state['action'] = $action;
  $form['#attributes']['class'][] = 'search-form';
  $form['module'] = array(
    '#type' =&gt; 'value',
    '#value' =&gt; $module,
  );
  $form['basic'] = array(
    '#type' =&gt; 'container',
    '#attributes' =&gt; array('class' =&gt; array('container-inline')),
  );
  $form['basic']['keys'] = array(
    '#type' =&gt; 'textfield', 
    '#title' =&gt; $prompt, 
    '#default_value' =&gt; $keys, 
    '#size' =&gt; $prompt ? 40 : 20, 
    '#maxlength' =&gt; 255,
  );
  // processed_keys is used to coordinate keyword passing between other forms
  // that hook into the basic search form.
  $form['basic']['processed_keys'] = array(
    '#type' =&gt; 'value',
    '#value' =&gt; '',
  );
  $form['basic']['submit'] = array(
    '#type' =&gt; 'submit',
    '#value' =&gt; t('Search'),
  );


Are $form['#action'] and $form['basic']['submit'] child elements?

As another side note, I will add that hook_view() is invoked by Drupal only for the modules that implement a content type.
In fact, the implementations of that hook are invoked by node_build_content() using the following code:

  // The 'view' hook can be implemented to overwrite the default function
  // to display nodes.
  if (node_hook($node, 'view')) {
    $node = node_invoke($node, 'view', $view_mode, $langcode);
  }


The code for node_invoke() is the following one:

  if (node_hook($node, $hook)) {
    $base = node_type_get_base($node);
    $function = $base . '_' . $hook;
    return ($function($node, $a2, $a3, $a4));
  }


The code invokes $hook for the module implementing the content type of the node passed as argument.