diff --git a/src/gameslot.rs b/src/gameslot.rs
index a4aada4..0f11deb 100644
--- a/src/gameslot.rs
+++ b/src/gameslot.rs
@@ -1,4 +1,5 @@
 use crate::attempt::Attempt;
+use crate::misc::generate_valid_letters;
 use crate::status::Status;
 use crate::words::get_word_of_the_day;
 use std::collections::{HashMap, HashSet, VecDeque};
@@ -30,6 +31,7 @@ pub struct Game {
     pub board: Board,
     pub status: GameStatus,
     pub last_insertion_status: InsertionStatus,
+    pub unproven_letters: HashSet<char>,
 }
 
 impl Game {
@@ -41,16 +43,13 @@ impl Game {
             board: Default::default(),
             status: GameStatus::Playing,
             last_insertion_status: InsertionStatus::Ok,
+            unproven_letters: generate_valid_letters(),
         }
     }
 
     pub fn add_attempt(&mut self, word: &String) -> InsertionStatus {
         let word = word.to_uppercase();
-        let valid_letters = {
-            let mut output: HashSet<char> = ('A'..='Z').collect();
-            output.insert('Ñ');
-            output
-        };
+        let valid_letters = generate_valid_letters();
 
         let win = word.eq(&self.answer);
         let has_valid_chars = word
@@ -66,6 +65,11 @@ impl Game {
         ) {
             (0..=5, 5, &GameStatus::Playing, true) => {
                 let new_attempt = Attempt::from_string(&word, &self.answer);
+                for attempt_letter in &new_attempt.chars {
+                    if attempt_letter.status == Status::NotFound {
+                        self.unproven_letters.remove(&attempt_letter.char);
+                    }
+                }
                 self.board[self.attempt_index] = Some(new_attempt);
                 self.attempt_index += 1;
 
diff --git a/src/main.rs b/src/main.rs
index 6814b7c..96ad716 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,15 @@
 mod attempt;
 mod gameslot;
+mod misc;
 mod status;
 mod words;
 
-use crate::attempt::Attempt;
+use std::collections::HashSet;
+
 use crate::gameslot::{Board, Game};
-use crate::words::get_word_of_the_day;
 use gameslot::{GameStatus, InsertionStatus, SlotManager};
+use misc::generate_valid_letters;
+use misc::sort_hashset;
 use tera::Tera;
 use tokio::sync::Mutex;
 use tokio::sync::OnceCell;
@@ -94,10 +97,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
             let board: Board;
             let error: Option<String>;
             let result_pattern: Option<String>;
+            let unproven_letters: HashSet<char>;
 
             match Uuid::parse_str(possible_uuid) {
                 Ok(uuid) => match get_game(uuid).await {
                     Ok(game) => {
+                        unproven_letters = game.unproven_letters;
                         board = game.board;
                         match game.status {
                             GameStatus::Playing => {
@@ -128,6 +133,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                     }
                     Err(_) => {
                         board = Default::default();
+                        unproven_letters = generate_valid_letters();
                         error = Some(
                             "La partida a la que intentas acceder ya no existe o nunca existió"
                                 .to_string(),
@@ -137,14 +143,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                 },
                 Err(_) => {
                     board = Default::default();
+                    unproven_letters = generate_valid_letters();
                     error = Some("Identificador incorrecto".to_string());
                     result_pattern = None;
                 }
             }
 
+            let unproven_letters_sorted = sort_hashset(unproven_letters);
+
             context.insert("board", &board);
             context.insert("error", &error);
             context.insert("result_pattern", &result_pattern);
+            context.insert("unproven_letters", &unproven_letters_sorted);
             windmark::response::Response::success(render("index", &context).await.unwrap())
         })
         .mount("/:uuid/:attempt", move |request| async move {
@@ -172,6 +182,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                 context.insert("board", &board);
                 context.insert("error", &error);
                 context.insert("result_pattern", &result_pattern);
+                context.insert("unproven_letters", &sort_hashset(generate_valid_letters()));
                 windmark::response::Response::success(render("index", &context).await.unwrap())
             }
         })
diff --git a/src/misc.rs b/src/misc.rs
new file mode 100644
index 0000000..29bb9a9
--- /dev/null
+++ b/src/misc.rs
@@ -0,0 +1,13 @@
+use std::collections::HashSet;
+
+pub fn generate_valid_letters() -> HashSet<char> {
+    let mut output: HashSet<char> = ('A'..='Z').collect();
+    output.insert('Ñ');
+    output
+}
+
+pub fn sort_hashset<T: Ord>(hashset: HashSet<T>) -> Vec<T> {
+    let mut output = hashset.into_iter().collect::<Vec<_>>();
+    output.sort();
+    output
+}
diff --git a/src/status.rs b/src/status.rs
index 72bf5dc..47f5d34 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -1,6 +1,6 @@
 use serde::{Serialize, Serializer};
 
-#[derive(Clone)]
+#[derive(Clone, PartialEq)]
 pub enum Status {
     NotFound,
     Found,
diff --git a/templates/index.gmi.tera b/templates/index.gmi.tera
index 747d34e..6bb2e42 100644
--- a/templates/index.gmi.tera
+++ b/templates/index.gmi.tera
@@ -23,6 +23,9 @@
 {% if result_pattern -%}
 {{ result_pattern }}
 
+{% else -%}
+{{unproven_letters | join(sep=", ")}}
+
 {% endif -%}
 
 ## Indicaciones: