A tiny read-only git web frontend — browse bare repos with just PHP and git, no database, no framework.
<?php
/** @var string $title @var string $theme @var ?string $repoName
* @var ?string $tab which nav tab is current ('log'/'refs'/'tree'), null for no tab bar
* @var string $description repo_description($repo), or SITE_DESCRIPTION on the repo
* index; '' hides the about box either way
* Owns the whole page shell — header, tab bar and the opening <main> — so the
* full-width bars and the centred column stay in one place. foot.php closes it. */
$altTheme = theme_counterpart($theme);
$tab = $tab ?? null;
$description = $description ?? '';
?>
<!doctype html>
<html lang="en"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= h($title) ?></title>
<link rel="stylesheet" href="<?= h(asset_url('themes/' . $theme . '.css')) ?>">
<link rel="stylesheet" href="<?= h(asset_url('assets/base.css')) ?>">
</head><body>
<header>
<div class="inner">
<a class="brand" href="?">
<svg class="icon" width="20" height="20" viewBox="0 0 16 16" aria-hidden="true"><path d="M11.28 6.78a.75.75 0 0 0-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 0 0-1.06 1.06l2 2a.75.75 0 0 0 1.06 0l3.5-3.5Z"></path><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13Z"></path></svg>
<?= h(SITE_NAME) ?>
</a>
<?php if ($repoName): ?>
<span class="path">
/ <svg class="icon" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path></svg>
<a href="?r=<?= h($repoName) ?>"><?= h(repo_display_name($repoName)) ?></a>
</span>
<?php endif; ?>
<span class="spacer"></span>
<?php if ($altTheme !== null): ?>
<a class="icon-btn" href="<?= h(current_query(['theme' => $altTheme])) ?>"
title="<?= theme_is_dark($theme) ? 'Byt till ljust tema' : 'Byt till mörkt tema' ?>"
aria-label="<?= theme_is_dark($theme) ? 'Byt till ljust tema' : 'Byt till mörkt tema' ?>">
<?php if (theme_is_dark($theme)): ?>
<svg class="icon" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 12a4 4 0 1 1 0-8 4 4 0 0 1 0 8Zm0-1.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Zm5.657-8.157a.75.75 0 0 1 0 1.06l-1.061 1.062a.75.75 0 0 1-1.06-1.06l1.06-1.062a.75.75 0 0 1 1.06 0Zm-9.193 9.193a.75.75 0 0 1 0 1.06L3.11 13.72a.75.75 0 1 1-1.06-1.06l1.06-1.06a.75.75 0 0 1 1.06 0ZM8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0ZM3 8a.75.75 0 0 1-.75.75H.75a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 3 8Zm13 0a.75.75 0 0 1-.75.75h-1.5a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 16 8Zm-8 5a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13Zm-3.536-9.193a.75.75 0 0 1-1.06 0L2.343 2.747a.75.75 0 1 1 1.06-1.06l1.06 1.06a.75.75 0 0 1 0 1.06Zm9.193 9.193a.75.75 0 0 1-1.06 0l-1.061-1.06a.75.75 0 0 1 1.06-1.06l1.06 1.06a.75.75 0 0 1 0 1.06Z"></path></svg>
<?php else: ?>
<svg class="icon" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M9.598 1.591a.749.749 0 0 1 .785-.175 7.001 7.001 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786Zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.499 5.499 0 1 0 7.678-7.678Z"></path></svg>
<?php endif; ?>
</a>
<?php endif; ?>
<a class="icon-btn" href="?a=help" title="Help" aria-label="Help">
<svg class="icon" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.92 6.085a.749.749 0 1 1-1.342-.67c.169-.339.436-.701.849-.977C6.845 4.16 7.369 4 8 4c.73 0 1.334.192 1.752.545.416.353.65.822.667 1.328.033.988-.65 1.606-1.166 2.02l-.147.117c-.363.288-.573.485-.573.86v.007a.75.75 0 0 1-1.5-.037c.03-.673.457-1.109.877-1.454l.087-.07c.529-.421.867-.723.85-1.132-.007-.174-.09-.375-.323-.564-.234-.19-.575-.32-1.024-.32-.44 0-.77.12-.996.26a1.28 1.28 0 0 0-.481.523ZM8 12a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"></path></svg>
</a>
<?php if (is_logged_in()): ?>
<span class="nav-auth">
<a class="nav-btn" href="?a=account" title="Your account and API keys">
<svg class="icon" width="14" height="14" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="4.5" r="2.75"></circle><path d="M8 8.75c-3.02 0-5.5 2.02-5.5 4.5 0 .41.34.75.75.75h9.5c.41 0 .75-.34.75-.75 0-2.48-2.48-4.5-5.5-4.5Z"></path></svg>
<span class="label"><?= h((string) current_username()) ?></span>
</a>
<?php if (is_admin()): ?>
<span class="nav-sep"></span>
<a class="nav-btn" href="?a=admin" title="Manage repos and accounts">Admin</a>
<?php endif; ?>
<span class="nav-sep"></span>
<form method="post" action="?a=logout">
<input type="hidden" name="csrf" value="<?= h(csrf_token()) ?>">
<button type="submit" class="nav-btn" title="Log out">
<svg class="icon" width="14" height="14" viewBox="0 0 16 16" aria-hidden="true"><path d="M6.5 2.25a.75.75 0 0 0-.75-.75h-2A1.75 1.75 0 0 0 2 3.25v9.5c0 .966.784 1.75 1.75 1.75h2a.75.75 0 0 0 0-1.5h-2a.25.25 0 0 1-.25-.25v-9.5A.25.25 0 0 1 3.75 3h2a.75.75 0 0 0 .75-.75Z"></path><path d="M10.44 4.72a.75.75 0 0 1 1.06 0l2.75 2.75a.75.75 0 0 1 0 1.06l-2.75 2.75a.75.75 0 1 1-1.06-1.06l1.47-1.47H6.75a.75.75 0 0 1 0-1.5h5.16l-1.47-1.47a.75.75 0 0 1 0-1.06Z"></path></svg>
<span class="label">Log out</span>
</button>
</form>
</span>
<?php else: ?>
<span class="nav-auth">
<a class="nav-btn" href="?a=login">Log in</a>
</span>
<?php endif; ?>
</div>
</header>
<?php if ($tab !== null && $repoName !== null) render('partials/tabs', ['repoName' => $repoName, 'cur' => $tab]); ?>
<main><div class="inner">
<?php if ($description !== ''): ?>
<div class="box about"><?= h($description) ?></div>
<?php endif; ?>