diff --git a/lib/todoist/todoist.rb b/lib/todoist/todoist.rb
new file mode 100644
index 0000000..71d46af
--- /dev/null
+++ b/lib/todoist/todoist.rb
@@ -0,0 +1,63 @@
+module Plugins
+ class Todoist < Base
+
+ def locals
+ { tasks: }
+ end
+
+ class << self
+ def redirect_url
+ query = {
+ response_type: 'code',
+ client_id: Rails.application.credentials.plugins[:todoist][:client_id],
+ scope: 'data:read',
+ redirect_uri: "#{Rails.application.credentials.base_url}/plugin_settings/todoist/redirect"
+ }.to_query
+ "https://todoist.com/oauth/authorize?#{query}"
+ end
+
+ def fetch_access_token(code)
+ body = {
+ grant_type: "authorization_code",
+ client_id: Rails.application.credentials.plugins[:todoist][:client_id],
+ client_secret: Rails.application.credentials.plugins[:todoist][:client_secret],
+ redirect_uri: "#{Rails.application.credentials.base_url}/plugin_settings/todoist/redirect",
+ code: code
+ }
+ response = HTTParty.post("https://todoist.com/oauth/access_token", body:)
+ response.parsed_response['access_token']
+ end
+
+ def projects(access_token)
+ response = HTTParty.get('https://api.todoist.com/rest/v2/projects', headers: headers(access_token))
+ response.map { |m| { m['name'] => m['id'] } }&.push({ 'Today' => 'today' })
+ end
+
+ def headers(access_token) = { "Authorization" => "Bearer #{access_token}" }
+ end
+
+ private
+
+ def task_url = "https://api.todoist.com/rest/v2/tasks"
+
+ def tasks
+ fetch(task_url, query:, headers: Plugins::Todoist.headers(access_token))
+ .sort_by { Date.parse(it.dig('due', 'date') || (Date.today + 100.days).to_s) }
+ .reject { today_view? ? (it.dig('due', 'date').blank? || Date.parse(it.dig('due', 'date')) > today) : false }
+ .map do |it|
+ {
+ content: it['content'],
+ due: it.dig('due', 'date').present? ? Date.parse(it.dig('due', 'date')).strftime("%d %b") : it.dig('due', 'string')
+ }
+ end
+ end
+
+ def query = today_view? ? {} : { project_id: settings['todoist_project_id'] }
+
+ def access_token = settings.dig('todoist', 'access_token')
+
+ def today_view? = settings['todoist_project_id'] == 'today'
+
+ def today = user.datetime_now.end_of_day
+ end
+end
diff --git a/lib/todoist/views/full.html.erb b/lib/todoist/views/full.html.erb
new file mode 100644
index 0000000..cefc59b
--- /dev/null
+++ b/lib/todoist/views/full.html.erb
@@ -0,0 +1,27 @@
+
+
+
+ <% todos.reverse.each_with_index do |doing_and_done, list_index| %>
+
+
<%= doing_and_done[:label].titleize %>
+ <% visible_items = doing_and_done[:items] %>
+ <% hidden_items_count = doing_and_done[:items].size - visible_items.size %>
+
+ <% visible_items.each_with_index do |item, idx| %>
+
+
+ <%= idx + 1 %>
+
+
+ <%= item %>
+
+
+ <% end %>
+
+
+ <% end %>
+
+
+
+ <%= render 'plugins/todo_list/shared/title_bar', instance_name: instance_name %>
+
diff --git a/lib/todoist/views/half_horizontal.html.erb b/lib/todoist/views/half_horizontal.html.erb
new file mode 100644
index 0000000..3893b55
--- /dev/null
+++ b/lib/todoist/views/half_horizontal.html.erb
@@ -0,0 +1,23 @@
+
+
+ <% todos.reverse.each_with_index do |doing_and_done, list_index| %>
+
+
<%= doing_and_done[:label].titleize %>
+
+ <% doing_and_done[:items].each_with_index do |item, idx| %>
+
+
+ <%= idx + 1 %>
+
+
+ <%= item %>
+
+
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= render 'plugins/todo_list/shared/title_bar', instance_name: instance_name %>
+
diff --git a/lib/todoist/views/half_vertical.html.erb b/lib/todoist/views/half_vertical.html.erb
new file mode 100644
index 0000000..14a154b
--- /dev/null
+++ b/lib/todoist/views/half_vertical.html.erb
@@ -0,0 +1,25 @@
+
+
+ <% todos.each_with_index do |doing_and_done, list_index| %>
+
+
<%= doing_and_done[:label].titleize %>
+ <% doing_and_done[:items].each_with_index do |item, idx| %>
+
+
+ <%= idx + 1 %>
+
+
+ <%= item %>
+
+
+ <% end %>
+ <% hidden_items_count = doing_and_done[:items].size - 3 %>
+
+ <% if list_index == 0 %>
+
+ <% end %>
+ <% end %>
+
+
+ <%= render 'plugins/todo_list/shared/title_bar', instance_name: instance_name %>
+
diff --git a/lib/todoist/views/quadrant.html.erb b/lib/todoist/views/quadrant.html.erb
new file mode 100644
index 0000000..f19eb2e
--- /dev/null
+++ b/lib/todoist/views/quadrant.html.erb
@@ -0,0 +1,19 @@
+
+
+
+ <% todos = todos.first %>
+ <% todos[:items].each_with_index do |item, idx| %>
+
+
+ <%= idx + 1 %>
+
+
+ <%= item %>
+
+
+ <% end %>
+
+
+
+ <%= render 'plugins/todo_list/shared/title_bar', instance_name: instance_name %>
+
diff --git a/lib/todoist/views/shared/_title_bar.html.erb b/lib/todoist/views/shared/_title_bar.html.erb
new file mode 100644
index 0000000..6d6ad9f
--- /dev/null
+++ b/lib/todoist/views/shared/_title_bar.html.erb
@@ -0,0 +1,6 @@
+
+

+
Todo List
+
<%= instance_name %>
+
+