diff --git a/chessboard.field.inc b/chessboard.field.inc
new file mode 100644
index 0000000..4cb02bb
--- /dev/null
+++ b/chessboard.field.inc
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Field module functionality for the Chessboard module.
+ */
+
+/**
+ * Implements hook_field_info().
+ */
+function chessboard_field_info() {
+  return array(
+    'chessboard' => array(
+      'label' => t('Chessboard'),
+      'description' => t('An entity field containing a chessboard.'),
+      'default_widget' => 'chessboard_default',
+      'default_formatter' => 'chessboard_simple',
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_is_empty().
+ */
+function chessboard_field_is_empty($item, $field) {
+  return !isset($item['piece_placement']) || $item['piece_placement'] === '';
+}
+
+/**
+ * Implements hook_field_formatter_info().
+ */
+function chessboard_field_formatter_info() {
+  return array(
+    'chessboard_simple' => array(
+      'label' => t('Chessboard simple'),
+      'field types' => array('chessboard'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_formatter_view().
+ */
+function chessboard_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+  $element = array();
+
+  switch ($display['type']) {
+    case 'chessboard_simple':
+      foreach ($items as $delta => $item) {
+        $element[$delta] = array(
+          '#markup' => '<pre>' . check_plain(chunk_split($item['piece_placement'], 8, "\n")) . '</pre>',
+        );
+      }
+      break;
+  }
+  return $element;
+}
+
+/**
+ * Implements hook_field_widget_info().
+ */
+function chessboard_field_widget_info() {
+  return array(
+    'chessboard_default' => array(
+      'label' => t('Chessboard'),
+      'field types' => array('chessboard'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_widget_form().
+ */
+function chessboard_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
+  $default_value = isset($items[$delta]['piece_placement']) ? $items[$delta]['piece_placement'] : NULL;
+
+  $widget = $element;
+
+  switch ($instance['widget']['type']) {
+    case 'chessboard_default':
+      $widget += array(
+        '#type' => 'textfield',
+        '#default_value' => $value,
+        '#size' => 64,
+        '#maxlength' => 64,
+      );
+      break;
+  }
+
+  $element['piece_placement'] = $widget;
+  return $element;
+}
diff --git a/chessboard.install b/chessboard.install
index 92bc4a2..a755aad 100644
--- a/chessboard.install
+++ b/chessboard.install
@@ -6,6 +6,22 @@
  */
 
 /**
+ * Implements hook_field_schema().
+ */
+function chessboard_field_schema($field) {
+  $columns = array(
+    'piece_placement' => array('type' => 'char', 'length' => 64, 'not null' => FALSE),
+  );
+  $indexes = array(
+    'piece_placement' => array('piece_placement'),
+  );
+  return array(
+    'columns' => $columns,
+    'indexes' => $indexes,
+  );
+}
+
+/**
  * Implements hook_uninstall().
  */
 function chessboard_uninstall() {
diff --git a/chessboard.module b/chessboard.module
index 2dcaadd..4f1142f 100644
--- a/chessboard.module
+++ b/chessboard.module
@@ -1,5 +1,8 @@
 <?php
 
+// Load all Field module hooks for Chessboard.
+module_load_include('inc', 'chessboard', 'chessboard.field');
+
 function chessboard_border_filename($border) {
   // $border: T, B, L, R, TL, TR, BL, BR
   switch ($border) {
