diff --git a/templates/WidgetArea.ss b/templates/WidgetArea.ss
new file mode 100644
index 000000000..cda23ea06
--- /dev/null
+++ b/templates/WidgetArea.ss
@@ -0,0 +1,3 @@
+<% control Widgets %>
+ $WidgetHolder
+<% end_control %>
\ No newline at end of file
diff --git a/templates/WidgetHolder.ss b/templates/WidgetHolder.ss
new file mode 100644
index 000000000..5a988176f
--- /dev/null
+++ b/templates/WidgetHolder.ss
@@ -0,0 +1,2 @@
+
$Title
+$Content
\ No newline at end of file
diff --git a/widgets/Widget.php b/widgets/Widget.php
new file mode 100644
index 000000000..2ca71f075
--- /dev/null
+++ b/widgets/Widget.php
@@ -0,0 +1,89 @@
+ "Int",
+ "Sort" => "Int"
+ );
+
+ static $default_sort = "Sort";
+
+ static $title = "Widget Title";
+ static $cmsTitle = "Name of this widget";
+ static $description = "Description of what this widget does.";
+
+ function getCMSFields() {
+ return new FieldSet();
+ }
+
+ function WidgetHolder() {
+ return $this->renderWith("WidgetHolder");
+ }
+
+ function Content() {
+ return $this->renderWith($this->class);
+ }
+
+ function Title() {
+ $instance = singleton($this->class);
+ return $instance->uninherited('title', true);
+ }
+
+ function CMSTitle() {
+ $instance = singleton($this->class);
+ return $instance->uninherited('cmsTitle', true);
+ }
+
+ function Description() {
+ $instance = singleton($this->class);
+ return $instance->uninherited('description', true);
+ }
+
+ function DescriptionSegment() {
+ return $this->renderWith('WidgetDescription');
+ }
+
+ function EditableSegment() {
+ return $this->renderWith('WidgetEditor');
+ }
+
+ function CMSEditor() {
+ $output = '';
+
+ $fields = $this->getCMSFields();
+ foreach($fields as $field) {
+ $name = $field->Name();
+ $field->setValue($this->getField($name));
+ $renderedField = $field->FieldHolder();
+ $renderedField = ereg_replace("name=\"([A-Za-z0-9\-_]+)\"", "name=\"Widget[" . $this->ID . "][\\1]\"", $renderedField);
+ $renderedField = ereg_replace("id=\"([A-Za-z0-9\-_]+)\"", "id=\"Widget[" . $this->ID . "][\\1]\"", $renderedField);
+ $output .= $renderedField;
+ }
+ return $output;
+ }
+
+ function ClassName() {
+ return $this->class;
+ }
+
+ function Name() {
+ return "Widget[".$this->ID."]";
+ }
+
+ function populateFromPostData($data) {
+ foreach($data as $name => $value) {
+ if($name != "Type") {
+ $this->setField($name, $value);
+ }
+ }
+
+ $this->write();
+
+ // The field must be written to ensure a unique ID.
+ $this->Name = $this->class.$this->ID;
+ $this->write();
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/widgets/WidgetArea.php b/widgets/WidgetArea.php
new file mode 100644
index 000000000..e0254a26d
--- /dev/null
+++ b/widgets/WidgetArea.php
@@ -0,0 +1,15 @@
+ "Widget"
+ );
+
+ function forTemplate() {
+ return $this->renderWith("WidgetArea");
+ }
+}
+
+?>
\ No newline at end of file