diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css
index 094625f7998bd737fd69e7012a5790d20f40fe88..d8baf27587ff675b6e331695b0cd834886a0eaa8 100644
--- a/app/assets/stylesheets/application.tailwind.css
+++ b/app/assets/stylesheets/application.tailwind.css
@@ -41,3 +41,14 @@ select {
     @apply bg-green-100 border-green-300;
   }
 }
+#flash {
+  @apply mx-auto flex items-center flex-col gap-1 p-2;
+  .flash {
+    @apply bg-slate-50 border-slate-100 border inline-block p-2 rounded-md shadow;
+  }
+}
+.main-nav {
+  a {
+    @apply underline hover:text-blue-600 hover:border-b hover:border-blue-600;
+  }
+}
\ No newline at end of file
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 09705d12ab4dfe301535a973e2607fad4efc9d0d..001ed300f4d3e8bc96c0c2972b8fb37989379994 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,2 +1,9 @@
 class ApplicationController < ActionController::Base
+  helper_method :current_user
+
+  private
+
+  def current_user
+    @current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
+  end
 end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..05b666ecc39287386e045629634491c85892cff4
--- /dev/null
+++ b/app/controllers/users_controller.rb
@@ -0,0 +1,47 @@
+class UsersController < ApplicationController
+  before_action :require_login, except: [:login]
+
+  def login
+    @users = User.all
+    if params[:user_id]
+      user = User.find(params[:user_id])
+      session[:user_id] = user.id
+      redirect_to conferences_path, notice: "Logged in as #{user.name}"
+    end
+  end
+
+  def logout
+    session[:user_id] = nil
+    redirect_to login_path, notice: "Logged out"
+  end
+
+  def profile
+    @user = current_user
+  end
+
+  def update_profile
+    @user = current_user
+    if @user.update(user_params)
+      flash.now[:notice] = "Profile updated successfully!"
+      respond_to do |format|
+        format.html { redirect_to profile_path, notice: "Profile updated successfully!"  }
+        #format.turbo_stream { render turbo_stream: turbo_stream.replace("flash", partial: "shared/flash") }
+      end
+    else
+      render :edit
+    end
+  end
+
+  private
+
+  def user_params
+    params.require(:user).permit(:name, :email, :avatar_color, :telegram_username)
+  end
+
+  def require_login
+    unless current_user
+      flash[:alert] = "You must be logged in to edit your profile."
+      redirect_to login_path
+    end
+  end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index de6be7945c6a59798eb0ace177df38b05e98c2f0..6d16c9aeafa09c87a3e7af019880496cae491e27 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,2 +1,5 @@
 module ApplicationHelper
+  def logged_in?
+    !session[:user_id].nil?
+  end
 end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2310a240d78bd6361668625f782ada9d71cdd6c5
--- /dev/null
+++ b/app/helpers/users_helper.rb
@@ -0,0 +1,2 @@
+module UsersHelper
+end
diff --git a/app/javascript/application.js b/app/javascript/application.js
index e239947abfd19eb083fb16ac650b9a49b63ff6e4..84b06ebb56969db99d05c9c284ab917a6f2d6e19 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -1,3 +1,18 @@
 // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
 import "controllers"
 import "@hotwired/turbo-rails"
+
+document.addEventListener("turbo:load", function() {
+  console.log('turbo:load');
+  const flashMessages = document.querySelectorAll(".flash");
+
+  flashMessages.forEach(flashMessage => {
+    flashMessage.querySelector('.close').addEventListener('click', () => {
+      flashMessage.parentNode.removeChild(flashMessage);
+    });
+
+    setTimeout(() => {
+      flashMessage.parentNode.removeChild(flashMessage);
+    }, 5000);
+  });
+});
\ No newline at end of file
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index d8c668001681d5160e73b74dc47df15b8ee6bb3e..c817a0a5c77f1817cb6fa12964c1c59d2843affe 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -12,6 +12,24 @@
   </head>
 
   <body>
+    <nav class="main-nav bg-slate-100 border-b border-slate-200">
+      <div class="container mx-auto p-5 flex flex-row justify-between">
+        <div class="main-nav-left">
+          <%= link_to 'Conferences', conferences_path %>
+        </div>
+        <div class="main-nav-right">
+        <% if logged_in? %>
+          logged in as: <%= render partial: 'application/user_avatar', locals: { user: current_user } %>
+          <%= link_to 'Profile', profile_path %>
+          <%= link_to 'Assignments', user_assignments_path(current_user) %>
+          <%= link_to 'Logout', logout_path, data: { turbo_method: :post } %>
+        <% else %>
+          Not logged in
+        <% end %>
+        </div>
+      </div>
+    </nav>
+    <%= render partial: 'shared/flash' %>
     <main class="container mx-auto mt-8 px-5 flex">
       <%= yield %>
     </main>
diff --git a/app/views/shared/_flash.html.erb b/app/views/shared/_flash.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..143f14ff63cd1879f79f0a2a0477d6ea4c0873db
--- /dev/null
+++ b/app/views/shared/_flash.html.erb
@@ -0,0 +1,10 @@
+<div id="flash">
+  <% flash.each do |type, message| %>
+    <div class="flash alert alert-<%= type %>">
+      <%= message %>
+      <button type="button" class="close" data-dismiss="alert" aria-label="Close">
+        <span aria-hidden="true">&times;</span>
+      </button>
+    </div>
+  <% end %>
+</div>
\ No newline at end of file
diff --git a/app/views/users/login.html.erb b/app/views/users/login.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..7c99ca874b99aa6b93dd46f34928f750ed7d2554
--- /dev/null
+++ b/app/views/users/login.html.erb
@@ -0,0 +1,10 @@
+<div>
+  <h1 class="font-bold text-4xl mb-8">Choose User</h1>
+  <ul class="flex flex-wrap gap-2">
+  <% @users.each do |user| %>
+    <li>
+      <%= button_to user.name, login_path(user_id: user.id), data: { turbo_method: :post }, class: "p-2 border hover:bg-slate-100 hover:shadow" %>
+    </li>
+  <% end %>
+</ul>
+</div>
diff --git a/app/views/users/logout.html.erb b/app/views/users/logout.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..00a082014b19442f248051f08f72c7a08d767fd2
--- /dev/null
+++ b/app/views/users/logout.html.erb
@@ -0,0 +1,4 @@
+<div>
+  <h1 class="font-bold text-4xl">Users#logout</h1>
+  <p>Find me in app/views/users/logout.html.erb</p>
+</div>
diff --git a/app/views/users/profile.html.erb b/app/views/users/profile.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..f655398be3ee0a88389c8d72c01a8406884e782a
--- /dev/null
+++ b/app/views/users/profile.html.erb
@@ -0,0 +1,28 @@
+<div>
+  <h1 class="font-bold text-4xl">Profile</h1>
+  <%= form_with(model: @user, url: update_profile_path, local: true) do |form| %>
+    <div class="field">
+      <%= form.label :name %>
+      <%= form.text_field :name %>
+    </div>
+
+    <div class="field">
+      <%= form.label :email %>
+      <%= form.text_field :email %>
+    </div>
+
+    <div class="field">
+      <%= form.label :avatar_color %>
+      <%= form.color_field :avatar_color %>
+    </div>
+
+    <div class="field">
+      <%= form.label :telegram_username %>
+      <%= form.text_field :telegram_username %>
+    </div>
+
+    <div class="actions">
+      <%= form.submit "Update Profile" %>
+    </div>
+  <% end %>
+</div>
diff --git a/app/views/users/update.html.erb b/app/views/users/update.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..7ead44d26f45fe7623a624b881c824f668cce592
--- /dev/null
+++ b/app/views/users/update.html.erb
@@ -0,0 +1,4 @@
+<div>
+  <h1 class="font-bold text-4xl">Users#update</h1>
+  <p>Find me in app/views/users/update.html.erb</p>
+</div>
diff --git a/config/routes.rb b/config/routes.rb
index 6f22f91e52ef48af5afded9115ea5c0a966d8436..80999f2dfae0b1a57235af8ac99eac132cd1c586 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,10 @@
 Rails.application.routes.draw do
+  get 'login', to: 'users#login', as: :login
+  post 'login', to: 'users#login'
+  post 'logout', to: 'users#logout', as: :logout
+  get 'profile', to: 'users#profile', as: :profile
+  patch 'profile', to: 'users#update_profile', as: :update_profile
+  resources :users, only: [:show]
   # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
 
   # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6753bae81db05556a24e7114407c38a79804778e
--- /dev/null
+++ b/test/controllers/users_controller_test.rb
@@ -0,0 +1,23 @@
+require "test_helper"
+
+class UsersControllerTest < ActionDispatch::IntegrationTest
+  test "should get login" do
+    get users_login_url
+    assert_response :success
+  end
+
+  test "should get logout" do
+    get users_logout_url
+    assert_response :success
+  end
+
+  test "should get show" do
+    get users_show_url
+    assert_response :success
+  end
+
+  test "should get update" do
+    get users_update_url
+    assert_response :success
+  end
+end