diff --git a/pygitweb/README.md b/pygitweb/README.md
index 27bc110..c1bd6fe 100644
--- a/pygitweb/README.md
+++ b/pygitweb/README.md
@@ -35,38 +35,44 @@ Set environment variables (or use a Python config file via `GITWEB_CONFIG`):
 
 ## Routes
 
-See [ROUTES.md](ROUTES.md) for more detail.
+Load the `/docs` page for a detailed view of routes (below the readme) if in debug mode. 
 
 **No-project routes**
 
-- `GET /` — project list
-- `GET /index` — plain text project index (path, owner)
-- `GET /opml` — OPML feed list
-
-**Project-scoped actions (implemented)**
-
-- `GET /{project}` or `a=summary` — project summary (description, owner, HEAD, tree link)
-- `GET /{project}?a=tree&h=...&f=...` — directory listing (tree)
-- `GET /{project}?a=blob&h=...&f=...` — file view (HTML)
-- `GET /{project}?a=blob_plain&h=...&f=...` — raw file download
-- `GET /{project}?a=log&h=...` — commit log
-- `GET /{project}?a=shortlog&h=...` — shortlog
-- `GET /{project}?a=history&h=...&f=...` — history of a file or path
-- `GET /{project}?a=heads` — list branch heads
-- `GET /{project}?a=tags` — list all tags
-- `GET /{project}?a=tag&h=...` — single tag view (tag ref or hash)
-- `GET /{project}?a=commit` — commit information
-- `GET /{project}?a=commitdiff` — commit diff (unified diff rendered with [diff2html](https://github.com/rtfpessoa/diff2html))
-- `GET /{project}?a=patch&h=...` — single-commit patch (plain text)
-- `GET /{project}?a=patches&h=...&hb=...` — multi-commit patches for range `hb..h` (plain text)
-- `GET /{project}?a=blobdiff&h=...&hb=...&f=...&fp=...` — blob diff (two versions of a file) rendered with diff2html
-- `GET /{project}?a=blobpatch&h=...&hb=...&f=...&fp=...` — blob diff as plain unified diff
-- `GET /{project}?a=remotes` — list repo remotes
-- `GET /{project}?a=object&h=...` — show object by type (commit, tree, tag, or blob)
-
-**Project-scoped actions (stub only)**
-
-These actions are accepted but return a minimal placeholder page. Add handlers in `main.py` to implement: `blame`, `blame_incremental`, `blame_data`, `rss`, `atom`, `search`, `search_help`.
+- `GET /`: project list
+- `GET /index`: plain text project index (path, owner)
+- `GET /opml`: OPML feed list
+- `GET /project/{name}`: Project dispatch (See actions table)
+
+**Actions**
+
+| Action | Query parameters | URL | Description |
+|--------|------------------|-----|-------------|
+| summary | *(default)* or `a` | `GET /project/{project}` | Project summary (description, owner, HEAD, tree link). |
+| tree | `h`, `f` | `GET /project/{project}?a=tree&h=...&f=...` | Directory listing (tree). |
+| blob | `h`, `f` | `GET /project/{project}?a=blob&h=...&f=...` | File view (HTML). |
+| blob_plain | `h`, `f` | `GET /project/{project}?a=blob_plain&h=...&f=...` | Raw file download. |
+| log | `h` | `GET /project/{project}?a=log&h=...` | Commit log. |
+| shortlog | `h` | `GET /project/{project}?a=shortlog&h=...` | Shortlog. |
+| history | `h`, `f` | `GET /project/{project}?a=history&h=...&f=...` | History of a file or path. |
+| heads | — | `GET /project/{project}?a=heads` | List branch heads. |
+| tags | — | `GET /project/{project}?a=tags` | List all tags. |
+| tag | `h` | `GET /project/{project}?a=tag&h=...` | Single tag view (tag ref or hash). |
+| commit | — | `GET /project/{project}?a=commit` | Commit information. |
+| commitdiff | — | `GET /project/{project}?a=commitdiff` | Commit diff (unified diff rendered with [diff2html](https://github.com/rtfpessoa/diff2html)). |
+| patch | `h` | `GET /project/{project}?a=patch&h=...` | Single-commit patch (plain text). |
+| patches | `h`, `hb` | `GET /project/{project}?a=patches&h=...&hb=...` | Multi-commit patches for range `hb..h` (plain text). |
+| blobdiff | `h`, `hb`, `f`, `fp` | `GET /project/{project}?a=blobdiff&h=...&hb=...&f=...&fp=...` | Blob diff (two versions of a file) rendered with diff2html. |
+| blobpatch | `h`, `hb`, `f`, `fp` | `GET /project/{project}?a=blobpatch&h=...&hb=...&f=...&fp=...` | Blob diff as plain unified diff. |
+| remotes | — | `GET /project/{project}?a=remotes` | List repo remotes. |
+| object | `h` | `GET /project/{project}?a=object&h=...` | Show object by type (commit, tree, tag, or blob). |
+| blame | — | | TODO |
+| blame_incremental | — | | TODO |
+| blame_data | — | | TODO |
+| rss | — | | TODO |
+| atom | — | | TODO |
+| search | — | | TODO |
+| search_help | — | | TODO |
 
 ## Query parameter short names (CGI mapping)
 
diff --git a/pygitweb/actions.py b/pygitweb/actions.py
index 4cf1599..4e90471 100644
--- a/pygitweb/actions.py
+++ b/pygitweb/actions.py
@@ -77,11 +77,11 @@ def parse_pagination(
 
 
 def _tree_url(project: str, h: str, f: str | None, a: str = "tree") -> str:
-    """Build URL for tree or blob: /project?a=a&h=h&f=f with f quoted."""
+    """Build URL for tree or blob: /project/{project}?a=a&h=h&f=f with f quoted."""
     q = f"a={a}&h={quote(h, safe='')}"
     if f:
         q += f"&f={quote(f, safe='/')}"
-    return f"/{project}?{q}"
+    return f"/project/{project}?{q}"
 
 
 def _format_date(epoch: int | None, tz_offset: int | None = None) -> str:
@@ -117,8 +117,8 @@ def _format_commit_table_row(project: str, commit: dict[str, Any], short: bool =
     else:
         age_str = ""
 
-    commit_link = f"/{project}?a=commit&h={quote(oid, safe='')}"
-    diff_link = f"/{project}?a=commitdiff&h={quote(oid, safe='')}"
+    commit_link = f"/project/{project}?a=commit&h={quote(oid, safe='')}"
+    diff_link = f"/project/{project}?a=commitdiff&h={quote(oid, safe='')}"
     author_display = esc_html(author) or "unknown"
 
     if short:
@@ -182,7 +182,7 @@ def _render_readme_card(
 ) -> str:
     """Return HTML for the README card (and script for markdown). blob_dir is the current tree path for relative links."""
     is_markdown = readme_filename.lower().endswith(".md")
-    blob_base = f"/{project}?a=blob&h={quote(ref_oid, safe='')}&f="
+    blob_base = f"/project/{project}?a=blob&h={quote(ref_oid, safe='')}&f="
     blob_base_attr = blob_base.replace("&", "&amp;").replace('"', "&quot;")
     blob_dir_attr = blob_dir.replace("&", "&amp;").replace('"', "&quot;") if blob_dir else ""
     if is_markdown:
@@ -262,7 +262,7 @@ def git_object(project: str, h: str | None) -> Response:
             title=f"Blob {oid_short} - {esc_html(project)}",
             site_name=config.SITE_NAME,
         )
-        return HTMLResponse(f"{pre}<h1>Blob {esc_html(oid_short)}</h1><p>Project: <a href='/{project}'>{esc_html(project)}</a></p>{blob_html}{POSTAMBLE}")
+        return HTMLResponse(f"{pre}<h1>Blob {esc_html(oid_short)}</h1><p>Project: <a href='/project/{project}'>{esc_html(project)}</a></p>{blob_html}{POSTAMBLE}")
     raise HTTPException(status_code=404, detail="Unknown object type")
 
 
@@ -278,13 +278,13 @@ def git_summary(project: str) -> HTMLResponse:
         rows=[
             ["Description", esc_html(descr)],
             ["Owner", esc_html(owner)],
-            [esc_html("HEAD"), f"<a href='/{project}?a=commit&h={quote(head or '', safe='')}'>{head_short or 'N/A'}</a>"],
-            [esc_html("tree"), f"<a href='/{project}?a=tree&h={head or ''}'>browse</a>"],
-            ["Log", f"<a href='/{project}?a=log&h={head or ''}'>view log</a>"],
-            ["Shortlog", f"<a href='/{project}?a=shortlog&h={head or ''}'>view shortlog</a>"],
-            ["Heads", f"<a href='/{project}?a=heads'>view heads</a>"],
-            ["Tags", f"<a href='/{project}?a=tags'>view tags</a>"],
-            ["Remotes", f"<a href='/{project}?a=remotes'>view remotes</a>"],
+            [esc_html("HEAD"), f"<a href='/project/{project}?a=commit&h={quote(head or '', safe='')}'>{head_short or 'N/A'}</a>"],
+            [esc_html("tree"), f"<a href='/project/{project}?a=tree&h={head or ''}'>browse</a>"],
+            ["Log", f"<a href='/project/{project}?a=log&h={head or ''}'>view log</a>"],
+            ["Shortlog", f"<a href='/project/{project}?a=shortlog&h={head or ''}'>view shortlog</a>"],
+            ["Heads", f"<a href='/project/{project}?a=heads'>view heads</a>"],
+            ["Tags", f"<a href='/project/{project}?a=tags'>view tags</a>"],
+            ["Remotes", f"<a href='/project/{project}?a=remotes'>view remotes</a>"],
         ],
     )
     pre = PREAMBLE.render(title=f"{esc_html(config.SITE_NAME)} - {project}", site_name=config.SITE_NAME)
@@ -355,7 +355,7 @@ def git_blob(project: str, h: str | None, f: str | None, *, raw: bool = False) -
         f"<pre class=\"blob-content\"><code class=\"hljs{lang_attr}\">{body}</code></pre>"
         f"</div>"
     )
-    blob_script = '<script src="static/blob-view.js"></script>'
+    blob_script = '<script src="/static/blob-view.js"></script>'
     pre = PREAMBLE.render(title=f"{esc_html(f)} - {esc_html(project)}", site_name=config.SITE_NAME)
     return HTMLResponse(f"{pre}{blob_html}{blob_script}{POSTAMBLE}")
 
@@ -368,7 +368,7 @@ def git_tree(project: str, h: str | None, f: str | None) -> HTMLResponse:
     if not result:
         raise HTTPException(status_code=404, detail="Tree or path not found")
     tree, ref_oid = result
-    base = f"/{project}"
+    base = f"/project/{project}"
     breadcrumbs = [f'<a href="{base}">{esc_html(project)}</a>']
     if f:
         parts = f.strip("/").split("/")
@@ -486,7 +486,7 @@ def git_history(project: str, h: str | None, f: str | None, request: Request, pa
     )
     pagination_html = _render_pagination(request, page, pagecount, page > 1, has_next)
     return HTMLResponse(
-        f"{pre}<h1>{title}</h1><p>Project: <a href='/{project}'>{esc_html(project)}</a></p>{table}{pagination_html}{POSTAMBLE}"
+        f"{pre}<h1>{title}</h1><p>Project: <a href='/project/{project}'>{esc_html(project)}</a></p>{table}{pagination_html}{POSTAMBLE}"
     )
 
 
@@ -498,8 +498,8 @@ def git_heads(project: str) -> HTMLResponse:
     rows = []
     for name, _ref, oid in heads_list:
         oid_short = oid[:7] if oid else ""
-        commit_link = f"/{project}?a=commit&h={quote(oid, safe='')}"
-        tree_link = f"/{project}?a=tree&h={quote(oid, safe='')}"
+        commit_link = f"/project/{project}?a=commit&h={quote(oid, safe='')}"
+        tree_link = f"/project/{project}?a=tree&h={quote(oid, safe='')}"
         rows.append([
             f'<a href="{commit_link}">{esc_html(name)}</a>',
             f'<a href="{commit_link}">{esc_html(oid_short)}</a>',
@@ -512,7 +512,7 @@ def git_heads(project: str) -> HTMLResponse:
         rows=rows,
     )
     return HTMLResponse(
-        f"{pre}<h1>{title}</h1><p>Project: <a href='/{project}'>{esc_html(project)}</a></p>{table}{POSTAMBLE}"
+        f"{pre}<h1>{title}</h1><p>Project: <a href='/project/{project}'>{esc_html(project)}</a></p>{table}{POSTAMBLE}"
     )
 
 
@@ -533,7 +533,7 @@ def git_tags(project: str, request: Request, page: int, pagecount: int) -> HTMLR
         raise HTTPException(status_code=404, detail="Repository not found")
     rows = []
     for name, _ref, oid in tags_page:
-        tag_link = f"/{project}?a=tag&h={quote(oid, safe='')}"
+        tag_link = f"/project/{project}?a=tag&h={quote(oid, safe='')}"
         target_oid = oid
         target_type = "commit"
         try:
@@ -545,9 +545,9 @@ def git_tags(project: str, request: Request, page: int, pagecount: int) -> HTMLR
             pass
         target_short = target_oid[:7] if target_oid else ""
         if target_type == "commit":
-            target_link = f"/{project}?a=commit&h={quote(target_oid, safe='')}"
+            target_link = f"/project/{project}?a=commit&h={quote(target_oid, safe='')}"
         elif target_type == "tree":
-            target_link = f"/{project}?a=tree&h={quote(target_oid, safe='')}"
+            target_link = f"/project/{project}?a=tree&h={quote(target_oid, safe='')}"
         else:
             target_link = None
         obj_cell = f'<a href="{target_link}">{esc_html(target_short)}</a>' if target_link else esc_html(target_short)
@@ -565,7 +565,7 @@ def git_tags(project: str, request: Request, page: int, pagecount: int) -> HTMLR
         request, page, pagecount, page > 1, page < total_pages, total_pages=total_pages
     )
     return HTMLResponse(
-        f"{pre}<h1>{title}</h1><p>Project: <a href='/{project}'>{esc_html(project)}</a></p>{table}{pagination_html}{POSTAMBLE}"
+        f"{pre}<h1>{title}</h1><p>Project: <a href='/project/{project}'>{esc_html(project)}</a></p>{table}{pagination_html}{POSTAMBLE}"
     )
 
 
@@ -601,9 +601,9 @@ def git_tag(project: str, h: str | None) -> HTMLResponse:
         tag_name = tag_oid[:7]
     target_short = target_oid[:7] if target_oid else ""
     if target_type == "commit":
-        object_link = f'<a href="/{project}?a=commit&h={quote(target_oid, safe="")}">{esc_html(target_short)}</a>'
+        object_link = f'<a href="/project/{project}?a=commit&h={quote(target_oid, safe="")}">{esc_html(target_short)}</a>'
     elif target_type == "tree":
-        object_link = f'<a href="/{project}?a=tree&h={quote(target_oid, safe="")}">{esc_html(target_short)}</a>'
+        object_link = f'<a href="/project/{project}?a=tree&h={quote(target_oid, safe="")}">{esc_html(target_short)}</a>'
     else:
         object_link = esc_html(target_short)
     table_rows = [
@@ -618,7 +618,7 @@ def git_tag(project: str, h: str | None) -> HTMLResponse:
     title = f"Tag {esc_html(tag_name)} - {esc_html(project)}"
     pre = PREAMBLE.render(title=title, site_name=config.SITE_NAME)
     return HTMLResponse(
-        f"{pre}<h1>Tag {esc_html(tag_name)}</h1><p>Project: <a href='/{project}'>{esc_html(project)}</a></p>{table}{POSTAMBLE}"
+        f"{pre}<h1>Tag {esc_html(tag_name)}</h1><p>Project: <a href='/project/{project}'>{esc_html(project)}</a></p>{table}{POSTAMBLE}"
     )
 
 
@@ -644,10 +644,10 @@ def git_commit(project: str, h: str | None) -> HTMLResponse:
     author_date = _format_date(data.get("author_epoch"), data.get("author_tz"))
     tree_oid = data.get("tree", "")
     message = (data.get("body") or "").strip()
-    commit_link = f"/{project}?a=commit&h={quote(oid, safe='')}"
-    tree_link = f"/{project}?a=tree&h={quote(oid, safe='')}"
-    diff_link = f"/{project}?a=commitdiff&h={quote(oid, safe='')}"
-    patch_link = f"/{project}?a=patch&h={quote(oid, safe='')}"
+    commit_link = f"/project/{project}?a=commit&h={quote(oid, safe='')}"
+    tree_link = f"/project/{project}?a=tree&h={quote(oid, safe='')}"
+    diff_link = f"/project/{project}?a=commitdiff&h={quote(oid, safe='')}"
+    patch_link = f"/project/{project}?a=patch&h={quote(oid, safe='')}"
     table_rows = [
         ["commit", f'<a href="{commit_link}">{esc_html(oid)}</a>'],
         ["Author", f"{esc_html(author)} &lt;{esc_html(author_email)}&gt;"],
@@ -657,7 +657,7 @@ def git_commit(project: str, h: str | None) -> HTMLResponse:
     for i, parent_id in enumerate(commit.parent_ids):
         parent_oid = str(parent_id)
         parent_short = parent_oid[:7]
-        parent_link = f"/{project}?a=commit&h={quote(parent_oid, safe='')}"
+        parent_link = f"/project/{project}?a=commit&h={quote(parent_oid, safe='')}"
         label = "parent" if len(commit.parent_ids) == 1 else f"parent ({i + 1})"
         table_rows.append([label, f'<a href="{parent_link}">{esc_html(parent_short)}</a>'])
     if message:
@@ -667,7 +667,7 @@ def git_commit(project: str, h: str | None) -> HTMLResponse:
     title = f"Commit {esc_html(oid_short)} - {esc_html(project)}"
     pre = PREAMBLE.render(title=title, site_name=config.SITE_NAME)
     return HTMLResponse(
-        f"{pre}<h1>Commit {esc_html(oid_short)}</h1><p>Project: <a href='/{project}'>{esc_html(project)}</a></p>{table}{POSTAMBLE}"
+        f"{pre}<h1>Commit {esc_html(oid_short)}</h1><p>Project: <a href='/project/{project}'>{esc_html(project)}</a></p>{table}{POSTAMBLE}"
     )
 
 
@@ -681,7 +681,7 @@ def git_commitdiff(project: str, h: str | None) -> HTMLResponse:
         project=project,
         oid_short=oid_short,
         diff_b64=diff_b64,
-        commit_link=f"/{project}?a=commit&h={quote(h or '', safe='')}",
+        commit_link=f"/project/{project}?a=commit&h={quote(h or '', safe='')}",
     )
     return HTMLResponse(f"{pre}{body}{POSTAMBLE}")
 
@@ -749,7 +749,7 @@ def git_blobdiff(
     if diff_text is None:
         raise HTTPException(status_code=404, detail="Blob not found")
     diff_b64 = base64.b64encode(diff_text.encode("utf-8")).decode("ascii")
-    blob_link = f"/{project}?a=blob&h={quote(h or '', safe='')}&f={quote(path_new, safe='/')}"
+    blob_link = f"/project/{project}?a=blob&h={quote(h or '', safe='')}&f={quote(path_new, safe='/')}"
     pre = PREAMBLE.render(
         title=f"Blob diff - {esc_html(path_new)} - {esc_html(project)}",
         site_name=config.SITE_NAME,
diff --git a/pygitweb/main.py b/pygitweb/main.py
index 94af50a..49d76a3 100644
--- a/pygitweb/main.py
+++ b/pygitweb/main.py
@@ -189,7 +189,7 @@ def git_project_list(
     table = env.get_template("table.html").render(
         cols=["Project", "Description"],
         rows=[
-            [f"<a href='/{pr.get('path', "")}'>{pr.get('path', "")}</a>",
+            [f"<a href='/project/{pr.get('path', '')}'>{pr.get('path', '')}</a>",
             pr.get('descr') or pr.get('path', "")]
              for pr in list_[:50]]
     )
@@ -351,13 +351,13 @@ async def addproject_submit(
     except OSError as e:
         raise HTTPException(status_code=500, detail=str(e))
 
-    return RedirectResponse(url=f"/{project_name}", status_code=303)
+    return RedirectResponse(url=f"/project/{project_name}", status_code=303)
 
 
 # ---------- Routes (project required) ----------
 
 
-@app.get("/{project:path}", response_class=HTMLResponse)
+@app.get("/project/{project:path}", response_class=HTMLResponse)
 def dispatch(
     request: Request,
     project: str,
@@ -370,15 +370,12 @@ def dispatch(
     pagecount: Annotated[str | None, Query(alias="pagecount")] = None,
 ):
     """
-    Dispatch by path: /project -> summary; /project/action/... -> action.
+    Dispatch by path: /project/{project} -> summary; /project/{project}/action/... -> action.
     Port of dispatch + run_request path handling.
     """
-    # Normalize project: first path segment that is a valid repo
-    segments = [s for s in project.split("/") if s]
-    if not segments:
+    if not project or project == "":
         raise HTTPException(status_code=400, detail="Project needed")
-    proj = segments[0]
-    _validate_project(proj)
+    _validate_project(project)
     action = a
     hash_param = h or hb
     file_name = f
@@ -386,12 +383,12 @@ def dispatch(
     # If no action, infer: hash only -> object type; project only -> summary
     if not action:
         if hash_param and file_name:
-            obj_type = git_get_type(proj, f"{hash_param}:{file_name}")
+            obj_type = git_get_type(project, f"{hash_param}:{file_name}")
             if not obj_type:
                 raise HTTPException(status_code=404, detail="File or directory does not exist")
             action = "tree" if obj_type == "tree" else "blob_plain"
         elif hash_param:
-            obj_type = git_get_type(proj, hash_param)
+            obj_type = git_get_type(project, hash_param)
             if not obj_type:
                 raise HTTPException(status_code=404, detail="Object does not exist")
             action = {"commit": "commit", "tree": "tree", "blob": "blob", "tag": "tag"}.get(obj_type, "object")
@@ -403,47 +400,47 @@ def dispatch(
         raise HTTPException(status_code=400, detail="Project not needed for this action")
     # Route to handler
     if action == "summary":
-        return git_summary(proj)
+        return git_summary(project)
     if action == "tree":
-        return git_tree(proj, hash_param, file_name)
+        return git_tree(project, hash_param, file_name)
     if action in ("blob", "blob_plain"):
-        return git_blob(proj, hash_param, file_name, raw=(action == "blob_plain"))
+        return git_blob(project, hash_param, file_name, raw=(action == "blob_plain"))
     if action == "blobdiff":
-        return git_blobdiff(proj, h, hb, file_name, file_parent)
+        return git_blobdiff(project, h, hb, file_name, file_parent)
     if action == "blobpatch":
-        return git_blobpatch(proj, h, hb, file_name, file_parent)
+        return git_blobpatch(project, h, hb, file_name, file_parent)
     if action == "log":
         p, pc = parse_pagination(page, pagecount)
-        return git_log(proj, hash_param, request, p, pc)
+        return git_log(project, hash_param, request, p, pc)
     if action == "shortlog":
         p, pc = parse_pagination(page, pagecount)
-        return git_shortlog(proj, hash_param, request, p, pc)
+        return git_shortlog(project, hash_param, request, p, pc)
     if action == "history":
         p, pc = parse_pagination(page, pagecount)
-        return git_history(proj, hash_param, file_name, request, p, pc)
+        return git_history(project, hash_param, file_name, request, p, pc)
     if action == "heads":
-        return git_heads(proj)
+        return git_heads(project)
     if action == "tags":
         p, pc = parse_pagination(page, pagecount)
-        return git_tags(proj, request, p, pc)
+        return git_tags(project, request, p, pc)
     if action == "tag":
-        return git_tag(proj, hash_param)
+        return git_tag(project, hash_param)
     if action == "commit":
-        return git_commit(proj, hash_param)
+        return git_commit(project, hash_param)
     if action == "patch":
-        return git_patch(proj, h)
+        return git_patch(project, h)
     if action == "patches":
-        return git_patches(proj, h, hb)
+        return git_patches(project, h, hb)
     if action == "commitdiff":
-        return git_commitdiff(proj, hash_param)
+        return git_commitdiff(project, hash_param)
     if action == "remotes":
-        return git_remotes(proj)
+        return git_remotes(project)
     if action == "object":
-        return git_object(proj, hash_param)
+        return git_object(project, hash_param)
     # Stub others with minimal response
-    pre = PREAMBLE.render(title=f"{esc_html(action)} - {esc_html(proj)}", site_name=config.SITE_NAME)
+    pre = PREAMBLE.render(title=f"{esc_html(action)} - {esc_html(project)}", site_name=config.SITE_NAME)
     return HTMLResponse(
-        f"{pre}<p>Action: {esc_html(action)}</p><p>Project: {esc_html(proj)}</p>{POSTAMBLE}"
+        f"{pre}<p>Action: {esc_html(action)}</p><p>Project: {esc_html(project)}</p>{POSTAMBLE}"
     )
 
 
diff --git a/pygitweb/templates/blobdiff.html b/pygitweb/templates/blobdiff.html
index a88b3ba..f1d5c65 100644
--- a/pygitweb/templates/blobdiff.html
+++ b/pygitweb/templates/blobdiff.html
@@ -1,5 +1,5 @@
 <h1>Blob diff {{ path_new }}</h1>
-<p>Project: <a href="/{{ project }}">{{ project }}</a> · <a href="{{ blob_link }}">blob</a></p>
+<p>Project: <a href="/project/{{ project }}">{{ project }}</a> · <a href="{{ blob_link }}">blob</a></p>
 <div id="d2h-container" data-diff-b64="{{ diff_b64 }}" data-has-diff="{{ 'true' if diff_b64 else 'false' }}">
   <div id="d2h-output"></div>
   <p id="d2h-empty" class="text-muted" style="display: none;">No changes between these blobs.</p>
diff --git a/pygitweb/templates/commitdiff.html b/pygitweb/templates/commitdiff.html
index c1c0093..0f86c60 100644
--- a/pygitweb/templates/commitdiff.html
+++ b/pygitweb/templates/commitdiff.html
@@ -1,5 +1,5 @@
 <h1>Commit diff {{ oid_short }}</h1>
-<p>Project: <a href="/{{ project }}">{{ project }}</a> · <a href="{{ commit_link }}">commit</a></p>
+<p>Project: <a href="/project/{{ project }}">{{ project }}</a> · <a href="{{ commit_link }}">commit</a></p>
 <div id="d2h-container" data-diff-b64="{{ diff_b64 }}" data-has-diff="{{ 'true' if diff_b64 else 'false' }}">
   <div id="d2h-output"></div>
   <p id="d2h-empty" class="text-muted" style="display: none;">No changes in this commit.</p>
diff --git a/pygitweb/templates/preamble.html b/pygitweb/templates/preamble.html
index 571d540..d76e251 100644
--- a/pygitweb/templates/preamble.html
+++ b/pygitweb/templates/preamble.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html><html><head><title>{{title | default('DistGit')}}</title>
 <script>document.documentElement.setAttribute('data-bs-theme', window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e){ document.documentElement.setAttribute('data-bs-theme', e.matches ? 'dark' : 'light'); });</script>
-<link rel="icon" href="static/logo.svg" type="image/svg+xml">
+<link rel="icon" href="/static/logo.svg" type="image/svg+xml">
 <script id="Highlight-script" async src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
 <script id="MathJax-script" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-chtml.min.js"></script>
@@ -13,7 +13,7 @@
 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=Fira+Mono:wght@400;500;700&family=Fira+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/core@1.0.0-beta17/dist/css/tabler.min.css">
-<link rel="stylesheet" href="static/main.css"/>
+<link rel="stylesheet" href="/static/main.css"/>
 </head><body>
 <div class="page">
   <aside class="navbar navbar-vertical navbar-expand-sm position-fixed">
@@ -23,7 +23,7 @@
       </button>
       <h1 class="navbar-brand navbar-brand-autodark py-3">
         <a href="/" class="d-flex align-items-center text-reset">
-          <img src="static/logo.svg" width="32" height="32" alt="Logo" class="navbar-brand-image me-2" style="object-fit: contain;">
+          <img src="/static/logo.svg" width="32" height="32" alt="Logo" class="navbar-brand-image me-2" style="object-fit: contain;">
           <span class="nav-link-title">{{ site_name | default('DistGit') }}</span>
         </a>
       </h1>
