diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..567609b1234a9b8806c5a05da6c866e480aa148d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+build/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..2614aa6f52b569feba19c53168c92e37ffaa32d3
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.26)
+
+project(dict VERSION 0.1 LANGUAGES C)
+
+file(GLOB src CONFIGURE_DEPENDS "*.h" "*.c")
+add_executable(dict ${src})
+
+target_compile_options(dict PRIVATE -Wall -Wextra -Wpedantic -Werror)
+target_include_directories(dict PUBLIC "${PROJECT_BINARY_DIR}")
+target_link_libraries(dict sqlite3)
+
diff --git a/data.c b/data.c
new file mode 100644
index 0000000000000000000000000000000000000000..5a9a103daf2dd02f9b494385a08cbbe4a8e316ea
--- /dev/null
+++ b/data.c
@@ -0,0 +1,183 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "data.h"
+
+const char *insert_into = "INSERT INTO words (LINE) VALUES($VVV);";
+const char *select_words = "SELECT Id, Line FROM words LIMIT 10;";
+const char *create_table = "CREATE TABLE IF NOT EXISTS words (ID INTEGER PRIMARY KEY AUTOINCREMENT, LINE TEXT NOT NULL);";
+
+Data* new_data(const char* con) {
+ Data* data = (Data*)malloc(sizeof(Data));
+
+ int v = sqlite3_open(con, &(data->db));
+ if (v == SQLITE_OK) {
+ return data;
+ }
+
+ print_result_code(v);
+ return NULL;
+}
+
+
+void free_data(Data* data) {
+ sqlite3_close(data->db);
+ free(data);
+}
+
+void insert(Data* data, char* line) {
+ sqlite3_stmt *stmt;
+ int r = sqlite3_prepare_v2(data->db, insert_into, -1, &stmt, NULL);
+
+ if (r != SQLITE_OK) {
+ printf("Error executing insert: ");
+ print_result_code(r);
+ printf("\n");
+ return;
+ }
+
+ // binds the paremets to the statement, in this case the line;
+ sqlite3_bind_text(stmt, 1, line, -1, NULL);
+
+ int c = sqlite3_step(stmt);
+ if (c != SQLITE_DONE) {
+ printf("Error executing insert: ");
+ print_result_code(r);
+ printf("\n");
+ }
+}
+
+void bootstrap(Data* data) {
+ sqlite3_stmt *stmt;
+ int r = sqlite3_prepare_v2(data->db, create_table, -1, &stmt, NULL);
+
+ if (r != SQLITE_OK) {
+ printf("Error preparing bootstrap: ");
+ print_result_code(r);
+ printf("\n");
+ return;
+ }
+
+ int c = sqlite3_step(stmt);
+ if (c != SQLITE_DONE) {
+ printf("Error executing bootstrap: ");
+ print_result_code(r);
+ printf("\n");
+ }
+}
+
+LIST* select(Data* data) {
+ sqlite3_stmt *stmt;
+ int r = sqlite3_prepare_v2(data->db, select_words, -1, &stmt, NULL);
+
+ if (r != SQLITE_OK) {
+ printf("Error executing select: ");
+ print_result_code(r);
+ printf("\n");
+ return NULL;
+ }
+
+ LIST *list = NULL;
+
+ int m = sqlite3_step(stmt);
+ while(m == SQLITE_ROW) {
+ Word *word = (Word*)malloc(sizeof(Word));
+
+ int id = sqlite3_column_int(stmt, 0);
+ const unsigned char *line = sqlite3_column_text(stmt, 1);
+
+ word->Id = id;
+ word->Line = line;
+ list = list_add(list, word);
+
+ m = sqlite3_step(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return list;
+}
+
+void print_result_code(int code) {
+ switch(code) {
+ // Primary result code
+ case SQLITE_ABORT:
+ printf("SQLITE_ABORT");
+ break;
+ case SQLITE_AUTH:
+ printf("SQLITE_AUTH");
+ break;
+ case SQLITE_BUSY:
+ printf("SQLITE_BUSY");
+ break;
+ case SQLITE_CANTOPEN:
+ printf("SQLITE_CANTOPEN");
+ break;
+ case SQLITE_CONSTRAINT:
+ printf("SQLITE_CONSTRAINT");
+ break;
+ case SQLITE_CORRUPT:
+ printf("SQLITE_CORRUPT");
+ break;
+ case SQLITE_DONE:
+ printf("SQLITE_DONE");
+ break;
+ case SQLITE_EMPTY:
+ printf("SQLITE_EMPTY");
+ break;
+ case SQLITE_ERROR:
+ printf("SQLITE_ERROR");
+ break;
+ case SQLITE_FORMAT:
+ printf("SQLITE_FORMAT");
+ break;
+ case SQLITE_INTERNAL:
+ printf("SQLITE_INTERNAL");
+ break;
+ case SQLITE_INTERRUPT:
+ printf("SQLITE_INTERRUPT");
+ break;
+ case SQLITE_IOERR:
+ printf("SQLITE_IOERR");
+ break;
+ case SQLITE_LOCKED:
+ printf("SQLITE_LOCKED");
+ break;
+ case SQLITE_MISMATCH:
+ printf("SQLITE_MISMATCH");
+ break;
+ case SQLITE_MISUSE:
+ printf("SQLITE_MISUSE");
+ break;
+ case SQLITE_NOLFS:
+ printf("SQLITE_NOLFS");
+ break;
+ case SQLITE_NOMEM:
+ printf("SQLITE_NOMEM");
+ break;
+ case SQLITE_NOTADB:
+ printf("SQLITE_NOTADB");
+ break;
+ case SQLITE_NOTFOUND:
+ printf("SQLITE_NOTFOUND");
+ break;
+ case SQLITE_NOTICE:
+ printf("SQLITE_NOTICE");
+ break;
+ case SQLITE_OK:
+ printf("SQLITE_OK");
+ break;
+ case SQLITE_PERM:
+ printf("SQLITE_PERM");
+ break;
+ case SQLITE_SCHEMA:
+ printf("SQLITE_SCHEMA");
+ break;
+ case SQLITE_TOOBIG:
+ printf("SQLITE_TOOBIG");
+ break;
+ case SQLITE_WARNING:
+ printf("SQLITE_WARNING");
+ break;
+ }
+}
diff --git a/data.h b/data.h
new file mode 100644
index 0000000000000000000000000000000000000000..db8aedc2a5e9ea62ef2f577718b9dbf8418c9a4c
--- /dev/null
+++ b/data.h
@@ -0,0 +1,47 @@
+#pragma once
+#include <sqlite3.h>
+#include "list.h"
+
+/*
+ * This word into the dictionary
+ */
+typedef struct word {
+ int Id;
+ const unsigned char *Line;
+} Word;
+
+/*
+ * This is database connection.
+ */
+typedef struct data {
+ sqlite3 *db;
+} Data;
+
+
+/*
+ * create a new data struct from sqlite filename.
+ */
+Data* new_data(const char*);
+
+
+void free_data(Data*);
+
+/*
+ * Create the tables.
+ */
+void bootstrap(Data*);
+
+/*
+ * insert line into database.
+ */
+void insert(Data*, char*);
+
+/*
+ * Select all words.
+ */
+LIST* select(Data*);
+
+/*
+ * Print result code from sqlite.
+ */
+void print_result_code(int error);
diff --git a/list.c b/list.c
new file mode 100644
index 0000000000000000000000000000000000000000..a40dd576db2dcc385a4bb2f4fb8f6f4e99102793
--- /dev/null
+++ b/list.c
@@ -0,0 +1,44 @@
+#include "list.h"
+#include <stdlib.h>
+
+LIST* list_add(LIST* list, void* item)
+{
+
+ if (list == NULL)
+ {
+ list = (LIST*)malloc(sizeof(LIST));
+ list->size = 0;
+ list->list = (void**)malloc(sizeof(0));
+
+ }
+
+ list->size ++;
+ void** new_list = (void**)reallocarray(list->list, list->size, sizeof(void*));
+
+ new_list[list->size-1] = item;
+ list->list = new_list;
+
+ return list;
+
+}
+
+LIST* list_remove(LIST* list, unsigned int pos)
+{
+ for(unsigned int i = pos; i < list->size - 1; i++)
+ list->list[i] = list->list[i + 1];
+
+ list->size--;
+
+ void** new_list = reallocarray(list->list, list->size, sizeof(void*));
+ list->list = new_list;
+
+ return list;
+}
+
+void list_free(LIST* list) {
+ for (unsigned int x = 0; x < list->size; x++)
+ free(list->list[x]);
+
+ free(list->list);
+ free(list);
+}
diff --git a/list.h b/list.h
new file mode 100644
index 0000000000000000000000000000000000000000..e33bf017753ff3c93db620c320e024cd2b18ec8a
--- /dev/null
+++ b/list.h
@@ -0,0 +1,27 @@
+#pragma once
+#include <stdlib.h>
+
+#define LIST_SIZE_FACTOR 1.5
+struct list {
+ unsigned int size;
+ unsigned int allocated_size;
+ void** list;
+};
+
+typedef struct list LIST;
+
+/**
+* Add an item to a list
+* @list: array list structure.
+* @item: item to be added to the list.
+*/
+LIST* list_add(LIST* list, void* item);
+
+/**
+* Remove an item from a given list
+* @list: array list structure.
+* @pos: position of item to be removed.
+*/
+LIST* list_remove(LIST* list, unsigned int pos);
+
+void list_free(LIST* list);
diff --git a/main.c b/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..720871ca2071734484ce7c6feb3b9ae706e2c4a1
--- /dev/null
+++ b/main.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <sqlite3.h>
+
+#include "data.h"
+
+int main() {
+ Data *data = new_data(":memory:");
+
+ bootstrap(data);
+ for (int x = 0; x < 10000; x++)
+ insert(data, "LINE X");
+
+ LIST *list = select(data);
+
+ for (unsigned int x = 0; x < list->size; x++)
+ printf("This is a line: %s\n", ((Word*)list->list[x])->Line);
+
+ list_free(list);
+ return 0;
+}