diff --git a/lib/kmxgit/repository_manager.ex b/lib/kmxgit/repository_manager.ex
new file mode 100644
index 0000000..0adb30d
--- /dev/null
+++ b/lib/kmxgit/repository_manager.ex
@@ -0,0 +1,69 @@
+defmodule Kmxgit.RepositoryManager do
+
+  import Ecto.Query, warn: false
+
+  alias Kmxgit.OrganisationManager.Organisation
+  alias Kmxgit.Repo
+  alias Kmxgit.RepositoryManager.Repository
+  alias Kmxgit.SlugManager.Slug
+  alias Kmxgit.UserManager.User
+
+  def list_repositories do
+    Repo.all from org in Repository,
+      preload: [organisation: :slug],
+      preload: [user: :slug]
+  end
+
+  def change_repository(repository \\ %Repository{}) do
+    Repository.changeset(repository, %{})
+  end
+
+  def create_repository(owner), do: create_repository(owner, %{})
+
+  def create_repository(user = %User{}, attrs) do
+    %Repository{}
+    |> Repository.changeset(attrs)
+    |> Ecto.Changeset.put_assoc(:user, user)
+    |> Repo.insert()
+  end
+
+  def create_repository(org = %Organisation{}, attrs) do
+    %Repository{}
+    |> Repository.changeset(attrs)
+    |> Ecto.Changeset.put_assoc(:organisation, org)
+    |> Repo.insert()
+  end
+
+  def update_repository(repository, attrs \\ %{}) do
+    repository
+    |> Repository.changeset(attrs)
+    |> Repo.update()
+  end
+
+  def get_repository(id) do
+    Repo.one from repository in Repository,
+      where: [id: ^id],
+      preload: :slug,
+      preload: [users: :slug],
+      limit: 1
+  end
+
+  def get_repository_by_owner_and_slug(owner, slug) do
+    downcase_owner = String.downcase(owner)
+    downcase_slug = String.downcase(slug)
+    Repo.one from r in Repository,
+      join: o in Organisation,
+      on: o.id == r.organisation_id,
+      join: os in Slug,
+      on: os.organisation_id == o.id,
+      join: u in User,
+      on: u.id == r.user_id,
+      join: us in Slug,
+      on: us.user_id == u.id,
+      where: (fragment("lower(?)", os.slug) == ^downcase_owner or fragment("lower(?)", us.slug) == ^downcase_owner) and fragment("lower(?)", r.slug) == ^downcase_slug
+  end
+
+  def delete_repository(%Repository{} = repository) do
+    Repo.delete(repository)
+  end
+end
diff --git a/lib/kmxgit/repository_manager/repository.ex b/lib/kmxgit/repository_manager/repository.ex
new file mode 100644
index 0000000..7a182c6
--- /dev/null
+++ b/lib/kmxgit/repository_manager/repository.ex
@@ -0,0 +1,26 @@
+defmodule Kmxgit.RepositoryManager.Repository do
+
+  use Ecto.Schema
+  import Ecto.Changeset
+
+  alias Kmxgit.OrganisationManager.Organisation
+  alias Kmxgit.UserManager.User
+
+  schema "repositories" do
+    field :description, :string
+    belongs_to :organisation, Organisation
+    field :slug, :string, unique: true
+    belongs_to :user, User
+    timestamps()
+  end
+
+  def changeset(repository, attrs \\ %{}) do
+    repository
+    |> cast(attrs, [:description, :slug])
+    |> validate_required([:slug])
+    |> validate_format(:slug, ~r|^[A-Za-z][-_+.0-9A-Za-z]{1,64}(/[A-Za-z][-_+.0-9A-Za-z]{1,64})*$|)
+    |> unique_constraint(:_lower_slug)
+    |> Markdown.validate_markdown(:description)
+  end
+
+end
diff --git a/lib/kmxgit/slug_manager.ex b/lib/kmxgit/slug_manager.ex
index 3d8e83f..4366b87 100644
--- a/lib/kmxgit/slug_manager.ex
+++ b/lib/kmxgit/slug_manager.ex
@@ -24,9 +24,9 @@ defmodule Kmxgit.SlugManager do
 
   def get_slug(slug) do
     Repo.one from s in Slug,
-      where: [slug: ^slug],
+      where: fragment("lower(slug)") == ^String.downcase(slug),
       preload: [organisation: [:slug, [users: :slug]]],
-      preload: [user: [:slug, [organisations: :slug]]],
+      preload: [user: [[organisations: :slug], :repositories, :slug]],
       limit: 1
   end
 
diff --git a/lib/kmxgit/slug_manager/slug.ex b/lib/kmxgit/slug_manager/slug.ex
index 55559cb..32f42d9 100644
--- a/lib/kmxgit/slug_manager/slug.ex
+++ b/lib/kmxgit/slug_manager/slug.ex
@@ -12,43 +12,11 @@ defmodule Kmxgit.SlugManager.Slug do
     timestamps()
   end
 
-  def changeset(slug, attrs) do
+  def changeset(slug, attrs \\ %{}) do
     slug
     |> cast(attrs, [:slug])
     |> validate_required([:slug])
     |> validate_format(:slug, ~r/^[A-Za-z][-_+.0-9A-Za-z]{1,64}$/)
     |> unique_constraint(:_lower_slug)
   end
-
-  def user_changeset(slug, user, attrs \\ {}) do
-    slug
-    |> changeset(attrs)
-    |> Ecto.Changeset.put_assoc(:user, user)
-    |> validate_only_user()
-  end
-
-  defp validate_only_user(changeset) do
-    c = changeset |> validate_required(:user_id)
-    if get_field(changeset, :organisation_id) do
-      add_error(c, :organisation_id, "cannot be set")
-    else
-      c
-    end
-  end
-
-  def organisation_changeset(slug, org, attrs \\ {}) do
-    slug
-    |> changeset(attrs)
-    |> Ecto.Changeset.put_assoc(:organisation, org)
-    |> validate_only_organisation()
-  end
-
-  defp validate_only_organisation(changeset) do
-    c = changeset |> validate_required(:organisation_id)
-    if get_field(changeset, :user_id) do
-      add_error(c, :user_id, "cannot be set")
-    else
-      c
-    end
-  end
 end
diff --git a/lib/kmxgit/user_manager.ex b/lib/kmxgit/user_manager.ex
index 181e688..bed1665 100644
--- a/lib/kmxgit/user_manager.ex
+++ b/lib/kmxgit/user_manager.ex
@@ -19,6 +19,7 @@ defmodule Kmxgit.UserManager do
     user = Repo.one(from user in User,
       where: [id: ^id],
       preload: [organisations: :slug],
+      preload: :repositories,
       preload: :slug
     )
     user || raise Ecto.NoResultsError
@@ -28,6 +29,7 @@ defmodule Kmxgit.UserManager do
     Repo.one from user in User,
       where: [id: ^id],
       preload: [organisations: :slug],
+      preload: :repositories,
       preload: :slug
   end
 
@@ -35,34 +37,22 @@ defmodule Kmxgit.UserManager do
     Repo.one from u in User,
       join: s in Slug,
       on: s.id == u.slug_id,
-      where: s.slug == ^slug,
+      where: fragment("lower(?)", s.slug) == ^String.downcase(slug),
       limit: 1
   end
 
-  def create_user(slug, attrs \\ %{}) do
-    %User{slug: slug}
+  def create_user(attrs \\ %{}) do
+    %User{}
     |> User.changeset(attrs)
     |> Repo.insert()
   end
 
-  def admin_create_user(slug, attrs \\ %{}) do
-    %User{slug: slug}
+  def admin_create_user(attrs \\ %{}) do
+    %User{}
     |> User.admin_changeset(attrs)
     |> Repo.insert()
   end
 
-  @doc """
-  Updates a user.
-
-  ## Examples
-
-      iex> update_user(user, %{field: new_value})
-      {:ok, %User{}}
-
-      iex> update_user(user, %{field: bad_value})
-      {:error, %Ecto.Changeset{}}
-
-  """
   def update_user(%User{} = user, attrs) do
     user
     |> User.changeset(attrs)
@@ -75,38 +65,20 @@ defmodule Kmxgit.UserManager do
     |> Repo.update()
   end
 
-  @doc """
-  Deletes a user.
-
-  ## Examples
-
-      iex> delete_user(user)
-      {:ok, %User{}}
-
-      iex> delete_user(user)
-      {:error, %Ecto.Changeset{}}
-
-  """
   def delete_user(%User{} = user) do
     Repo.delete(user)
   end
 
-  @doc """
-  Returns an `%Ecto.Changeset{}` for tracking user changes.
-
-  ## Examples
-
-      iex> change_user(user)
-      %Ecto.Changeset{source: %User{}}
-
-  """
   def change_user(%User{} = user) do
     User.changeset(user, %{})
   end
 
   def authenticate_user(login, password) do
     query = from u in User,
-      where: fragment("lower(?)", u.login) == ^String.downcase(login) or fragment("lower(?)", u.email) == ^String.downcase(login)
+      join: s in Slug,
+      on: s.user_id == u.id,
+      where: fragment("lower(?)", s.slug) == ^String.downcase(login) or fragment("lower(?)", u.email) == ^String.downcase(login),
+      limit: 1
     case Repo.one(query) do
       nil ->
         Bcrypt.no_user_verify()
diff --git a/lib/kmxgit/user_manager/user.ex b/lib/kmxgit/user_manager/user.ex
index a7aea10..a9e731e 100644
--- a/lib/kmxgit/user_manager/user.ex
+++ b/lib/kmxgit/user_manager/user.ex
@@ -3,8 +3,8 @@ defmodule Kmxgit.UserManager.User do
   import Ecto.Changeset
 
   alias Kmxgit.OrganisationManager.Organisation
+  alias Kmxgit.RepositoryManager.Repository
   alias Kmxgit.SlugManager.Slug
-  alias KmxgitWeb.Router.Helpers, as: Routes
   alias BCrypt
 
   schema "users" do
@@ -15,14 +15,15 @@ defmodule Kmxgit.UserManager.User do
     field :name, :string
     field :password, :string, virtual: true, redact: true
     field :password_confirmation, :string, virtual: true, redact: true
+    has_many :repositories, Repository
     has_one :slug, Slug, on_delete: :delete_all
     field :ssh_keys, :string
-    many_to_many :organisations, Organisation, join_through: "users_organisations"
+    many_to_many :organisations, Organisation, join_through: "users_organisations", on_delete: :delete_all
     timestamps()
   end
 
-  defp common_changeset(user) do
-    user
+  defp common_changeset(changeset) do
+    changeset
     |> check_password_confirmation()
     |> put_password_hash()
     |> cast_assoc(:slug)
@@ -32,14 +33,12 @@ defmodule Kmxgit.UserManager.User do
     |> Markdown.validate_markdown(:description)
   end
 
-  @doc false
   def changeset(user, attrs \\ %{}) do
     user
     |> cast(attrs, [:description, :email, :name, :password, :password_confirmation, :ssh_keys])
     |> common_changeset()
   end
 
-  @doc false
   def admin_changeset(user, attrs \\ %{}) do
     user
     |> cast(attrs, [:description, :email, :is_admin, :name, :password, :password_confirmation, :ssh_keys])
@@ -84,14 +83,6 @@ defmodule Kmxgit.UserManager.User do
     changeset
   end
 
-  def after_login_path(user) do
-    Routes.user_path(KmxgitWeb.Endpoint, :show, user.login)
-  end
-
-  def after_register_path(user) do
-    Routes.user_path(KmxgitWeb.Endpoint, :show, user.login)
-  end
-
   def display_name(user) do
     user.name || user.login
   end
diff --git a/lib/kmxgit_web/controllers/admin/organisation_controller.ex b/lib/kmxgit_web/controllers/admin/organisation_controller.ex
index 35cbff6..f1b1424 100644
--- a/lib/kmxgit_web/controllers/admin/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/admin/organisation_controller.ex
@@ -27,9 +27,9 @@ defmodule KmxgitWeb.Admin.OrganisationController do
       case SlugManager.create_slug(org_params["slug"]["slug"]) do
         {:ok, slug} ->
           case OrganisationManager.create_organisation(Map.merge(org_params, %{slug: slug, user: current_user})) do
-            {:ok, organisation} ->
+            {:ok, org} ->
               conn
-              |> redirect(to: Routes.organisation_path(conn, :show, organisation.slug))
+              |> redirect(to: Routes.admin_organisation_path(conn, :show, org))
             {:error, changeset} ->
               conn
               |> assign(:action, Routes.admin_organisation_path(conn, :create))
diff --git a/lib/kmxgit_web/controllers/organisation_controller.ex b/lib/kmxgit_web/controllers/organisation_controller.ex
index 773412b..e7ab9c6 100644
--- a/lib/kmxgit_web/controllers/organisation_controller.ex
+++ b/lib/kmxgit_web/controllers/organisation_controller.ex
@@ -17,7 +17,7 @@ defmodule KmxgitWeb.OrganisationController do
     case OrganisationManager.create_organisation(current_user, params["organisation"]) do
       {:ok, organisation} ->
         conn
-        |> redirect(to: Routes.organisation_path(conn, :show, organisation.slug.slug))
+        |> redirect(to: Routes.slug_path(conn, :show, organisation.slug.slug))
       {:error, changeset} ->
         IO.inspect(changeset)
         conn
@@ -66,7 +66,7 @@ defmodule KmxgitWeb.OrganisationController do
       case OrganisationManager.update_organisation(organisation, params["organisation"]) do
         {:ok, org} ->
           conn
-          |> redirect(to: Routes.organisation_path(conn, :show, org.slug.slug))
+          |> redirect(to: Routes.slug_path(conn, :show, org.slug.slug))
         {:error, changeset} ->
           IO.inspect(changeset)
           conn
diff --git a/lib/kmxgit_web/controllers/page_controller.ex b/lib/kmxgit_web/controllers/page_controller.ex
index c2ddb3f..964a934 100644
--- a/lib/kmxgit_web/controllers/page_controller.ex
+++ b/lib/kmxgit_web/controllers/page_controller.ex
@@ -30,23 +30,12 @@ defmodule KmxgitWeb.PageController do
   def new_admin_post(conn, params) do
     if ! UserManager.admin_user_present? do
       user_params = Map.merge(params["user"], %{"is_admin" => true})
-      login = user_params["login"]
       Repo.transaction fn ->
-        case SlugManager.create_slug(login) do
-          {:ok, slug} ->
-            case UserManager.admin_create_user(slug, user_params) do
-              {:ok, user} ->
-                conn
-                |> Guardian.Plug.sign_in(user)
-                |> redirect(to: "/")
-              {:error, changeset} ->
-                IO.inspect(changeset)
-                conn
-                |> assign(:no_navbar_links, true)
-                |> assign(:changeset, changeset)
-                |> assign(:action, Routes.page_path(conn, :new_admin))
-                |> render("new_admin.html")
-            end
+        case UserManager.admin_create_user(user_params) do
+          {:ok, user} ->
+            conn
+            |> Guardian.Plug.sign_in(user)
+            |> redirect(to: "/")
           {:error, changeset} ->
             IO.inspect(changeset)
             conn
diff --git a/lib/kmxgit_web/controllers/registration_controller.ex b/lib/kmxgit_web/controllers/registration_controller.ex
index 54178cb..82e3959 100644
--- a/lib/kmxgit_web/controllers/registration_controller.ex
+++ b/lib/kmxgit_web/controllers/registration_controller.ex
@@ -5,8 +5,10 @@ defmodule KmxgitWeb.RegistrationController do
 
   def new(conn, _) do
     changeset = UserManager.change_user(%User{})
-    render(conn, "new.html", changeset: changeset,
-      action: Routes.registration_path(conn, :register))
+    conn
+    |> assign(:action, Routes.registration_path(conn, :register))
+    |> assign(:changeset, changeset)
+    |> render("new.html")
   end
 
   def register(conn, params) do
@@ -14,11 +16,13 @@ defmodule KmxgitWeb.RegistrationController do
       {:ok, user} ->
         conn
         |> Guardian.Plug.sign_in(user)
-        |> redirect(to: User.after_register_path(user))
+        |> redirect(to: Routes.slug_path(conn, :show, user.slug.slug))
       {:error, changeset} ->
         conn
-        |> render("new.html", changeset: changeset,
-                  action: Routes.registration_path(conn, :register))
+        |> assign(:action, Routes.registration_path(conn, :register))
+        |> assign(:changeset, changeset)
+        |> render("new.html")
+                  
     end
   end
 end
diff --git a/lib/kmxgit_web/controllers/repository_controller.ex b/lib/kmxgit_web/controllers/repository_controller.ex
new file mode 100644
index 0000000..161cc2c
--- /dev/null
+++ b/lib/kmxgit_web/controllers/repository_controller.ex
@@ -0,0 +1,93 @@
+defmodule KmxgitWeb.RepositoryController do
+  use KmxgitWeb, :controller
+
+  alias Kmxgit.RepositoryManager
+
+  def new(conn, params) do
+    current_user = conn.assigns.current_user
+    # TODO: check the owner part of path
+    changeset = RepositoryManager.change_repository
+    conn
+    |> assign(:action, Routes.repository_path(conn, :create, params["owner"]))
+    |> assign(:changeset, changeset)
+    |> render("new.html")
+  end
+
+  def create(conn, params) do
+    current_user = conn.assigns.current_user
+    # TODO: handle organisations
+    owner = current_user
+    # TODO: check the owner part of path
+    case RepositoryManager.create_repository(current_user, params["repository"]) do
+      {:ok, repository} ->
+        conn
+        |> redirect(to: Routes.repository_path(conn, :show, owner.slug.slug, repository.slug))
+      {:error, changeset} ->
+        IO.inspect(changeset)
+        conn
+        |> assign(:action, Routes.repository_path(conn, :create, owner.slug))
+        |> assign(:changeset, changeset)
+        |> render("new.html")
+    end
+  end
+
+  defp not_found(conn) do
+    conn
+    |> put_status(:not_found)
+    |> put_view(ErrorView)
+    |> render(:"404")
+  end
+
+  def show(conn, params) do
+    slug = Enum.join(params["slug"], "/")
+    repo =  RepositoryManager.get_repository_by_owner_and_slug(params["owner"], slug)
+    if repo do
+      org = repo.organisation
+      user = repo.user
+      conn
+      |> assign(:current_repository, repo)
+      |> assign_current_organisation(org)
+      |> assign(:owner, org || user)
+      |> render("show.html")
+    else
+      not_found(conn)
+    end
+  end
+
+  defp assign_current_organisation(conn, nil), do: conn
+  defp assign_current_organisation(conn, org) do
+    assign(conn, :current_organisation, org)
+  end
+  
+  def edit(conn, params) do
+    org =  RepositoryManager.get_repository_by_slug(params["slug"])
+    changeset = RepositoryManager.change_repository(org)
+    if org do
+      conn
+      |> assign(:action, Routes.repository_path(conn, :update, org.slug.slug))
+      |> assign(:changeset, changeset)
+      |> assign(:current_repository, org)
+      |> render("edit.html")
+    else
+      not_found(conn)
+    end
+  end
+
+  def update(conn, params) do
+    repository = RepositoryManager.get_repository_by_slug(params["slug"])
+    if repository do
+      case RepositoryManager.update_repository(repository, params["repository"]) do
+        {:ok, org} ->
+          conn
+          |> redirect(to: Routes.slug_path(conn, :show, org.slug.slug))
+        {:error, changeset} ->
+          IO.inspect(changeset)
+          conn
+          |> render("edit.html", changeset: changeset,
+                    action: Routes.repository_path(conn, :update, repository.slug.slug))
+      end
+    else
+      not_found(conn)
+    end
+  end
+end
diff --git a/lib/kmxgit_web/controllers/session_controller.ex b/lib/kmxgit_web/controllers/session_controller.ex
index f5178ed..4651c06 100644
--- a/lib/kmxgit_web/controllers/session_controller.ex
+++ b/lib/kmxgit_web/controllers/session_controller.ex
@@ -7,7 +7,7 @@ defmodule KmxgitWeb.SessionController do
     changeset = UserManager.change_user(%User{})
     user = UserManager.Guardian.Plug.current_resource(conn)
     if user do
-      redirect(conn, to: params["redirect"] || User.after_login_path(user))
+      redirect(conn, to: params["redirect"] || Routes.user_path(KmxgitWeb.Endpoint, :show, user.slug.slug))
     else
       redirect = params["redirect"]
       action = if redirect do
@@ -39,7 +39,7 @@ defmodule KmxgitWeb.SessionController do
   defp login_reply(conn, {:ok, user}, redirect) do
     conn
     |> UserManager.Guardian.Plug.sign_in(user)
-    |> redirect(to: redirect || User.after_login_path(user))
+    |> redirect(to: redirect || Routes.user_path(KmxgitWeb.Endpoint, :show, user.slug.slug))
   end
 
   defp login_reply(conn, {:error, reason}, _redirect) do
diff --git a/lib/kmxgit_web/controllers/user_controller.ex b/lib/kmxgit_web/controllers/user_controller.ex
index 63a8f6d..93461e3 100644
--- a/lib/kmxgit_web/controllers/user_controller.ex
+++ b/lib/kmxgit_web/controllers/user_controller.ex
@@ -48,7 +48,7 @@ defmodule KmxgitWeb.UserController do
       case UserManager.update_user(current_user, params["user"]) do
         {:ok, user} ->
           conn
-          |> redirect(to: Routes.user_path(conn, :show, user.slug.slug))
+          |> redirect(to: Routes.slug_path(conn, :show, user.slug.slug))
         {:error, changeset} ->
           conn
           |> assign(:page_title, gettext("Edit user %{login}", login: current_user.slug.slug))
diff --git a/lib/kmxgit_web/router.ex b/lib/kmxgit_web/router.ex
index 1ca56a4..1180775 100644
--- a/lib/kmxgit_web/router.ex
+++ b/lib/kmxgit_web/router.ex
@@ -44,25 +44,27 @@ defmodule KmxgitWeb.Router do
     end
 
     get  "/_register", RegistrationController, :new
-    post "/",          RegistrationController, :register
+    post "/_register", RegistrationController, :register
   end
 
   # definitely logged in, will redirect to login page
   scope "/", KmxgitWeb do
     pipe_through [:browser, :auth, :ensure_auth]
 
-    scope "/_o" do
-      get  "/_new",        OrganisationController, :new
-      post "/",            OrganisationController, :create
-      get  "/:slug",       OrganisationController, :show
-      get  "/:slug/_edit", OrganisationController, :edit
-      put  "/:slug",       OrganisationController, :update
+    scope "/_new" do
+      get  "/organisation", OrganisationController, :new
+      post "/organisation", OrganisationController, :create
+      get  "/:owner", RepositoryController, :new
+      post "/:owner", RepositoryController, :create
     end
 
-    scope "/_u" do
-      get "/:login",       UserController, :show
-      get "/:login/_edit", UserController, :edit
-      put "/:login",       UserController, :update
+    scope "/_edit/" do
+      get "/organisation/:slug", OrganisationController, :edit
+      put "/organisation/:slug", OrganisationController, :update
+      get "/user/:login", UserController, :edit
+      put "/user/:login", UserController, :update
+      get "/:owner/*slug", RepositoryController, :edit
+      put "/:owner/*slug", RepositoryController, :update
     end
 
     scope "/admin", Admin, as: "admin" do
@@ -81,6 +83,7 @@ defmodule KmxgitWeb.Router do
     pipe_through [:browser, :auth]
 
     get "/:slug", SlugController, :show
+    get "/:owner/*slug", RepositoryController, :show
   end
 
   # Other scopes may use custom stacks.
diff --git a/lib/kmxgit_web/templates/admin/organisation/index.html.heex b/lib/kmxgit_web/templates/admin/organisation/index.html.heex
index e9adaeb..800e554 100644
--- a/lib/kmxgit_web/templates/admin/organisation/index.html.heex
+++ b/lib/kmxgit_web/templates/admin/organisation/index.html.heex
@@ -11,7 +11,7 @@
       <tr>
         <td><%= link org.id, to: Routes.admin_organisation_path(@conn, :show, org) %></td>
         <td><%= org.name %></td>
-        <td><%= link org.slug.slug, to: Routes.organisation_path(@conn, :show, org.slug.slug) %></td>
+        <td><%= link org.slug.slug, to: Routes.slug_path(@conn, :show, org.slug.slug) %></td>
       </tr>
     <% end %>
   </table>
diff --git a/lib/kmxgit_web/templates/admin/organisation/show.html.heex b/lib/kmxgit_web/templates/admin/organisation/show.html.heex
index 5bf3e00..6efd2eb 100644
--- a/lib/kmxgit_web/templates/admin/organisation/show.html.heex
+++ b/lib/kmxgit_web/templates/admin/organisation/show.html.heex
@@ -8,11 +8,11 @@
     </tr>
     <tr>
       <th><%= gettext "Name" %></th>
-      <td><%= link @org.name, to: Routes.organisation_path(@conn, :show, @org.slug.slug) %></td>
+      <td><%= link @org.name, to: Routes.slug_path(@conn, :show, @org.slug.slug) %></td>
     </tr>
     <tr>
       <th><%= gettext "Slug" %></th>
-      <td><%= link @org.slug.slug, to: Routes.organisation_path(@conn, :show, @org.slug.slug) %></td>
+      <td><%= link @org.slug.slug, to: Routes.slug_path(@conn, :show, @org.slug.slug) %></td>
     </tr>
     <tr>
       <th><%= gettext "Description" %></th>
diff --git a/lib/kmxgit_web/templates/admin/user/index.html.heex b/lib/kmxgit_web/templates/admin/user/index.html.heex
index a05c437..150ee82 100644
--- a/lib/kmxgit_web/templates/admin/user/index.html.heex
+++ b/lib/kmxgit_web/templates/admin/user/index.html.heex
@@ -13,7 +13,7 @@
       <td><%= link user.id, to: Routes.admin_user_path(@conn, :show, user) %></td>
       <td><%= user.name %></td>
       <td><%= link user.email, to: "mailto:#{user.email}" %></td>
-      <td><%= link user.slug.slug, to: Routes.user_path(@conn, :show, user.slug.slug) %></td>
+      <td><%= link user.slug.slug, to: Routes.slug_path(@conn, :show, user.slug.slug) %></td>
       <td><%= user.is_admin %></td>
     </tr>
   <% end %>
diff --git a/lib/kmxgit_web/templates/admin/user/show.html.heex b/lib/kmxgit_web/templates/admin/user/show.html.heex
index 1c2d231..2003993 100644
--- a/lib/kmxgit_web/templates/admin/user/show.html.heex
+++ b/lib/kmxgit_web/templates/admin/user/show.html.heex
@@ -15,7 +15,7 @@
   </tr>
   <tr>
     <th><%= gettext "Login" %></th>
-    <td><%= link @user.slug.slug, to: Routes.user_path(@conn, :show, @user.slug.slug) %></td>
+    <td><%= link @user.slug.slug, to: Routes.slug_path(@conn, :show, @user.slug.slug) %></td>
   </tr>
   <tr>
     <th><%= gettext "Description" %></th>
diff --git a/lib/kmxgit_web/templates/layout/nav_connected.html.heex b/lib/kmxgit_web/templates/layout/nav_connected.html.heex
index 78ad2ef..277741d 100644
--- a/lib/kmxgit_web/templates/layout/nav_connected.html.heex
+++ b/lib/kmxgit_web/templates/layout/nav_connected.html.heex
@@ -1,12 +1,12 @@
 <%= if @conn.assigns[:current_organisation] do %>
   <li class="nav-item">
     <%= link @current_organisation.name || @current_organisation.slug.slug,
-             to: Routes.organisation_path(@conn, :show, @current_organisation.slug),
+             to: Routes.slug_path(@conn, :show, @current_organisation.slug.slug),
              class: "nav-link" %>
   </li>
 <% end %>
 <li class="nav-item">
-  <%= link @current_user.slug.slug, to: Routes.user_path(@conn, :show, @current_user.slug.slug), class: "nav-link" %>
+  <%= link @current_user.slug.slug, to: Routes.slug_path(@conn, :show, @current_user.slug.slug), class: "nav-link" %>
 </li>
 <%= if @current_user.is_admin do %>
   <li class="nav-item">
diff --git a/lib/kmxgit_web/templates/organisation/show.html.heex b/lib/kmxgit_web/templates/organisation/show.html.heex
index d6ba952..04c9cf2 100644
--- a/lib/kmxgit_web/templates/organisation/show.html.heex
+++ b/lib/kmxgit_web/templates/organisation/show.html.heex
@@ -40,7 +40,7 @@
           <th><%= gettext "Users" %></th>
           <td>
             <%= for user <- @org.users do %>
-              <%= link(user.slug.slug, to: Routes.user_path(@conn, :show, user.slug.slug), class: "user") %>
+              <%= link(user.slug.slug, to: Routes.slug_path(@conn, :show, user.slug.slug), class: "user") %>
             <% end %>
           </td>
         </tr>
diff --git a/lib/kmxgit_web/templates/page/new_admin.html.heex b/lib/kmxgit_web/templates/page/new_admin.html.heex
index 50144ba..9901753 100644
--- a/lib/kmxgit_web/templates/page/new_admin.html.heex
+++ b/lib/kmxgit_web/templates/page/new_admin.html.heex
@@ -23,11 +23,13 @@
       <%= error_tag f, :email %>
     </div>
 
-    <div class="mb-3">
-      <%= label f, :login, class: "form-label" %>
-      <%= text_input f, :login, class: "form-control" %>
-      <%= error_tag f, :login %>
-    </div>
+    <%= inputs_for f, :slug, fn ff -> %>
+      <div class="mb-3">
+        <%= label ff, :slug, class: "form-label" %>
+        <%= text_input ff, :slug, class: "form-control" %>
+        <%= error_tag ff, :slug %>
+      </div>
+    <% end %>
 
     <div class="mb-3">
       <%= label f, :password, class: "form-label" %>
diff --git a/lib/kmxgit_web/templates/registration/new.html.heex b/lib/kmxgit_web/templates/registration/new.html.heex
index df1a754..a79ad95 100644
--- a/lib/kmxgit_web/templates/registration/new.html.heex
+++ b/lib/kmxgit_web/templates/registration/new.html.heex
@@ -1,7 +1,7 @@
 <div class="container-fluid">
   <h1><%= gettext "Register" %></h1>
 
-  <%= form_for @changeset, @action, fn f -> %>
+  <%= form_for @changeset, @action, [as: "user"], fn f -> %>
 
     <div class="mb-3">
       <%= label f, :name, class: "form-label" %>
@@ -15,11 +15,13 @@
       <%= error_tag f, :email %>
     </div>
 
-    <div class="mb-3">
-      <%= label f, :login, class: "form-label" %>
-      <%= text_input f, :login, class: "form-control" %>
-      <%= error_tag f, :login %>
-    </div>
+    <%= inputs_for f, :slug, fn ff -> %>
+      <div class="mb-3">
+        <%= label ff, :slug, gettext("Login"), class: "form-label" %>
+        <%= text_input ff, :slug, class: "form-control" %>
+        <%= error_tag ff, :slug %>
+      </div>
+    <% end %>
 
     <div class="mb-3">
       <%= label f, :password, class: "form-label" %>
diff --git a/lib/kmxgit_web/templates/repository/form.html.heex b/lib/kmxgit_web/templates/repository/form.html.heex
new file mode 100644
index 0000000..fe584fa
--- /dev/null
+++ b/lib/kmxgit_web/templates/repository/form.html.heex
@@ -0,0 +1,19 @@
+<%= form_for @changeset, @action, fn f -> %>
+
+  <div class="mb-3">
+    <%= label f, :slug, class: "form-label" %>
+    <%= text_input f, :slug, class: "form-control" %>
+    <%= error_tag f, :slug %>
+  </div>
+
+  <div class="mb-3">
+    <%= label f, :description, class: "form-label" %>
+    <%= textarea f, :description, class: "form-control" %>
+    <%= error_tag f, :description %>
+  </div>
+
+  <div class="mb-3">
+    <%= submit gettext("Submit"), class: "btn btn-primary" %>
+  </div>
+
+<% end %>
diff --git a/lib/kmxgit_web/templates/repository/new.html.heex b/lib/kmxgit_web/templates/repository/new.html.heex
new file mode 100644
index 0000000..e806943
--- /dev/null
+++ b/lib/kmxgit_web/templates/repository/new.html.heex
@@ -0,0 +1,4 @@
+<div class="container-fluid">
+  <h1>New repository</h1>
+  <%= render "form.html", assigns %>
+</div>
diff --git a/lib/kmxgit_web/templates/user/edit.html.heex b/lib/kmxgit_web/templates/user/edit.html.heex
index c0e1c5d..1d82b1b 100644
--- a/lib/kmxgit_web/templates/user/edit.html.heex
+++ b/lib/kmxgit_web/templates/user/edit.html.heex
@@ -41,7 +41,7 @@
 
     <div class="mb-3">
       <%= link gettext("Cancel"),
-               to: Routes.user_path(@conn, :show, @current_user.slug.slug),
+               to: Routes.slug_path(@conn, :show, @current_user.slug.slug),
                class: "btn btn-secondary" %>
        
       <%= submit gettext("Submit"), class: "btn btn-primary" %>
diff --git a/lib/kmxgit_web/templates/user/show.html.heex b/lib/kmxgit_web/templates/user/show.html.heex
index 387eab7..dfbcd3a 100644
--- a/lib/kmxgit_web/templates/user/show.html.heex
+++ b/lib/kmxgit_web/templates/user/show.html.heex
@@ -4,6 +4,9 @@
       <h1><%= @user.slug.slug %></h1>
     </div>
     <div class="col col-12 col-sm-4">
+      <%= link gettext("New repository"),
+               to: Routes.repository_path(@conn, :new, @user.slug.slug),
+               class: "btn btn-primary" %>
       <%= link gettext("Edit"),
                to: Routes.user_path(@conn, :edit, @user.slug.slug),
                class: "btn btn-primary" %>
@@ -14,6 +17,9 @@
     <div class="col col-12 col-md-7">
       <hr/>
       <h2><%= gettext "Repositories" %></h2>
+      <%= for repo <- @user.repositories do %>
+        <%= link repo.slug, to: Routes.repository_path(@conn, :show, @user.slug.slug, String.split(repo.slug, "/")) %>
+      <% end %>
     </div>
     <div class="col col-12 col-md-4">
       <hr/>
@@ -45,7 +51,7 @@
           </th>
           <td>
             <%= for org <- @user.organisations do %>
-              <%= link(org.name || org.slug.slug, to: Routes.organisation_path(@conn, :show, org.slug.slug), class: "org") %>
+              <%= link(org.name || org.slug.slug, to: Routes.slug_path(@conn, :show, org.slug.slug), class: "org") %>
             <% end %>
             <%= if @user == @current_user do %>
               <%= link("+", to: Routes.organisation_path(@conn, :new), class: "btn btn-primary") %>
diff --git a/lib/kmxgit_web/views/repository_view.ex b/lib/kmxgit_web/views/repository_view.ex
new file mode 100644
index 0000000..08f0b6a
--- /dev/null
+++ b/lib/kmxgit_web/views/repository_view.ex
@@ -0,0 +1,3 @@
+defmodule KmxgitWeb.RepositoryView do
+  use KmxgitWeb, :view
+end
diff --git a/priv/repo/migrations/20211118161213_create_repositories.exs b/priv/repo/migrations/20211118161213_create_repositories.exs
new file mode 100644
index 0000000..1243c05
--- /dev/null
+++ b/priv/repo/migrations/20211118161213_create_repositories.exs
@@ -0,0 +1,14 @@
+defmodule Kmxgit.Repo.Migrations.CreateRepositories do
+  use Ecto.Migration
+
+  def change do
+    create table(:repositories) do
+      add :slug, :string, unique: true
+      add :description, :string
+      add :organisation_id, references(:organisations), null: true
+      add :user_id, references(:users), null: true
+      timestamps()
+    end
+    create index(:repositories, ["(lower(slug))"], unique: true)
+  end
+end