Add Hop logo and an explanatory public landing page

Hop-State: A_06FN4GBGQFKPXH5B5MK4P0R
Hop-Proposal: R_06FN4GAZCEER9W65XJTCVJG
Hop-Task: T_06FN4FT3436TX5AV35QM4RR
Hop-Attempt: AT_06FN4FT3401X9BHCJVKT52G
This commit is contained in:
Hop
2026-07-11 10:37:28 -07:00
parent 8115847b32
commit ae2ffae36d
7 changed files with 122 additions and 10 deletions
+10 -1
View File
@@ -10,13 +10,22 @@ fi
docker compose --env-file "$env_file" up -d gitea
docker compose --env-file "$env_file" exec -T -u root gitea \
mkdir -p /data/gitea/templates/custom /data/gitea/public/assets/js
mkdir -p /data/gitea/templates/custom /data/gitea/public/assets/js /data/gitea/public/assets/css /data/gitea/public/assets/img
docker compose --env-file "$env_file" cp \
deploy/gitea/templates/home.tmpl \
gitea:/data/gitea/templates/home.tmpl
docker compose --env-file "$env_file" cp \
deploy/gitea/templates/custom/footer.tmpl \
gitea:/data/gitea/templates/custom/footer.tmpl
docker compose --env-file "$env_file" cp \
deploy/gitea/public/assets/js/hop-native.js \
gitea:/data/gitea/public/assets/js/hop-native.js
docker compose --env-file "$env_file" cp \
deploy/gitea/public/assets/css/hop-home.css \
gitea:/data/gitea/public/assets/css/hop-home.css
docker compose --env-file "$env_file" cp \
deploy/gitea/public/assets/img/hop.svg \
gitea:/data/gitea/public/assets/img/hop.svg
docker compose --env-file "$env_file" exec -T -u root gitea \
chown -R git:git /data/gitea/templates /data/gitea/public
docker compose --env-file "$env_file" exec -T -u git \
@@ -0,0 +1,32 @@
.hop-home { max-width: 1120px; margin: 0 auto; padding: 5.5rem 2rem 4rem; }
.hop-home h1, .hop-home h2, .hop-home h3 { color: var(--color-text); letter-spacing: -0.035em; }
.hop-home p { color: var(--color-text-light-2); line-height: 1.65; }
.hop-eyebrow { color: var(--color-primary) !important; font-size: .78rem; font-weight: 700; letter-spacing: .13em; margin: 0 0 1rem; text-transform: uppercase; }
.hop-hero { align-items: center; display: grid; gap: 5rem; grid-template-columns: 1.25fr .75fr; min-height: 390px; }
.hop-hero h1 { font-size: clamp(2.75rem, 6vw, 4.8rem); line-height: 1.02; margin: 0; max-width: 750px; }
.hop-lede { font-size: 1.18rem; margin: 1.5rem 0 2rem; max-width: 650px; }
.hop-actions { display: flex; flex-wrap: wrap; gap: .75rem; }
.hop-actions .button, .hop-closing .button { margin: 0; }
.hop-hero-mark { display: grid; justify-items: center; position: relative; }
.hop-hero-mark img { filter: drop-shadow(0 18px 24px color-mix(in srgb, var(--color-primary) 22%, transparent)); width: min(100%, 220px); }
.hop-state-card { align-items: center; background: var(--color-box-body); border: 1px solid var(--color-secondary); border-radius: 8px; box-shadow: 0 12px 28px rgba(0,0,0,.12); color: var(--color-text); display: flex; font-size: .85rem; gap: .55rem; margin-top: -1rem; padding: .72rem .9rem; position: relative; }
.hop-state-dot { background: #2da44e; border-radius: 50%; height: .55rem; width: .55rem; }
.hop-intro { border-top: 1px solid var(--color-secondary); margin-top: 4.5rem; max-width: 780px; padding-top: 4.5rem; }
.hop-intro h2, .hop-flow h2, .hop-closing h2 { font-size: clamp(2rem, 3.5vw, 3rem); line-height: 1.12; margin: 0 0 1.1rem; }
.hop-intro p { font-size: 1.12rem; }
.hop-benefits { display: grid; gap: 1px; grid-template-columns: repeat(3, 1fr); margin: 5rem 0; background: var(--color-secondary); border: 1px solid var(--color-secondary); }
.hop-benefits article { background: var(--color-box-body); padding: 2rem; }
.hop-number { color: var(--color-primary); font-size: .82rem; font-weight: 700; letter-spacing: .1em; }
.hop-benefits h2 { font-size: 1.35rem; margin: 3.5rem 0 .8rem; }
.hop-benefits p { font-size: .97rem; margin: 0; }
.hop-flow { display: grid; gap: 4rem; grid-template-columns: .8fr 1.2fr; padding: 2rem 0 5rem; }
.hop-flow h2 { font-size: 2.3rem; }
.hop-flow ol { border-left: 1px solid var(--color-secondary); list-style: none; margin: 0; padding: 0 0 0 2rem; }
.hop-flow li { display: grid; gap: 1rem; grid-template-columns: 2rem 1fr; margin: 0 0 2rem; position: relative; }
.hop-flow li:last-child { margin-bottom: 0; }
.hop-flow li > span { align-items: center; background: var(--color-box-body); border: 1px solid var(--color-primary); border-radius: 50%; color: var(--color-primary); display: flex; font-size: .8rem; font-weight: 700; height: 2rem; justify-content: center; margin-left: -3.05rem; }
.hop-flow h3 { font-size: 1.12rem; margin: .25rem 0 .3rem; }
.hop-flow li p { margin: 0; }
.hop-closing { align-items: center; background: color-mix(in srgb, var(--color-primary) 9%, var(--color-box-body)); border: 1px solid color-mix(in srgb, var(--color-primary) 32%, var(--color-secondary)); display: flex; justify-content: space-between; gap: 2rem; padding: 2.5rem; }
.hop-closing h2 { font-size: 2rem; margin-bottom: 0; max-width: 540px; }
@media (max-width: 760px) { .hop-home { padding: 3.5rem 1.25rem; } .hop-hero, .hop-flow { gap: 2.5rem; grid-template-columns: 1fr; } .hop-hero-mark { justify-items: start; } .hop-hero-mark img { width: 145px; } .hop-benefits { grid-template-columns: 1fr; } .hop-benefits h2 { margin-top: 1.5rem; } .hop-closing { align-items: flex-start; flex-direction: column; } }
+4
View File
@@ -0,0 +1,4 @@
+Exit code: 0
Wall time: 0 seconds
Output:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180" fill="none" shape-rendering="auto" aria-hidden="true" width="512" height="512"><!-- Generated by DiceBear (https://dicebear.com) --><metadata xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/"><rdf:RDF><rdf:Description><dc:title>Bottts</dc:title><dc:creator>Pablo Stanley</dc:creator><dc:source xsi:type="dcterms:URI">https://bottts.com/</dc:source><dcterms:license xsi:type="dcterms:URI">https://bottts.com/</dcterms:license><dc:rights>Remix of “Bottts” (https://bottts.com/) by “Pablo Stanley”, licensed under “Free for personal and commercial use” (https://bottts.com/)</dc:rights></rdf:Description></rdf:RDF></metadata><defs><g id="sides-antenna01-b3dae8fb"><mask id="sidesAntenna01-a" style="mask-type:luminance"><rect y="31" width="36" height="14" rx="4" fill="white"/><rect x="12" y="14" width="36" height="48" rx="4" fill="white"/><rect x="120" y="28" width="36" height="24" rx="4" fill="white"/><rect x="5" y="11" width="2" height="20" fill="white"/></mask><g mask="url(#sidesAntenna01-a)"><path d="M-6 0h180v76H-6z" fill="#9975ea"/><rect x="-6" width="180" height="76" fill="white" fill-opacity=".3"/><rect x="-6" y="38" width="180" height="38" fill="black" fill-opacity=".1"/></g><rect x="5" y="11" width="2" height="20" fill="white" fill-opacity=".4"/><circle cx="6" cy="8" r="4" fill="#FFEA8F"/><circle cx="7" cy="7" r="2" fill="white"/></g><g id="top-antennaCrooked-b3dae8fb"><mask id="topAntennaCrooked-a" style="mask-type:luminance"><path d="M47.54 34.98 43 45.59h-3.74l4.92-10.43-6.05-10.43 3.22-11.84 2.9.8-2.9 10.6z" fill="white"/><rect x="30" y="39.59" width="24" height="13" fill="white"/></mask><g mask="url(#topAntennaCrooked-a)"><path d="M-8 .6H92v52H-8z" fill="#9975ea"/><path d="M-8 6.6H92v52H-8z" fill="white" fill-opacity=".3"/><rect x="30" y="39.59" width="24" height="13" fill="white" fill-opacity=".2"/></g><circle cx="42" cy="8.59" r="8" fill="#FFE65C"/><circle cx="45" cy="5.59" r="3" fill="white"/></g><g id="texture-circuits-b3dae8fb"><path d="M66 36h49.42a5 5 0 1 1 0 4H62V6h4zm-8-12h-4V6h4z" fill="black" fill-opacity=".1"/><path d="M163 31a5 5 0 0 1 2 9.58V66h19v4h-23V40.58a5 5 0 0 1 2-9.58" fill="white" fill-opacity=".2"/><path d="M157 74h27v4h-31V52h4zm-85 26a5 5 0 0 0-2 9.58V135H51v4h23v-29.42a5 5 0 0 0-2-9.58" fill="black" fill-opacity=".2"/></g><g id="head-round02-b3dae8fb"><mask id="headRound02-a" style="mask-type:luminance"><path fill-rule="evenodd" clip-rule="evenodd" d="M0 31v-1c.18-.48.4-1.5 1-3 .83-3.06 2.78-6.56 6-10C16.7 6.6 35.17 0 65 0s48.3 6.6 58 17c3.22 3.44 5.17 6.94 6 10 .6 1.5.82 2.52 1 3v40c0-.1-.03.5 0 1a54 54 0 0 1-1 6c-1.19 6-3.4 11.91-7 17-9.72 16.34-27.74 26-57 26s-47.28-9.66-57-26c-3.6-5.1-5.8-11-7-17a54 54 0 0 1-1-6c.03-.45 0-1.32 0-1z" fill="white"/></mask><g mask="url(#headRound02-a)"><path d="M-4-2h138v124H-4z" fill="#9975ea"/><use transform="translate(-44 -7)" href="#texture-circuits-b3dae8fb"/></g></g><g id="mouth-smile01-b3dae8fb"><path d="M23.05 4.44a2 2 0 1 1 3.9-.88C27.72 6.96 30.4 9 34 9s6.28-2.04 7.05-5.44a2 2 0 1 1 3.9.88C43.75 9.7 39.43 13 34 13s-9.76-3.3-10.95-8.56" fill="black" fill-opacity=".6"/></g><g id="eyes-frame1-b3dae8fb"><rect y="4" width="104" height="42" rx="4" fill="black" fill-opacity=".8"/><rect x="28" y="25" width="10" height="11" rx="2" fill="#8BDDFF"/><rect x="66" y="25" width="10" height="11" rx="2" fill="#8BDDFF"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 4h8L12 46H4z" fill="white" fill-opacity=".4"/></g><clipPath id="clip-b3dae8fb"><rect width="180" height="180" rx="0" ry="0"/></clipPath></defs><g clip-path="url(#clip-b3dae8fb)"><use transform="translate(6 66)" href="#sides-antenna01-b3dae8fb"/><use transform="translate(49 -.6)" href="#top-antennaCrooked-b3dae8fb"/><use transform="translate(25 44)" href="#head-round02-b3dae8fb"/><use transform="translate(56 128)" href="#mouth-smile01-b3dae8fb"/><use transform="translate(38 76)" href="#eyes-frame1-b3dae8fb"/></g></svg>
@@ -141,6 +141,8 @@
}
function applyHopSemantics() {
const brandLogo = document.querySelector('#navbar-logo img');
if (brandLogo) brandLogo.src = brandLogo.src.replace('/img/logo.svg', '/assets/img/hop.svg');
for (const root of document.querySelectorAll(semanticRoots)) replaceExactText(root);
replaceAccessibleLabels(document);
addWorkflowSummary();
+2 -2
View File
@@ -1,2 +1,2 @@
<script src="{{AssetUrlPrefix}}/js/hop-native.js?v=1"></script>
<link rel="stylesheet" href="{{AssetUrlPrefix}}/assets/css/hop-home.css?v=1">
<script src="{{AssetUrlPrefix}}/assets/js/hop-native.js?v=2"></script>
+66
View File
@@ -0,0 +1,66 @@
{{template "base/head" .}}
<main role="main" aria-label="Hop — prompt-native software development" class="page-content hop-home">
<section class="hop-hero">
<div class="hop-hero-copy">
<p class="hop-eyebrow">The prompt-native forge</p>
<h1>Turn a clear outcome into accepted, verified work.</h1>
<p class="hop-lede">Hop gives people and AI agents one shared workflow for building software: state the goal, run isolated attempts, review the evidence, and accept the result.</p>
<div class="hop-actions">
{{if .IsSigned}}
<a class="ui primary button" href="{{AppSubUrl}}/repo/create">Create a repository</a>
<a class="ui basic button" href="{{AppSubUrl}}/explore/repos">Explore work</a>
{{else}}
<a class="ui primary button" href="{{AppSubUrl}}/user/sign_up">Get started</a>
<a class="ui basic button" href="#how-it-works">See how it works</a>
{{end}}
</div>
</div>
<div class="hop-hero-mark" aria-hidden="true">
<img src="{{AssetUrlPrefix}}/assets/img/hop.svg" width="180" height="180" alt="">
<div class="hop-state-card"><span class="hop-state-dot"></span><span>Outcome ready for review</span></div>
</div>
</section>
<section class="hop-intro" aria-labelledby="hop-intro-title">
<p class="hop-eyebrow">A better unit of collaboration</p>
<h2 id="hop-intro-title">Software work begins with intent, not a branch.</h2>
<p>Git remains the durable home for your files. Hop makes the work around those files legible: what was asked for, who attempted it, what was checked, and which outcome became shared truth.</p>
</section>
<section class="hop-benefits" aria-label="Why use Hop">
<article>
<div class="hop-number">01</div>
<h2>Keep the why attached</h2>
<p>Each task starts with the requested outcome and retains its causal context, so nobody has to reconstruct intent from a terminal history.</p>
</article>
<article>
<div class="hop-number">02</div>
<h2>Try work without collisions</h2>
<p>Human and agent attempts run in isolated workspaces. Compare different approaches without putting your main line at risk.</p>
</article>
<article>
<div class="hop-number">03</div>
<h2>Review proof, not promises</h2>
<p>Checks are bound to immutable checkpoints, making it clear exactly what was verified before a proposal is accepted.</p>
</article>
</section>
<section class="hop-flow" id="how-it-works" aria-labelledby="how-it-works-title">
<div class="hop-flow-heading">
<p class="hop-eyebrow">How Hop works</p>
<h2 id="how-it-works-title">A calm, visible path from request to shared truth.</h2>
</div>
<ol>
<li><span>1</span><div><h3>Open a task</h3><p>Describe the outcome you need in plain language.</p></div></li>
<li><span>2</span><div><h3>Launch an attempt</h3><p>Work yourself, direct an agent, or run both approaches side by side.</p></div></li>
<li><span>3</span><div><h3>Inspect the evidence</h3><p>Review diffs, checkpoints, and the checks attached to them.</p></div></li>
<li><span>4</span><div><h3>Accept the outcome</h3><p>Choose the verified proposal that should become the shared state.</p></div></li>
</ol>
</section>
<section class="hop-closing">
<div><p class="hop-eyebrow">Ready when you are</p><h2>Build with agents without losing the thread.</h2></div>
{{if .IsSigned}}<a class="ui primary button" href="{{AppSubUrl}}/repo/create">Start a repository</a>{{else}}<a class="ui primary button" href="{{AppSubUrl}}/user/sign_up">Create your account</a>{{end}}
</section>
</main>
{{template "base/footer" .}}
+6 -7
View File
@@ -1,8 +1,7 @@
# Hop-native Gitea semantics
HopWeb keeps Gitea's existing interface design and changes the meaning of its
collaboration elements. No custom stylesheet, theme, component library, or
layout override is installed.
HopWeb keeps Gitea's existing forge interface and adds a Hop-specific public
home page, brand mark, and semantic vocabulary for collaboration elements.
## Install
@@ -18,9 +17,10 @@ Set `ENV_FILE` when the Compose environment is stored elsewhere:
ENV_FILE=/path/to/environment ./deploy/gitea/install-hop-native.sh
```
The installer copies the adapter into Gitea's persistent custom directory,
sets the application name to `Hop`, restarts Gitea, and waits for a healthy
response. Re-run it after editing the adapter or replacing the Gitea volume.
The installer copies the home page, brand mark, styles, and adapter into
Gitea's persistent custom directory, sets the application name to `Hop`,
restarts Gitea, and waits for a healthy response. Re-run it after editing an
asset or replacing the Gitea volume.
## Semantic mapping
@@ -52,4 +52,3 @@ After changing the pinned Gitea version:
4. confirm proposal creation and acceptance labels;
5. inspect browser console errors; and
6. test a narrow viewport and keyboard navigation.