diff --git a/.gitignore b/.gitignore
index 83b754c04..0a6215ba9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,9 +8,11 @@ Homestead.yaml
 /public/css
 /public/js
 /public/bower
+/public/build/
 /storage/images
 _ide_helper.php
 /storage/debugbar
 .phpstorm.meta.php
 yarn.lock
-/bin
\ No newline at end of file
+/bin
+nbproject
\ No newline at end of file
diff --git a/app/Comment.php b/app/Comment.php
new file mode 100644
index 000000000..9ef892bdc
--- /dev/null
+++ b/app/Comment.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace BookStack;
+
+class Comment extends Ownable
+{
+    protected $fillable = ['text', 'html'];
+    
+    /**
+     * Get the entity that this comment belongs to
+     * @return \Illuminate\Database\Eloquent\Relations\MorphTo
+     */
+    public function entity()
+    {
+        return $this->morphTo('entity');
+    }
+    
+    /**
+     * Get the page that this comment is in.
+     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+     */
+    public function page()
+    {
+        return $this->belongsTo(Page::class);
+    }
+    
+    /**
+     * Get the owner of this comment.
+     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+     */
+    public function user() 
+    {
+        return $this->belongsTo(User::class);
+    }
+}
diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php
new file mode 100644
index 000000000..de97169a8
--- /dev/null
+++ b/app/Http/Controllers/CommentController.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace BookStack\Http\Controllers;
+
+use Illuminate\Http\Request;
+
+use BookStack\Http\Requests;
+
+class CommentController extends Controller
+{
+    
+    public function add(Request $request, $pageId) {
+        // $this->checkOwnablePermission('page-view', $page);
+    }
+    
+    public function update(Request $request, $id) {
+        // Check whether its an admin or the comment owner.
+        // $this->checkOwnablePermission('page-view', $page);
+    }
+    
+    public function destroy($id) {
+        // Check whether its an admin or the comment owner.
+        // $this->checkOwnablePermission('page-view', $page);
+    }
+    
+    public function getLastXComments($pageId) {
+        // $this->checkOwnablePermission('page-view', $page);
+    }
+    
+    public function getChildComments($pageId, $id) {
+        // $this->checkOwnablePermission('page-view', $page);
+    }
+}
diff --git a/app/Page.php b/app/Page.php
index b24e7778a..83ef6f350 100644
--- a/app/Page.php
+++ b/app/Page.php
@@ -39,6 +39,15 @@ class Page extends Entity
     {
         return $this->belongsTo(Chapter::class);
     }
+    
+    /**
+     * Get the comments in the page.
+     * @return \Illuminate\Database\Eloquent\Relations\HasMany
+     */
+    public function comment()
+    {
+        return $this->hasMany(Comment::class);
+    }
 
     /**
      * Check if this page has a chapter.
diff --git a/app/Repos/CommentRepo.php b/app/Repos/CommentRepo.php
new file mode 100644
index 000000000..e8db3f83e
--- /dev/null
+++ b/app/Repos/CommentRepo.php
@@ -0,0 +1,17 @@
+<?php namespace BookStack\Repos;
+
+use BookStack\Comment;
+use BookStack\Entity;
+
+/**
+ * Class TagRepo
+ * @package BookStack\Repos
+ */
+class CommentRepo {
+    /**
+     *
+     * @var Comment $comment 
+     */
+    protected $comment;
+    
+}
\ No newline at end of file
diff --git a/database/migrations/2017_01_01_130541_create_comments_table.php b/database/migrations/2017_01_01_130541_create_comments_table.php
new file mode 100644
index 000000000..3565192a4
--- /dev/null
+++ b/database/migrations/2017_01_01_130541_create_comments_table.php
@@ -0,0 +1,38 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class CreateCommentsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('comments', function (Blueprint $table) {
+            $table->increments('id')->unsigned();                       
+            $table->integer('page_id')->unsigned();
+            $table->longText('text')->nullable();
+            $table->longText('html')->nullable();
+            $table->integer('parent_id')->unsigned()->nullable();
+            $table->integer('created_by')->unsigned();
+            $table->integer('updated_by')->unsigned()->nullable();
+            $table->index(['page_id', 'parent_id']);
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('comments');
+    }
+}
diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php
index 0d97a6a4b..6f4009f72 100644
--- a/resources/views/home.blade.php
+++ b/resources/views/home.blade.php
@@ -51,7 +51,7 @@
                     @include('partials/entity-list', [
                     'entities' => $recentlyUpdatedPages,
                     'style' => 'compact',
-                    'emptyText' => trans('entites.no_pages_recently_updated')
+                    'emptyText' => trans('entities.no_pages_recently_updated')
                     ])
                 </div>
             </div>
diff --git a/routes/web.php b/routes/web.php
index 076ffb94f..42b88f3d6 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -113,6 +113,13 @@ Route::group(['middleware' => 'auth'], function () {
 
     Route::get('/ajax/search/entities', 'SearchController@searchEntitiesAjax');
 
+    // Comments
+    Route::post('/ajax/page/{pageId}/comment/', 'CommentController@add');
+    Route::put('/ajax/page/comment/{id}', 'CommentController@update');
+    Route::delete('/ajax/comment/{id}', 'CommentController@destroy');
+    Route::get('/ajax/page/{pageId}/comment/', 'CommentController@getLastXComments');
+    Route::get('/ajax/page/{pageId}/comment/{id}/sub-comments', 'CommentController@getChildComments');    
+    
     // Links
     Route::get('/link/{id}', 'PageController@redirectFromLink');