diff --git a/src/main.rs b/src/main.rs
index 6707abe76906b4b80ab5ce08e4659969b970011d..8350df69c4c6068f85da65e164b93b9ec4b9c3f8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -212,6 +212,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
                     .service(pages::rejudge_submission::rejudge_submission)
                     .service(pages::create_submission::create_submission)
                     .service(pages::create_contest::create_contest)
+                    .service(pages::get_problems::get_problems)
+                    .service(pages::get_about::get_about)
                     .service(pages::create_user::create_user)
                     .service(pages::impersonate_user::impersonate_user)
                     .service(pages::submission_updates::submission_updates)
diff --git a/src/models/problem.rs b/src/models/problem.rs
index 9cc1b359205e0e62237828485b118db7456b63e9..0d9f63def7e80a6a6727135a21334dc926961b53 100644
--- a/src/models/problem.rs
+++ b/src/models/problem.rs
@@ -94,6 +94,69 @@ pub struct ProblemByContestWithScore {
     pub user_accepted_count: i32,
 }
 
+pub fn get_problems_user_with_score(
+    connection: &mut PgConnection,
+    user_id: i32,
+) -> QueryResult<Vec<ProblemByContestWithScore>> {
+    diesel::sql_query(
+        r#"
+        with first_ac as (
+            select
+                min(submission_instant) as first_ac_submission_instant,
+                contest_problem_id,
+                submission.user_id
+            from submission
+            where submission.verdict = 'AC'
+            group by submission.user_id, submission.contest_problem_id
+        ), failed_submissions as (
+            select
+                submission.user_id,
+                submission.contest_problem_id,
+                cast(count(*) as int) as count
+            from submission
+            left join first_ac on first_ac.contest_problem_id = submission.contest_problem_id
+                and submission.user_id = first_ac.user_id
+            where (
+                first_ac_submission_instant is null or
+                submission.submission_instant < first_ac.first_ac_submission_instant
+            )
+            group by submission.user_id, submission.contest_problem_id
+        ), user_acs_count as (
+            select
+                cast(count(distinct submission.user_id) as int) as user_accepted_count,
+                submission.contest_problem_id
+            from submission
+            where submission.verdict = 'AC'
+            group by submission.contest_problem_id
+        )
+        select
+            "user".name as user_name,
+            first_ac_submission_instant,
+            coalesce(failed_submissions.count, 0) as failed_submissions,
+            contest_problems.id,
+            problem.name,
+            contest_problems.label,
+            problem.memory_limit_bytes,
+            problem.time_limit_ms,
+            coalesce(user_acs_count.user_accepted_count, 0) as user_accepted_count
+        from contest_problems
+        inner join problem on problem.id = contest_problems.problem_id
+        inner join "user" on "user".id = $1
+        left join failed_submissions
+            on failed_submissions.contest_problem_id = contest_problems.id
+            and failed_submissions.user_id = "user".id
+        left join first_ac
+            on first_ac.contest_problem_id = contest_problems.id
+            and first_ac.user_id = "user".id
+        left join user_acs_count
+            on user_acs_count.contest_problem_id = contest_problems.id
+        order by contest_problems.label
+    "#,
+    )
+    .bind::<sql_types::Integer, _>(user_id)
+    .load(connection)
+}
+
 pub fn get_problems_user_by_contest_id_with_score(
     connection: &mut PgConnection,
     user_id: i32,
diff --git a/src/pages/get_about.rs b/src/pages/get_about.rs
new file mode 100644
index 0000000000000000000000000000000000000000..89cb48b70e0ca8801199ed187f8b50cd5f0b59fe
--- /dev/null
+++ b/src/pages/get_about.rs
@@ -0,0 +1,6 @@
+use crate::pages::prelude::*;
+
+#[get("/about")]
+async fn get_about(hb: Data<Handlebars<'_>>) -> PageResult {
+    render(&hb, "about", &())
+}
diff --git a/src/pages/get_problems.rs b/src/pages/get_problems.rs
new file mode 100644
index 0000000000000000000000000000000000000000..a930fb74d7f6bc211453e1edb85f41a353615a34
--- /dev/null
+++ b/src/pages/get_problems.rs
@@ -0,0 +1,48 @@
+use crate::pages::prelude::*;
+use crate::models::problem;
+use crate::pages::{
+ FormattedProblemByContestWithScore,
+};
+
+#[get("/problems/")]
+pub async fn get_problems(
+    base: BaseContext,
+    identity: Identity,
+    pool: Data<DbPool>,
+    hb: Data<Handlebars<'_>>,
+    tz: Data<Tz>,
+) -> PageResult {
+    let logged_user = require_identity(&identity)?;
+
+    #[derive(Serialize)]
+    struct Context {
+        base: BaseContext,
+        problems: Vec<FormattedProblemByContestWithScore>,
+    }
+
+    let mut connection = pool.get()?;
+    let problems = problem::get_problems_user_with_score(&mut connection, logged_user.id)?;
+
+    render(
+        &hb,
+        "problems",
+        &Context {
+            base,
+            problems: problems
+                .iter()
+                .map(|p|
+    FormattedProblemByContestWithScore {
+        first_ac_submission_time: "".into(),
+        first_ac_submission_minutes: None,
+        failed_submissions: p.failed_submissions,
+        id: p.id,
+        name: p.name.clone(),
+        label: p.label.clone(),
+        memory_limit_mib: p.memory_limit_bytes / 1_024 / 1_024,
+        time_limit: format!("{}", f64::from(p.time_limit_ms) / 1000.0).replacen(".", ",", 1),
+        user_accepted_count: p.user_accepted_count,
+    })
+                .collect(),
+        },
+    )
+}
diff --git a/src/pages/mod.rs b/src/pages/mod.rs
index 69702214fc9a72067aaca1926f69d9acdd9e9316..e4ca1bc6baeeafa5477e55deeea3bb91bacb8f5a 100644
--- a/src/pages/mod.rs
+++ b/src/pages/mod.rs
@@ -38,6 +38,8 @@ pub mod post_logout;
 pub mod prelude;
 pub mod rejudge_submission;
 pub mod submission_updates;
+pub mod get_problems;
+pub mod get_about;
 
 use prelude::*;
 
diff --git a/templates/about.hbs b/templates/about.hbs
new file mode 100644
index 0000000000000000000000000000000000000000..945ada4f911317a07878ff44f54f61e73c522e78
--- /dev/null
+++ b/templates/about.hbs
@@ -0,0 +1,10 @@
+{{ #> base title="Sobre" }}
+  <div id="contests">
+  O Juĝisto é o juiz de maratona da Universidade Federal do Paraná.
+  Seu objetivo é ser utilizado para lecionar a disciplina de Desafios de Programação.
+
+  <p>
+  O código é aberto e licenciado sob GPLv3 e pode ser encontrado
+  <a href="gitlab.c3sl.ufpr.br/maratona-ufpr/jughisto">no GitLab do C3SL</a>.
+  </div>
+{{ /base }}
diff --git a/templates/base.hbs b/templates/base.hbs
index 42fd43a1db872ad084f3f8c27c2bedc80b322d03..8124d86f65f5a5da9e4f8efe0fc93c831c865adc 100644
--- a/templates/base.hbs
+++ b/templates/base.hbs
@@ -18,7 +18,7 @@
       <a href="problems/">Problemas</a>
       <a href="submissions/">Submissões</a>
       <a href="setting/">Criações</a>
-      <a href="about/">Sobre</a>
+      <a href="about">Sobre</a>
     </nav>
     <div class="span"></div>
     <div class="logged">
diff --git a/templates/problems.hbs b/templates/problems.hbs
new file mode 100644
index 0000000000000000000000000000000000000000..a63a99ed7d6c956ebb153abb094922f2849916fd
--- /dev/null
+++ b/templates/problems.hbs
@@ -0,0 +1,51 @@
+{{ #> base title="Problemas" }}
+  <div id="contest">
+    <div id="breadcrumb">
+      <a href=".">Início</a>
+      /
+      <a href="problems/">Problemas</a>
+    </div>
+
+    <div id="problems">
+      {{ #each problems }}
+      <a href="problems/{{ this.id }}" class="problem">
+        <div class="problem-info">
+          <div class="name">
+            {{ this.label }} · {{ this.name }}
+          </div>
+          <div class="extra">
+            {{this.time_limit}}s · {{ this.memory_limit_mib }}MiB
+          </div>
+        </div>
+        <div class="span"></div>
+        {{#if this.user_accepted_count}}
+          <div class="score">
+            <i class="gg-user"></i>
+            <div class="time">x{{this.user_accepted_count}}</div>
+          </div>
+        {{/if}}
+        {{#if this.first_ac_submission_time}}
+          <div class="score accepted">
+            <div>
+              +{{#if this.failed_submissions}}{{this.failed_submissions}}{{/if}}
+            </div>
+            {{#if (ne this.first_ac_submission_time "*")}}
+              <div class="time">
+                {{this.first_ac_submission_time}}
+              </div>
+            {{/if}}
+          </div>
+        {{else}}
+          {{#if this.failed_submissions}}
+            <div class="score wrong-answer">
+              <div>–{{ this.failed_submissions }}</div>
+            </div>
+          {{else}}
+            <div class="score"></div>
+          {{/if}}
+        {{/if}}
+      </a>
+      {{ /each }}
+    </div>
+  </div>
+{{ /base }}