diff --git a/db/dbic.conf b/db/dbic.conf
new file mode 100644
index 0000000000..3e53a59260
--- /dev/null
+++ b/db/dbic.conf
@@ -0,0 +1,18 @@
+schema_class TwittElection::Schema
+
+lib lib
+
+# connection string
+
+ dsn dbi:mysql:database=twittelection
+ user root
+ pass
+
+
+# dbic loader options
+
+ dump_directory ./lib
+ components InflateColumn::DateTime
+ components TimeStamp
+ use_moose 1
+
diff --git a/db/twittelect.sql b/db/twittelect.sql
index 4c473c6251..10d8817400 100644
--- a/db/twittelect.sql
+++ b/db/twittelect.sql
@@ -1,7 +1,4 @@
-create table list_owner (
- id integer primary key,
- name varchar(200) not null
-);
+begin;
create table party (
id integer primary key,
@@ -10,9 +7,7 @@ create table party (
create table constituency (
id integer primary key,
- name varchar(200) not null,
- list_owner_id integer not null,
- foreign key (list_owner_id) references list_owner(id)
+ name varchar(200) not null
);
create table candidate (
@@ -25,3 +20,5 @@ create table candidate (
foreign key (party_id) references party(id),
foreign key (constituency_id) references constituency(id)
);
+
+commit;
diff --git a/lib/TwittElection/Schema.pm b/lib/TwittElection/Schema.pm
new file mode 100644
index 0000000000..b2cc686f6b
--- /dev/null
+++ b/lib/TwittElection/Schema.pm
@@ -0,0 +1,20 @@
+use utf8;
+package TwittElection::Schema;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+use Moose;
+use MooseX::MarkAsMethods autoclean => 1;
+extends 'DBIx::Class::Schema';
+
+__PACKAGE__->load_namespaces;
+
+
+# Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-08-15 20:12:34
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:POtcyUDJVg5/NGxsfXb2fQ
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+__PACKAGE__->meta->make_immutable(inline_constructor => 0);
+1;
diff --git a/lib/TwittElection/Schema/Result/Candidate.pm b/lib/TwittElection/Schema/Result/Candidate.pm
new file mode 100644
index 0000000000..6f55a09566
--- /dev/null
+++ b/lib/TwittElection/Schema/Result/Candidate.pm
@@ -0,0 +1,151 @@
+use utf8;
+package TwittElection::Schema::Result::Candidate;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+TwittElection::Schema::Result::Candidate
+
+=cut
+
+use strict;
+use warnings;
+
+use Moose;
+use MooseX::NonMoose;
+use MooseX::MarkAsMethods autoclean => 1;
+extends 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L
+
+=item * L
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
+
+=head1 TABLE: C
+
+=cut
+
+__PACKAGE__->table("candidate");
+
+=head1 ACCESSORS
+
+=head2 id
+
+ data_type: 'integer'
+ is_nullable: 0
+
+=head2 name
+
+ data_type: 'varchar'
+ is_nullable: 0
+ size: 200
+
+=head2 twitter
+
+ data_type: 'varchar'
+ is_nullable: 1
+ size: 200
+
+=head2 party_id
+
+ data_type: 'integer'
+ is_foreign_key: 1
+ is_nullable: 0
+
+=head2 constituency_id
+
+ data_type: 'integer'
+ is_foreign_key: 1
+ is_nullable: 1
+
+=head2 current_mp
+
+ data_type: 'integer'
+ default_value: 0
+ is_nullable: 0
+
+=cut
+
+__PACKAGE__->add_columns(
+ "id",
+ { data_type => "integer", is_nullable => 0 },
+ "name",
+ { data_type => "varchar", is_nullable => 0, size => 200 },
+ "twitter",
+ { data_type => "varchar", is_nullable => 1, size => 200 },
+ "party_id",
+ { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+ "constituency_id",
+ { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+ "current_mp",
+ { data_type => "integer", default_value => 0, is_nullable => 0 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 RELATIONS
+
+=head2 constituency
+
+Type: belongs_to
+
+Related object: L
+
+=cut
+
+__PACKAGE__->belongs_to(
+ "constituency",
+ "TwittElection::Schema::Result::Constituency",
+ { id => "constituency_id" },
+ {
+ is_deferrable => 1,
+ join_type => "LEFT",
+ on_delete => "RESTRICT",
+ on_update => "RESTRICT",
+ },
+);
+
+=head2 party
+
+Type: belongs_to
+
+Related object: L
+
+=cut
+
+__PACKAGE__->belongs_to(
+ "party",
+ "TwittElection::Schema::Result::Party",
+ { id => "party_id" },
+ { is_deferrable => 1, on_delete => "RESTRICT", on_update => "RESTRICT" },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-08-15 20:12:34
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CpWHo/zzZ6BBuVPuTXoQAQ
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+__PACKAGE__->meta->make_immutable;
+1;
diff --git a/lib/TwittElection/Schema/Result/Constituency.pm b/lib/TwittElection/Schema/Result/Constituency.pm
new file mode 100644
index 0000000000..ecb685e473
--- /dev/null
+++ b/lib/TwittElection/Schema/Result/Constituency.pm
@@ -0,0 +1,99 @@
+use utf8;
+package TwittElection::Schema::Result::Constituency;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+TwittElection::Schema::Result::Constituency
+
+=cut
+
+use strict;
+use warnings;
+
+use Moose;
+use MooseX::NonMoose;
+use MooseX::MarkAsMethods autoclean => 1;
+extends 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L
+
+=item * L
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
+
+=head1 TABLE: C
+
+=cut
+
+__PACKAGE__->table("constituency");
+
+=head1 ACCESSORS
+
+=head2 id
+
+ data_type: 'integer'
+ is_nullable: 0
+
+=head2 name
+
+ data_type: 'varchar'
+ is_nullable: 0
+ size: 200
+
+=cut
+
+__PACKAGE__->add_columns(
+ "id",
+ { data_type => "integer", is_nullable => 0 },
+ "name",
+ { data_type => "varchar", is_nullable => 0, size => 200 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 RELATIONS
+
+=head2 candidates
+
+Type: has_many
+
+Related object: L
+
+=cut
+
+__PACKAGE__->has_many(
+ "candidates",
+ "TwittElection::Schema::Result::Candidate",
+ { "foreign.constituency_id" => "self.id" },
+ { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-08-15 20:12:34
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3nXUzbwFvl5i0kTFMaVjNQ
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+__PACKAGE__->meta->make_immutable;
+1;
diff --git a/lib/TwittElection/Schema/Result/Party.pm b/lib/TwittElection/Schema/Result/Party.pm
new file mode 100644
index 0000000000..f9f6fa87c4
--- /dev/null
+++ b/lib/TwittElection/Schema/Result/Party.pm
@@ -0,0 +1,99 @@
+use utf8;
+package TwittElection::Schema::Result::Party;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+=head1 NAME
+
+TwittElection::Schema::Result::Party
+
+=cut
+
+use strict;
+use warnings;
+
+use Moose;
+use MooseX::NonMoose;
+use MooseX::MarkAsMethods autoclean => 1;
+extends 'DBIx::Class::Core';
+
+=head1 COMPONENTS LOADED
+
+=over 4
+
+=item * L
+
+=item * L
+
+=back
+
+=cut
+
+__PACKAGE__->load_components("InflateColumn::DateTime", "TimeStamp");
+
+=head1 TABLE: C
+
+=cut
+
+__PACKAGE__->table("party");
+
+=head1 ACCESSORS
+
+=head2 id
+
+ data_type: 'integer'
+ is_nullable: 0
+
+=head2 name
+
+ data_type: 'varchar'
+ is_nullable: 0
+ size: 200
+
+=cut
+
+__PACKAGE__->add_columns(
+ "id",
+ { data_type => "integer", is_nullable => 0 },
+ "name",
+ { data_type => "varchar", is_nullable => 0, size => 200 },
+);
+
+=head1 PRIMARY KEY
+
+=over 4
+
+=item * L
+
+=back
+
+=cut
+
+__PACKAGE__->set_primary_key("id");
+
+=head1 RELATIONS
+
+=head2 candidates
+
+Type: has_many
+
+Related object: L
+
+=cut
+
+__PACKAGE__->has_many(
+ "candidates",
+ "TwittElection::Schema::Result::Candidate",
+ { "foreign.party_id" => "self.id" },
+ { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-08-15 20:12:34
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JCZbMFhxCEvMkmUtkSBc6A
+
+
+# You can replace this text with custom code or comments, and it will be preserved on regeneration
+__PACKAGE__->meta->make_immutable;
+1;