diff --git a/fb_stream.module b/fb_stream.module
index 30ba0f6..913df84 100644
--- a/fb_stream.module
+++ b/fb_stream.module
@@ -12,10 +12,338 @@
  * for much more, so eventually this module will do more.
  */
 
+define('FB_STREAM_VAR_TOKEN', 'fb_stream_token');
 define('FB_STREAM_DIALOGS', 'fb_stream_dialogs');
 
+define('FB_STREAM_PERM_OVERRIDE', 'override facebook stream details');
+define('FB_STREAM_PERM_POST', 'post to site-wide facebook stream');
+
+/**
+ * Implements hook_menu().
+ */
+function fb_stream_menu() {
+  $items = array();
+
+  $items[FB_PATH_ADMIN . '/fb_stream'] = array(
+    'title' => 'Stream Posts',
+    'access arguments' => array(FB_PERM_ADMINISTER),
+    'weight' => -1,
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('fb_stream_admin_settings'),
+    'file' => 'fb_stream.admin.inc',
+  );
+
+  return $items;
+}
+
+function fb_stream_perm() {
+  return array(FB_STREAM_PERM_POST, FB_STREAM_PERM_OVERRIDE);
+}
+
+function fb_stream_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
+  if ($op == 'insert' || $op == 'update') {
+    if ($node->fb_stream_do_post) {
+      $node_url = url("node/$node->nid", array('absolute' => TRUE));
+
+      $params = array(
+        'access_token' => $node->fb_stream_from_token,
+        'message' => $node->fb_stream_message,
+        'link' => $node_url,
+        'name' => $node->title,
+        'description' => $node->teaser,
+        'caption' => variable_get('site_name', ''),
+        'actions' => json_encode(array(
+                                   'name' => t('View More'),
+                                   'link' => $node_url,
+                                 )),
+        'method' => 'POST',
+      );
+
+      // Let third parties alter params.
+      $params = fb_invoke(FB_STREAM_OP_PRE_POST, array('node' => $node), $params, 'fb_stream');
+      if ($params['name']) {
+
+        // http://stackoverflow.com/questions/4652628/what-markup-is-allowed-in-the-description-of-a-facebook-feed-post
+        $params['description'] = strip_tags($params['description'], '<b><i><small><center>');
+
+        try {
+          $result = fb_graph($node->fb_stream_to . '/feed', $params, 'POST');
+          // Result should include an id of the post, but we can't query the single post via the graph.
+          if ($result['id']) {
+            // TODO: link to proper wall.
+            drupal_set_message(t('Content posted to Facebook.'));
+          }
+        }
+        catch (Exception $e) {
+          drupal_set_message(t('Unable to post content to facebook.'), 'warning');
+          fb_log_exception($e, t('Post to Facebook stream failed.'));
+        }
+      }
+    }
+  }
+}
+
+
+/**
+ * Implements hook_form_alter().
+ */
+function fb_stream_form_alter(&$form, $form_state, $form_id) {
+
+  if (isset($form['#node_type']) && 'node_type_form' == $form_id) {
+    fb_stream_node_settings_form($form);
+  }
+  elseif ($form['#id'] == 'node-form') {
+    $type = $form['type']['#value'];
+    if (variable_get('fb_stream_enabled__' . $type, FALSE) &&
+        ($token = variable_get(FB_STREAM_VAR_TOKEN, NULL)) &&
+        user_access(FB_STREAM_PERM_POST)) {
+
+      // Defaults configured per node type.
+      $from_token = variable_get('fb_stream_from_token__' . $type, $token);
+      $from_id = variable_get('fb_stream_from__' . $type, NULL);
+      $from_user = variable_get('fb_stream_from_user__' . $type, NULL);
+      $to_id = variable_get('fb_stream_to__' . $type, NULL);
+
+      try {
+        // TODO: consolodate graph api, use batch/cache.
+        $to = fb_graph($to_id, array('access_token' => $token));
+        $via = fb_graph('app', array('access_token' => $token));
+        $me = fb_graph('me', array('access_token' => $token));
+
+        $form['fb_stream'] = array(
+          '#type' => 'fieldset',
+          '#title' => t('Post to Facebook'),
+          '#collapsible' => TRUE,
+          '#collapsed' => TRUE,
+        );
+
+        // These args will be passed to t() more than once in the code that follows.
+        $t_args = array(
+          '%to' => $to['name'],
+          '%via' => $via['name'],
+          '%me' => $me['name'],
+        );
+
+        $form['fb_stream']['fb_stream_do_post'] = array(
+          '#type' => 'checkbox',
+          '#title' => t('Post to Facebook'),
+          '#description' => t('Post this content to %to on Facebook via the %via application and %me\'s account.', $t_args),
+        );
+
+        // Default details configured per node type.
+        $form['fb_stream']['override']['fb_stream_to'] = array(
+          '#type' => 'value',
+          '#value' => $to_id,
+        );
+        $form['fb_stream']['override']['fb_stream_from_user'] = array(
+          '#type' => 'value',
+          '#value' => $from_user,
+        );
+
+        if (user_access(FB_STREAM_PERM_OVERRIDE)) {
+          // Allow override of author/wall.
+          $to_options = array(); // IDs of user/page walls.
+          $from_options = array(); // deprecated.  No longer used. Clean this up! XXX
+          $from_tokens = array(); // Access tokens for posting as Page (not user).
+
+          fb_stream_post_options($token, $to_options, $from_options, $from_tokens);
+
+          $form['fb_stream']['override'] = array(
+            '#type' => 'fieldset',
+            '#title' => t('Override defaults (advanced)'),
+            '#collapsible' => TRUE,
+            '#collapsed' => TRUE,
+          );
+
+          $form['fb_stream']['override']['fb_stream_to'] = array(
+            '#type' => 'select',
+            '#title' => t("Post to Wall"),
+            '#options' => $to_options,
+            '#description' => t('Post to which Facebook Wall?'),
+            '#default_value' => $to_id,
+          );
+
+          $form['fb_stream']['override']['fb_stream_from_user'] = array(
+            '#type' => 'checkbox',
+            '#title' => t('Post as %me', $t_args),
+            '#description' => t('If you selected a Page Wall, the post\'s author will be that Page.  Check this box to force the author to be the user (%me) instead. <br/>If unchecked, the post will reach fans who <em>like</em> the Page.  If checked, the post will reach <em>friends of</em> %me.', $t_args),
+            '#default_value' => $from_user,
+          );
+
+          // We'll need the token that corresponds to our "from" option.  We don't want to include tokens directly in the form, for security.
+          $form['#fb_stream_from_tokens'] = $from_tokens;
+          $form['#validate'][] = 'fb_stream_node_form_validate';
+          $form['fb_stream']['fb_stream_from_token'] = array(
+            // placeholder.  See fb_stream_node_settings_form_validate().
+            '#type' => 'value',
+            '#value' => $from_token,
+          );
+        }
+
+        $form['fb_stream']['fb_stream_message'] = array(
+          '#type' => 'textfield',
+          '#title' => 'Message',
+          '#default_value' => '',
+          '#description' => 'Optionally, a brief message to precede the link.',
+        );
+
+      }
+      catch (Exception $e) {
+        drupal_set_messages(t('Post to facebook options not available.  Possibly a temporary failure to reach facebook.com, or an expired access token.'), 'warning');
+        fb_log_exception($e, t('Failed to access facebook altering node-form.'));
+      }
+    }
+  }
+
+}
+
+/**
+ * Helper function to add post options to a form.
+ */
+function fb_stream_post_options($token, &$to_options, &$from_options, &$from_tokens) {
+  try {
+    // TODO: consolodate graph api, use batch. And cache.
+    $me = fb_graph('me', array('access_token' => $token));
+    $accounts = fb_graph('me/accounts', array('access_token' => $token));
+
+    // "to" options are facebook ids.
+    $to_options[$me['id']] = $me['name'];
+
+    // "from" options are ids.
+    $from_options[$me['id']] = $me['name'];
+
+    // We will also need the access token that corresponds to "from" options.
+    $from_tokens[$me['id']] = $token;
+
+    foreach ($accounts['data'] as $account) {
+      // @TODO add only if access_token found
+      if (!isset($account['name'])) {
+        // @TODO handle applications more smarter.
+        $name = $account['category'] . ' ' . $account['id'];
+      }
+      else {
+        $name = $account['name'];
+      }
+      $to_options[$account['id']] = $name;
+
+      if (!empty($account['access_token'])) {
+        $from_options[$account['id']] = $name;
+        $from_tokens[$account['id']] = $account['access_token'];
+      }
+    }
+  }
+  catch (Exception $e) {
+    // TODO: link to token admin page.
+    fb_log_exception($e, t('Failed to get facebook post options.'));
+  }
+}
+
+/**
+  * Helper function for hook_form_alter() renders the settings per node-type.
+  */
+function fb_stream_node_settings_form(&$form) {
+  $node_type = $form['#node_type']->type;
+
+  $token = variable_get(FB_STREAM_VAR_TOKEN, '');
+  $to_options = array();
+  $from_options = array();
+  $from_tokens = array();
+
+  try {
+    // Get the possible author/wall combinations from facebook.
+    fb_stream_post_options($token, $to_options, $from_options, $from_tokens);
+
+    // TODO: consolodate graph api, use batch. And cache.
+    $me = fb_graph('me', array('access_token' => $token));
+    $via = fb_graph('app', array('access_token' => $token));
+
+    $t_args = array(
+      '%from' => $me['name'],
+      '%via' => $via['name'],
+    );
+
+    // Include options in the form.
+    $form['fb_stream'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Facebook Posts'),
+      '#weight' => 0,
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    );
+
+    $var_prefix = 'fb_stream_enabled_';
+    $var = $var_prefix . '_' . $node_type;
+    $form['fb_stream'][$var_prefix] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Enable Post to Facebook for this content type.'),
+      '#default_value' => variable_get($var, FALSE),
+    );
+
+    $var_prefix = 'fb_stream_to_';
+    $var = $var_prefix . '_' . $node_type;
+    $form['fb_stream'][$var_prefix] = array(
+      '#type' => 'select',
+      '#title' => t("Post to wall"),
+      '#options' => $to_options,
+      '#description' => t('Post to which Facebook Wall?'),
+      '#default_value' => variable_get($var, NULL),
+    );
+
+    $var_prefix = 'fb_stream_from_user_';
+    $var = $var_prefix . '_' . $node_type;
+    $form['fb_stream'][$var_prefix] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Post as user'),
+      '#description' => t('If you selected a Page Wall, the post\'s author will be that Page.  Check this box to force the author to be the user instead. <br/>If unchecked, the post will reach fans who <em>like</em> the Page.  If checked, the post will reach <em>friends of</em> the user (%from).', $t_args),
+    );
+
+    // We'll need the token that corresponds to our "from" option.  We don't want to include tokens directly in the form, for security.
+    $form['#fb_stream_from_tokens'] = $from_tokens;
+    $form['#validate'][] = 'fb_stream_node_settings_form_validate';
+    $form['fb_stream']['fb_stream_from_token_'] = array(
+      // placeholder.  See fb_stream_node_settings_form_validate().
+      '#type' => 'value',
+      '#value' => NULL,
+    );
+  }
+  catch (Exception $e) {
+    // TODO: link to token admin page.
+    fb_log_exception($e, t('Failed to access facebook using the fb_stream token (node settings form).'));
+  }
+}
+
+function fb_stream_node_settings_form_validate($form, &$form_state) {
+  $values = $form_state['values'];
+  if (!$values['fb_stream_from_user_'] &&
+      ($to_id = $values['fb_stream_to_'])) {
+    // Save the token for the facebook wall.
+    form_set_value($form['fb_stream']['fb_stream_from_token_'],
+                   $form['#fb_stream_from_tokens'][$to_id], $form_state);
+  }
+}
+
+function fb_stream_node_form_validate($form, &$form_state) {
+  $values = $form_state['values'];
+
+  if (!$values['fb_stream_from_user'] &&
+      ($to_id = $values['fb_stream_to']) &&
+      count($form['#fb_stream_from_tokens'])) {
+    form_set_value($form['fb_stream']['fb_stream_from_token'],
+                   $form['#fb_stream_from_tokens'][$to_id], $form_state);
+  }
+}
+
+/**
+ * Gets the auto node title setting associated with the given content type.
+ */
+function fb_stream_get_setting($type) {
+  return variable_get('fb_stream_'. $type, FALSE);
+}
+
+
 /**
- * Publish to a user's stream, or update their status.
+ * Publish to a user's stream or update their status, via a dialog.
  *
  * Calling this method will, through javascript, add content to a
  * user's wall or update their status.  The javascript will be written
@@ -85,7 +413,6 @@ function fb_stream_get_stream_dialog_data($fb_app = NULL) {
  */
 function fb_stream_fb($op, $data, &$return) {
   if ($op == FB_OP_JS) {
-    //dpm(func_get_args(), "fb_stream_fb($op)");
     $params_array = fb_stream_get_stream_dialog_data($data['fb_app']);
     $js = fb_stream_js($params_array);
     $return += $js;
