diff --git a/pygitweb/static/board.js b/pygitweb/static/board.js
index 1fd5ba7..43ebe83 100644
--- a/pygitweb/static/board.js
+++ b/pygitweb/static/board.js
@@ -117,6 +117,36 @@
     initBoard();
   }
 
+  function taskDisplayId(ref) {
+    if (!ref) return '';
+    var slug = ref.replace(/^refs\/tags\/tasks\//, '');
+    if (slug.indexOf('task_') === 0) return slug.slice(5);
+    return slug;
+  }
+
+  function taskDisplayIdShort(fullId) {
+    if (!fullId) return '';
+    return fullId.length <= 4 ? fullId : fullId.slice(-4);
+  }
+
+  function syncCardTitleLineTooltip(card) {
+    var titleLine = card.querySelector('.board-card-title-line');
+    if (!titleLine) return;
+    var titleEl = card.querySelector('.board-card-title');
+    var titleText = ((titleEl && titleEl.textContent) || '').trim() || 'Untitled';
+    var fullId = card.dataset.taskRef ? taskDisplayId(card.dataset.taskRef) : '';
+    titleLine.title = fullId ? (fullId + ': ' + titleText) : titleText;
+  }
+
+  function setCardTaskRefDisplay(card, ref, id) {
+    var fullId = id || taskDisplayId(ref);
+    var idEl = card.querySelector('.board-card-task-id');
+    if (idEl) idEl.textContent = taskDisplayIdShort(fullId);
+    var refEl = card.querySelector('.board-card-task-ref');
+    if (refEl) refEl.textContent = ref || '';
+    syncCardTitleLineTooltip(card);
+  }
+
   function getBoardContext() {
     var boardColumns = document.querySelector('.board-columns');
     var project = boardColumns && boardColumns.dataset.project;
@@ -137,8 +167,10 @@
     var status = task.status || 'TODO';
     card.dataset.taskRef = task.ref || '';
     card.dataset.taskStatus = status;
+    setCardTaskRefDisplay(card, task.ref || '', task.id);
     var titleEl = card.querySelector('.board-card-title');
     if (titleEl) titleEl.textContent = task.title || 'Untitled';
+    syncCardTitleLineTooltip(card);
     var descFull = card.querySelector('.board-card-description-full');
     if (descFull) setMarkdownElement(descFull, task.description || '');
     syncCompactDescription(card, task.description || '');
@@ -249,6 +281,7 @@
     if (!card) return;
     var titleEl = card.querySelector('.board-card-title');
     if (titleEl) titleEl.textContent = 'New task';
+    syncCardTitleLineTooltip(card);
     assignCloudIconToCard(card);
     cardsContainer.appendChild(clone);
     var badge = column.querySelector('.board-column-add-card');
@@ -271,7 +304,10 @@
       if (res.ok) {
         return res.json().then(function(body) {
           setCardIcon(card, 'cloud-filled');
-          if (body.ref) card.dataset.taskRef = body.ref;
+          if (body.ref) {
+            card.dataset.taskRef = body.ref;
+            setCardTaskRefDisplay(card, body.ref);
+          }
         });
       }
       if (res.status >= 400 && res.status < 600) {
@@ -574,6 +610,7 @@
       titleEl.textContent = val;
       titleEl.classList.remove('d-none');
       input.remove();
+      syncCardTitleLineTooltip(popoutCard);
       pushTaskUpdate();
     }
     if (titleEl) {
diff --git a/pygitweb/static/main.css b/pygitweb/static/main.css
index c3e6e8a..5eb6e08 100644
--- a/pygitweb/static/main.css
+++ b/pygitweb/static/main.css
@@ -1024,10 +1024,14 @@ pre {
 	-webkit-mask-image: url(/static/icons/cloud-exclamation.svg);
 	mask-image: url(/static/icons/cloud-exclamation.svg);
 }
-.board-card .board-card-title {
+.board-card .board-card-title-line {
 	padding-right: 1.75rem;
 }
 
+.board-card-popout .board-card-task-id {
+	display: none;
+}
+
 /* Board card popout: overlay and card on top of the board (above navbar and Bootstrap modals) */
 .board-card-popout-overlay {
 	position: fixed;
diff --git a/pygitweb/tasks.py b/pygitweb/tasks.py
index 531a911..20342ea 100644
--- a/pygitweb/tasks.py
+++ b/pygitweb/tasks.py
@@ -202,9 +202,18 @@ def boards_delete(
 task_router = APIRouter(tags=["tasks"])
 
 
+def _task_display_id(ref: str) -> str:
+	"""Numeric task id for UI (task_1730000000000 -> 1730000000000)."""
+	slug = ref.removeprefix(TASK_REF_PREFIX)
+	if slug.startswith("task_"):
+		return slug.removeprefix("task_")
+	return slug
+
+
 def _task_to_json(t: Task) -> dict[str, Any]:
 	return {
 		"ref": t.name,
+		"id": _task_display_id(t.name),
 		"title": t.title,
 		"description": getattr(t, "description", "") or "",
 		"status": t.status.value if t.status else None,
diff --git a/pygitweb/tasks_routes_test.py b/pygitweb/tasks_routes_test.py
index cd2a1c0..b37209d 100644
--- a/pygitweb/tasks_routes_test.py
+++ b/pygitweb/tasks_routes_test.py
@@ -120,6 +120,7 @@ class TestTaskRoutes:
 			tasks_by_ref = {entry["ref"]: entry for entry in body}
 			alpha = tasks_by_ref[str(seeded_env["task_a_ref"])]
 			assert alpha["title"] == "Alpha"
+			assert alpha["id"] == "a"
 			assert alpha["description"] == "Alpha description"
 			assert alpha["status"] == "TODO"
 			assert alpha["priority"] == "HIGH"
diff --git a/pygitweb/templates/board_card.html b/pygitweb/templates/board_card.html
index f68ee73..c705fe4 100644
--- a/pygitweb/templates/board_card.html
+++ b/pygitweb/templates/board_card.html
@@ -2,7 +2,7 @@
 <div class="card board-card mb-2 draggable" data-task-ref="{{ task.ref if task else '' }}" data-task-status="{{ (task.status or 'TODO') if task else 'TODO' }}" draggable="true">
   <div class="card-body py-2 px-3 position-relative">
     <span class="board-card-icon-wrap position-absolute top-0 end-0 mt-1 me-1" aria-hidden="true"><span class="board-card-icon" data-icon="cloud"></span></span>
-    <div class="board-card-title fw-medium text-truncate"{% if task %} title="{{ task.title }}"{% endif %}>{% if task %}{{ task.title or 'Untitled' }}{% endif %}</div>
+    <div class="board-card-title-line text-truncate fw-medium"{% if task and task.id %} title="{{ task.id }}: {{ task.title or 'Untitled' }}"{% elif task and task.title %} title="{{ task.title }}"{% endif %}><span class="board-card-task-id fw-bold font-monospace me-1">{% if task and task.id %}{{ task.id[-4:] }}{% endif %}</span><span class="board-card-title">{% if task %}{{ task.title or 'Untitled' }}{% endif %}</span></div>
     <div class="board-card-description small board-card-description-preview mt-1 text-truncate">{% if task and task.description %}{{ task.description }}{% else %}{% endif %}</div>
     <div class="board-card-meta d-flex align-items-center gap-1 mt-1 small text-muted">
       {% if task %}
@@ -24,6 +24,7 @@
       {% endif %}
     </div>
     <div class="board-card-details d-none mt-2 pt-2 border-top small">
+      <div class="mb-2"><strong class="text-muted">Ref</strong><div class="board-card-task-ref font-monospace text-muted mt-1 text-break">{% if task and task.ref %}{{ task.ref }}{% else %}{% endif %}</div></div>
       <div class="mb-2"><strong class="text-muted">Description</strong><div class="board-card-description-full board-card-editable board-card-markdown mt-1">{% if task and task.description %}{{ task.description }}{% else %}{% endif %}</div></div>
       <div class="mb-2"><strong class="text-muted">Due date</strong><div class="board-card-due-date board-card-editable text-muted mt-1">{% if task and task.due_date %}{{ task.due_date }}{% else %}None{% endif %}</div></div>
       <div class="mb-2"><strong class="text-muted">Last modified</strong><div class="board-card-updated-at text-muted mt-1">{% if task and task.updated_at %}{{ task.updated_at }}{% else %}None{% endif %}</div></div>
