diff --git a/assets/templates/admin.tmpl b/assets/templates/admin.tmpl
index 07cde22c038d05e646871e162dc6f3c2c23d07ee..ad90885589a3f690fed17daf43b0353135fb856c 100644
--- a/assets/templates/admin.tmpl
+++ b/assets/templates/admin.tmpl
@@ -23,17 +23,19 @@
                                             </li>
                                             <li>
                                                 <div class="my-match-info">
-                                                    {{/*
-                                                    TODO: send delete via hidden form
-                                                    */}}
-                                                    <a href="" target="_blank" class="live-btn">Delete</a>
+                                                    <form id="destroy-{{.ID}}" method="post" action="/admin/{{.ID}}">
+                                                        <input type="hidden" name="Delete" value="true">
+                                                        <a class="live-btn" type="submit" style="cursor: default"
+                                                           onclick="document.getElementById('destroy-{{.ID}}').submit()
+                                                                   ">Delete</a>
+                                                    </form>
                                                     <!-- Canlı yayın butonu -->
                                                     <h5>{{index .Attributes "title"}}</h5>
                                                     <span>{{.StartTimeFormatted}}</span>
                                                 </div>
                                             </li>
                                             <li>
-                                                <a href="/admin/{{.ID}}" target="_blank" class="watch-stream"><i
+                                                <a href="/admin/{{.ID}}" class="watch-stream"><i
                                                             class="fas fa-pencil-alt"></i> Düzenle</a>
                                             </li>
                                         </ul>
diff --git a/assets/templates/tournament-config.tmpl b/assets/templates/tournament-config.tmpl
index d7977c8750db2356aa096b68660b83e5ddaa08c4..e08207b355b56051111dc4fd2909dd4373ffb81a 100644
--- a/assets/templates/tournament-config.tmpl
+++ b/assets/templates/tournament-config.tmpl
@@ -16,41 +16,41 @@
                                 <div class="row">
                                     <div class="col-md-12">
                                         <label>
-                                            <input type="text" name="Title" value="{{.title}}"
+                                            <input type="text" name="Title" value="{{.tournament.Title}}"
                                                    placeholder="Turnuva Başlığı">
                                         </label>
                                     </div>
                                     <div class="col-md-6">
                                         <label>
                                             Turnuva Tarihi
-                                            <input type="date" name="StartTimeString" value="{{.start_time}}"
+                                            <input type="date" name="StartTimeString" value="{{.tournament.StartTimeString}}"
                                                    placeholder="Turnuva Tarihi">
                                         </label>
                                     </div>
                                     <div class="col-md-6">
                                         <label>
                                             Son Kayıt Tarihi
-                                            <input type="date" name="DeadlineString" value="{{.deadline}}"
+                                            <input type="date" name="DeadlineString" value="{{.tournament.DeadlineString}}"
                                                    placeholder="Son Kayıt Tarihi">
                                         </label>
                                     </div>
                                     <div class="col-md-6">
                                         <label for="size">Oyuncular</label><select id="size" name="TeamSize">
-                                            <option value="0"{{if eq .team_size 0}} selected="selected" {{end}}>1 v 1
+                                            <option value="0"{{if eq .tournament.TeamSizeString "0"}} selected="selected" {{end}}>1 v 1
                                             </option>
-                                            <option value="1"{{if eq .team_size 1}} selected="selected" {{end}}>2 v 2
+                                            <option value="1"{{if eq .tournament.TeamSizeString "1"}} selected="selected" {{end}}>2 v 2
                                             </option>
-                                            <option value="2"{{if eq .team_size 2}} selected="selected" {{end}}>3 v 3
+                                            <option value="2"{{if eq .tournament.TeamSizeString "2"}} selected="selected" {{end}}>3 v 3
                                             </option>
-                                            <option value="3"{{if eq .team_size 3}} selected="selected" {{end}}>4 v 4
+                                            <option value="3"{{if eq .tournament.TeamSizeString "3"}} selected="selected" {{end}}>4 v 4
                                             </option>
-                                            <option value="4"{{if eq .team_size 4}} selected="selected" {{end}}>5 v 5
+                                            <option value="4"{{if eq .tournament.TeamSizeString "4"}} selected="selected" {{end}}>5 v 5
                                             </option>
                                         </select>
                                     </div>
                                     <div class="col-md-6">
                                         <label>
-                                            <input type="text" name="Prize" placeholder="Turnuva Ödülü">
+                                            <input type="text" name="Prize" value="{{.tournament.Prize}}" placeholder="Turnuva Ödülü">
                                         </label>
                                     </div>
                                 </div>
diff --git a/database.go b/database.go
index 8697a944b3dcf9f5db8b5c2cc4351f2dcf560550..5a7b04b7d1ff298005deaa21180bd9b4424f52cf 100644
--- a/database.go
+++ b/database.go
@@ -31,3 +31,7 @@ func closeDatabase() {
 		log.Printf("error closing user database: %s", err)
 	}
 }
+
+func isNotFound(err error) bool {
+	return err == leveldb.ErrNotFound
+}
diff --git a/routes.go b/routes.go
index d08e2f1c71b5ecbfed0582b6fad989b5eb3c1968..ce97232965308032314ed8be79332b3d6b0965d0 100644
--- a/routes.go
+++ b/routes.go
@@ -1,13 +1,13 @@
 package main
 
 import (
+	"fmt"
 	"git.randomchars.net/levatax/tournament-website/oauth"
 	"github.com/gin-contrib/sessions"
 	"github.com/gin-gonic/gin"
 	"github.com/google/uuid"
 	"log"
 	"net/http"
-	"strconv"
 )
 
 func registerRoutes() {
@@ -62,7 +62,7 @@ func registerRoutes() {
 	router.POST("/enroll/:id", func(context *gin.Context) {
 		user := oauth.GetSelf(context)
 		if user == nil {
-			context.Redirect(http.StatusTemporaryRedirect, "/auth/login")
+			context.Redirect(http.StatusFound, "/auth/login")
 			return
 		}
 
@@ -120,42 +120,21 @@ func registerRoutes() {
 	router.POST("/admin/new", func(context *gin.Context) {
 		user := oauth.GetSelf(context)
 		if user == nil {
-			context.Redirect(http.StatusTemporaryRedirect, "/auth/login")
+			context.Redirect(http.StatusFound, "/auth/login")
 			return
 		}
 
 		if !administrators[user.ID] {
-			context.Redirect(http.StatusTemporaryRedirect, "/")
-			return
-		}
-
-		payload := tournamentPayload{}
-		if err := context.Bind(&payload); err != nil {
-			if config.System.Verbose {
-				log.Printf("error binding creation form: %s", err)
-			}
-			context.String(http.StatusBadRequest, "Bad Request")
+			context.Redirect(http.StatusFound, "/")
 			return
 		}
 
-		if !validatePayloadTournament(&payload) {
-			if config.System.Verbose {
-				log.Print("invalid data submitted to creation form")
-				log.Print(payload)
-			}
-			context.String(http.StatusBadRequest, "Bad Request")
+		t, _ := bindTournament(context)
+		if t == nil {
 			return
 		}
 
-		if err := makeTournament(&tournament{
-			StartTime: payload.StartTime(),
-			Deadline:  payload.Deadline(),
-			Attributes: map[string]string{
-				"title": payload.Title,
-				"prize": payload.Prize,
-				"size":  strconv.Itoa(payload.TeamSize),
-			},
-		}); err != nil {
+		if err := makeTournament(t); err != nil {
 			log.Printf("error making tournament: %s", err)
 			context.String(http.StatusInternalServerError, "Internal Server Error")
 		} else {
@@ -175,22 +154,69 @@ func registerRoutes() {
 			return
 		}
 
-		// TODO: render page
+		t := contextTournament(context)
+		if t == nil {
+			return
+		}
+
+		authText, authRef := getAuthButton(user)
+
+		sy, sm, sd := t.StartTime.Date()
+		dy, dm, dd := t.Deadline.Date()
+		context.HTML(http.StatusOK, "tournament-config.tmpl", gin.H{
+			"auth_text": authText,
+			"auth_ref":  authRef,
+			"tournament": tournamentPayload{
+				Title:           t.Attributes["title"],
+				StartTimeString: fmt.Sprintf("%d-%.2d-%.2d", sy, sm, sd),
+				DeadlineString:  fmt.Sprintf("%d-%.2d-%.2d", dy, dm, dd),
+				TeamSizeString:  t.Attributes["size"],
+				Prize:           t.Attributes["prize"],
+			},
+		})
 	})
 
 	router.POST("/admin/:id", func(context *gin.Context) {
 		user := oauth.GetSelf(context)
 		if user == nil {
-			context.Redirect(http.StatusTemporaryRedirect, "/auth/login")
+			context.Redirect(http.StatusFound, "/auth/login")
 			return
 		}
 
 		if !administrators[user.ID] {
-			context.Redirect(http.StatusTemporaryRedirect, "/")
+			context.Redirect(http.StatusFound, "/")
+			return
+		}
+
+		t := contextTournament(context)
+		if t == nil {
+			return
+		}
+
+		tn, del := bindTournament(context)
+		if tn == nil {
 			return
 		}
+		tn.ID = t.ID
 
-		// TODO: handle updates
+		if del {
+			if err := destroyTournament(t.ID); err != nil {
+				log.Printf("error destroying tournament %s: %s", t.ID.String(), err)
+				context.String(http.StatusInternalServerError, "Internal Server Error")
+				return
+			} else {
+				context.Redirect(http.StatusFound, "/admin")
+				return
+			}
+		}
+
+		if err := updateTournament(tn); err != nil {
+			log.Printf("error updating tournament %s: %s", t.ID.String(), err)
+			context.String(http.StatusInternalServerError, "Internal Server Error")
+			return
+		} else {
+			context.Redirect(http.StatusFound, "")
+		}
 	})
 
 	// OAuth
diff --git a/tournament.go b/tournament.go
index 9195db5280152a39d39d489e3fbfd63c2805f089..7b6c3d8f7537a9e0e2a91bdd346a01cca170c388 100644
--- a/tournament.go
+++ b/tournament.go
@@ -1,16 +1,17 @@
 package main
 
 import (
+	"github.com/gin-gonic/gin"
 	"github.com/google/uuid"
 	json "github.com/json-iterator/go"
+	"log"
+	"net/http"
 	"strconv"
 	"strings"
 	"sync"
 	"time"
 )
 
-// TODO: leveldb.ErrNotFound
-
 type tournament struct {
 	ID         uuid.UUID         `json:"id"`
 	StartTime  time.Time         `json:"start_time"`
@@ -29,6 +30,7 @@ type tournamentPayload struct {
 	DeadlineString  string
 	dl              *time.Time
 	TeamSize        int
+	TeamSizeString  string
 	Prize           string
 	Delete          bool
 }
@@ -223,6 +225,58 @@ func destroyTournament(id uuid.UUID) error {
 	return nil
 }
 
+func contextTournament(context *gin.Context) *tournament {
+	var t *tournament
+	if id, err := uuid.Parse(context.Param("id")); err != nil {
+		if config.System.Verbose {
+			log.Printf("error parsing UUID %s: %s", context.Param("id"), err)
+		}
+		context.Redirect(http.StatusTemporaryRedirect, "/admin")
+		return nil
+	} else {
+		if t, _, err = getTournament(id); err != nil {
+			if isNotFound(err) {
+				context.Redirect(http.StatusTemporaryRedirect, "/admin")
+				return nil
+			}
+			log.Printf("error getting tournament %s: %s", id.String(), err)
+			context.String(http.StatusInternalServerError, "Internal Server Error")
+			return nil
+		}
+	}
+	return t
+}
+
+func bindTournament(context *gin.Context) (*tournament, bool) {
+	payload := tournamentPayload{}
+	if err := context.Bind(&payload); err != nil {
+		if config.System.Verbose {
+			log.Printf("error binding creation form: %s", err)
+		}
+		context.String(http.StatusBadRequest, "Bad Request")
+		return nil, false
+	}
+
+	if !payload.Delete && !validatePayloadTournament(&payload) {
+		if config.System.Verbose {
+			log.Print("invalid data submitted to creation form")
+			log.Print(payload)
+		}
+		context.String(http.StatusBadRequest, "Bad Request")
+		return nil, false
+	}
+
+	return &tournament{
+		StartTime: payload.StartTime(),
+		Deadline:  payload.Deadline(),
+		Attributes: map[string]string{
+			"title": payload.Title,
+			"prize": payload.Prize,
+			"size":  strconv.Itoa(payload.TeamSize),
+		},
+	}, payload.Delete
+}
+
 func validatePayloadTournament(payload *tournamentPayload) bool {
 	return payload.TeamSize >= 0 &&
 		payload.TeamSize <= 4 &&