<% content_for :title do %> <%= @is_own_settings ? "My Settings" : "Settings | #{@user.display_name}" %> <% end %>

<%= @is_own_settings ? "My Settings" : "Settings for #{@user.display_name}" %>

Change your Hackatime experience and preferences

🚀

Time Tracking Wizard

Get started with tracking your coding time in just a few minutes.

<%= link_to "Set up time tracking", my_wakatime_setup_path, class: "inline-flex items-center gap-2 px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200" %>
🌍

Timezone

<%= form_with model: @user, url: @is_own_settings ? my_settings_path : settings_user_path(@user), method: :patch, local: false, class: "space-y-4" do |f| %>
<%= f.label :timezone, "Your timezone", class: "block text-sm font-medium text-gray-200 mb-2" %> <%= f.select :timezone, TZInfo::Timezone.all.map(&:identifier).sort, { include_blank: @user.timezone.blank? }, { class: "w-full px-3 py-2 bg-gray-800 border border-gray-600 rounded text-white focus:border-primary focus:ring-1 focus:ring-primary" } %>

This affects how your activity graph and other time-based features are displayed.

<%= f.submit "Save Settings", class: "w-full px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200 cursor-pointer" %> <% end %>
⚙️

Extension Settings

<%= form_with model: @user, url: @is_own_settings ? my_settings_path : settings_user_path(@user), method: :patch, local: false, class: "space-y-4" do |f| %>
<%= f.label :hackatime_extension_text_type, "Status bar text style", class: "block text-sm font-medium text-gray-200 mb-2" %> <%= f.select :hackatime_extension_text_type, User.hackatime_extension_text_types.keys.map { |key| [key.humanize, key] }, {}, { class: "w-full px-3 py-2 bg-gray-800 border border-gray-600 rounded text-white focus:border-primary focus:ring-1 focus:ring-primary" } %>
<%= f.submit "Save Settings", class: "w-full px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200 cursor-pointer" %> <% end %>
🪪

Display Name

<%= form_with model: @user, url: @is_own_settings ? my_settings_path : settings_user_path(@user), method: :patch, local: false, class: "space-y-4" do |f| %>
<%= f.label :username, "Custom display name", class: "block text-sm font-medium text-gray-200 mb-2" %> <%= f.text_field :username, class: "w-full px-3 py-2 bg-gray-800 border border-gray-600 rounded text-white focus:border-primary focus:ring-1 focus:ring-primary", placeholder: "HackClubber", maxlength: User::USERNAME_MAX_LENGTH %> <% if @user.errors[:username].present? %>

<%= @user.errors[:username].to_sentence %>

<% end %>

Choose a name to use in Hackatime. This will take priority over Slack or GitHub names when possible. Letters, numbers, "-" and "_" only, max <%= User::USERNAME_MAX_LENGTH %> chars.

<%= f.submit "Save Settings", class: "w-full px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200 cursor-pointer" %> <% end %>
💬

Slack Integration

Status Updates

When you're hacking on a project, Hackatime can update your Slack status so you can show it off!

<% unless @can_enable_slack_status %> <%= link_to "Re-authorize with Slack", slack_auth_path, class: "inline-flex items-center gap-2 px-3 py-2 bg-gray-700 hover:bg-gray-600 text-gray-200 text-sm font-medium rounded transition-colors duration-200 mb-3" %> <% end %> <%= form_with model: @user, url: @is_own_settings ? my_settings_path : settings_user_path(@user), method: :patch, local: false do |f| %>
<%= f.check_box :uses_slack_status, class: "w-4 h-4 text-primary border-gray-600 rounded focus:ring-primary bg-gray-800" %> <%= f.label :uses_slack_status, "Update my Slack status automatically", class: "text-sm text-gray-200" %>
<%= f.submit "Save", class: "mt-3 px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200 cursor-pointer" %> <% end %>

Channel Notifications

<% if @enabled_sailors_logs.any? %>

You have notifications enabled for the following channels:

    <% @enabled_sailors_logs.each do |sl| %>
  • <%= render "shared/slack_channel_mention", channel_id: sl.slack_channel_id %>
  • <% end %>
<% else %>

You have no notifications enabled.

<% end %>

You can enable notifications for specific channels by running /sailorslog on in the Slack channel.

🔒

Privacy Settings

<%= form_with model: @user, url: @is_own_settings ? my_settings_path : settings_user_path(@user), method: :patch, local: false, class: "space-y-4" do |f| %>
<%= f.check_box :allow_public_stats_lookup, class: "w-4 h-4 text-primary border-gray-600 rounded focus:ring-primary bg-gray-800" %> <%= f.label :allow_public_stats_lookup, "Allow public stats lookup", class: "text-sm text-gray-200" %>

When enabled, others can view your coding statistics through public APIs. Many Hack Club YSWS programs use this to track your progress. Disabling this can prevent you from participating in some programs.

<%= f.submit "Save Settings", class: "w-full px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200 cursor-pointer" %> <% end %>
🗑️

Delete Account

<% if @user.can_request_deletion? %>

Permanently delete your account and all associated data. This action cannot be undone after the 30-day grace period.

<% else %>

Due to your account standing, you cannot request account deletion at this time. Reach out in #hackatime-v2 if this is a mistake.

<% end %>
🔑

API Key

Your API key is used to authenticate requests from your code editor. If your key has been compromised, you can rotate it to generate a new one. Rotating your API key will immediately invalidate your old key. You'll need to update the key in all of your code editors and IDEs.

🔗

Connected Accounts

GitHub Account

This is used to show your active projects on the leaderboard & current hacking activity on the dashboard.

<% if @user.github_uid.present? %>
Connected: <%= link_to "@#{h(@user.github_username)}", "https://github.com/#{h(@user.github_username)}", target: "_blank", class: "text-primary hover:text-primary/80 underline" %>
<%= link_to "Relink GitHub Account", github_auth_path, data: { turbo: "false" }, class: "inline-flex items-center gap-2 px-3 py-2 bg-primary text-white text-sm font-medium rounded transition-colors duration-200" %> <% else %> <%= link_to "Link GitHub Account", github_auth_path, data: { turbo: "false" }, class: "inline-flex items-center gap-2 px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200" %> <% end %>

Email Addresses

These are the email addresses associated with your account.

<% if @user.email_addresses.any? %>
<% @user.email_addresses.each do |email| %>
<%= email.email %> <%= email.source&.humanize || "Unknown" %>
<% end %>
<% else %>

No email addresses found.

<% end %> <%= form_tag add_email_auth_path, data: { turbo: false }, class: "space-y-2" do %> <%= email_field_tag :email, nil, placeholder: "Add another email address", required: true, class: "w-full px-3 py-2 bg-gray-800 border border-gray-600 rounded text-white focus:border-primary focus:ring-1 focus:ring-primary text-sm" %> <%= submit_tag "Add Email", class: "w-full px-3 py-2 bg-primary hover:bg-primary/80 text-white text-sm font-medium rounded transition-colors duration-200 cursor-pointer" %> <% end %>
📊

Stats Badges

General Stats Badge

Show your coding stats on your GitHub profile with beautiful badges.

<% gh_badge = GithubReadmeStats.new(current_user.id, "darcula") %>
<%= gh_badge.generate_badge_url %>
<% if @projects.any? && @user.slack_uid.present? %>

Project Stats Badge

<%= @work_time_stats_url %>
<% end %>
📄

Config File

Your Wakatime configuration file for tracking coding time.

<%= render "wakatime_config_display" %>

This configuration file is automatically generated and updated when you make changes to your settings.

🚚

Migration Assistant

This will migrate your heartbeats from waka.hackclub.com to this platform.

<%= button_to "Migrate heartbeats", my_settings_migrate_heartbeats_path, method: :post, class: "w-full px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200 cursor-pointer" %> <% if @heartbeats_migration_jobs.any? %>

Migration Status

<% @heartbeats_migration_jobs.each do |job| %>
Job ID: <%= job.id %> - Status: <%= job.status %>
<% end %>
<% end %>
📝

Markscribe Templates

Use markscribe to create beautiful GitHub profile READMEs with your coding stats.

{{ wakatimeDoubleCategoryBar "💾 Languages:" wakatimeData.Languages "💼 Projects:" wakatimeData.Projects 5 }}

Add this to your GitHub profile README template to display your top languages and projects.

See the markscribe documentation for more template options.

Example of markscribe output showing coding language and project statistics
<%# This is copied from the github thingie blog, Im not good at UI so I copied :) %>
<% if @user.trust_level == "red" %>
💾

Download Your Data

⚠️ Export Restricted

Sorry, due to your account standing, you are unable to perform this action.

<% else %>
💾

Download Your Data

Your Data Overview

<%= number_with_delimiter(@user.heartbeats.count) %>
Total Heartbeats
<%= @user.heartbeats.duration_simple %>
Total Coding Time
<%= @user.heartbeats.where("time >= ?", 7.days.ago.to_f).count %>
Heartbeats in the Last 7 Days

Export Options

Heartbeat Data

Export your coding activity as JSON with detailed information about each coding session.

<%= link_to export_my_heartbeats_path(format: :json, all_data: "true"), class: "w-full bg-primary hover:bg-red text-white px-4 py-2 rounded font-medium transition-colors inline-flex items-center justify-center gap-2", method: :get do %> Export All Heartbeats <% end %> <%= link_to "#", class: "w-full bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded font-medium transition-colors inline-flex items-center justify-center gap-2", data: { controller: "heartbeat-export", action: "click->heartbeat-export#handleExport" } do %> Export Date Range <% end %>

All Heartbeats: Downloads your complete coding history, from the very start to your last heartbeat

Date Range: Choose specific dates to export

<% dev_tool do %>

Import Heartbeat Data

Import ur data from real hackatime to test stuff with.

PS: your console will be spammed and might crash ur dev env so be carefull if the file is very big

<%= form_with url: import_my_heartbeats_path, method: :post, multipart: true, local: true, class: "space-y-4" do |form| %>
<%= form.file_field :heartbeat_file, accept: ".json,application/json", class: "w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded text-white file:mr-4 file:py-2 file:px-4 file:rounded file:border-0 file:text-sm file:font-semibold file:bg-primary file:text-white hover:file:bg-red transition-colors", required: true %>
<%= form.submit "Import Heartbeats", class: "bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded font-medium transition-colors inline-flex items-center gap-2", data: { confirm: "Are you sure you want to import heartbeats? This will add new data to your account." } %>
<% end %>
<% end %>
<% end %>
<% admin_tool do %>
🔧

WakaTime Mirrors

<% if current_user.wakatime_mirrors.any? %> <% grid_cols = current_user.wakatime_mirrors.size > 1 ? "md:grid-cols-2" : "" %>
<% current_user.wakatime_mirrors.each do |mirror| %>

<%= mirror.endpoint_url %>

Last synced: <%= mirror.last_synced_at ? time_ago_in_words(mirror.last_synced_at) + " ago" : "Never" %>

<% end %>
<% end %> <%= form_with(model: [current_user, WakatimeMirror.new], local: true, class: "space-y-4") do |f| %>
<%= f.label :endpoint_url, class: "block text-sm font-medium text-gray-200 mb-2" %> <%= f.url_field :endpoint_url, value: "https://wakatime.com/api/v1", class: "w-full px-3 py-2 bg-gray-800 border border-gray-600 rounded text-white focus:border-primary focus:ring-1 focus:ring-primary" %>
<%= f.label :encrypted_api_key, "WakaTime API Key", class: "block text-sm font-medium text-gray-200 mb-2" %> <%= f.password_field :encrypted_api_key, placeholder: "Enter your WakaTime API key", class: "w-full px-3 py-2 bg-gray-800 border border-gray-600 rounded text-white focus:border-primary focus:ring-1 focus:ring-primary" %>
<%= f.submit "Add Mirror", class: "px-4 py-2 bg-primary text-white font-medium rounded transition-colors duration-200" %> <% end %>
<% end %>
<%= render "shared/modal", modal_id: "api-key-confirm-modal", title: "Rotate API Key?", description: "Your old key will be immediately invalidated and you'll need to update it in all your applications.", icon_svg: '', icon_color: "text-primary", buttons: [ { text: "Cancel", class: "border border-gray-600 text-gray-300 hover:bg-darkless", action: "click->modal#close" }, { text: "Rotate Now", class: "bg-primary text-white hover:bg-red-600 font-medium", action: "click->api-key-rotation#rotate" } ] %> <%= render "shared/modal", modal_id: "api-key-success-modal", title: "New API Key Generated", description: "Your old API key has been invalidated. Update your editor configuration with this new key:", icon_svg: '', icon_color: "text-green-500", max_width: "max-w-lg", buttons: [ { text: "Close", class: "border border-gray-600 text-gray-300 hover:bg-darkless", action: "click->modal#close" }, { text: "Copy Key", class: "bg-primary text-white hover:bg-red-600 font-medium", action: "click->api-key-rotation#copyKey" } ], custom: '
' %>
<% if @user.can_request_deletion? %>
<%= render "shared/modal", modal_id: "account-deletion-confirm-modal", title: "Delete Your Account?", description: "This will permanently delete your account after a 30 day waiting period. During this time, you won't be able to use your account for any Hack Club programs.", icon_svg: '', icon_color: "text-primary", buttons: [ { text: "Cancel", class: "border border-gray-600 text-gray-300 hover:bg-darkless", action: "click->modal#close" }, { text: "Delete My Account", class: "bg-primary text-white hover:bg-red-600 font-medium", form: true, url: create_deletion_path, method: "post" } ] %>
<% end %>