๐ feat: align landing page with shark design system
Changes
6 files changed, +57 -107
MODIFY
openspec/changes/add-landing-page/proposal.md
+2 -2
@@ -12,8 +12,8 @@
12
12
- "Use AI as a tool, not as a feature"
13
13
- "Focus on co-working, not lazy feeds"
14
14
- "Easy and painless to self-host"
15
-- Visual treatment: dark hero background with glowing ASCII-art branding (the shark), rendered with
16
- server-side markup + CSS only (no JS, native-image friendly).
15
+- Visual treatment: hero section with the git-shark logo and tagline, styled via the shared
16
+ `shark.css` design system (no JS, native-image friendly).
17
17
- Primary call to action: **Log in** (existing OIDC flow). Secondary: link to self-hosting docs/repo.
18
18
- Anonymous browsing of public repositories stays reachable via an explicit link (e.g. `/explore` or
19
19
a "Browse public repositories" link), so no functionality is removed.
MODIFY
openspec/changes/add-landing-page/specs/landing-page/spec.md
+7 -7
@@ -27,16 +27,16 @@
27
27
- **WHEN** an unauthenticated client requests `GET /`
28
28
- **THEN** the response body contains all three value-proposition statements
29
29
30
-### Requirement: Landing page hero with glowing ASCII-art background
30
+### Requirement: Landing page hero with branding
31
31
32
-The landing page SHALL render a dark hero section containing glowing ASCII-art branding, using
33
-only server-rendered markup and CSS (no client-side JavaScript), so it remains native-image
34
-compatible and degrades gracefully without scripting.
32
+The landing page SHALL render a hero section with the git-shark logo and tagline, using the shared
33
+`shark.css` design system (no page-level inline `<style>` block), so branding stays consistent with
34
+the rest of the UI.
35
35
36
-#### Scenario: Hero renders without JavaScript
36
+#### Scenario: Hero renders logo and shared stylesheet
37
37
38
-- **WHEN** an unauthenticated client requests `GET /` with scripting disabled
39
-- **THEN** the ASCII-art hero and its styling are present in the served HTML/CSS
38
+- **WHEN** an unauthenticated client requests `GET /`
39
+- **THEN** the response links `/shark.css`, contains the `/img/shark-logo.png` logo, and carries no inline `<style>` block
40
40
41
41
### Requirement: Landing page calls to action
42
42
MODIFY
src/main/resources/META-INF/resources/shark.css
+22 -0
@@ -154,6 +154,28 @@
154
154
color: var(--shark-fin);
155
155
}
156
156
157
+/* value list (landing page) */
158
+
159
+ul.values {
160
+ list-style: none;
161
+ padding: 0;
162
+ margin: 0 0 var(--space-5);
163
+ max-width: 44rem;
164
+}
165
+
166
+ul.values li {
167
+ padding: var(--space-3);
168
+ margin-bottom: var(--space-2);
169
+ background: var(--surface);
170
+ border: 1px solid var(--border);
171
+ border-left: 4px solid var(--shark-blue);
172
+ border-radius: var(--radius);
173
+}
174
+
175
+ul.values li strong {
176
+ color: var(--shark-deep);
177
+}
178
+
157
179
/* buttons */
158
180
159
181
.btn {
MODIFY
src/main/resources/templates/HomeResource/landing.html
+22 -96
@@ -1,99 +1,25 @@
1
-<!DOCTYPE html>
2
-<html lang="en">
3
-<head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>git-shark — self-hosted Git, AI as a tool</title>
7
- <style>
8
- :root { --glow: #38d9c8; --glow2: #1f8f86; --ink: #e6edf3; --muted: #9fb0bd; }
9
- * { box-sizing: border-box; }
10
- body {
11
- margin: 0; min-height: 100vh; color: var(--ink);
12
- font-family: system-ui, sans-serif;
13
- background: radial-gradient(1200px 600px at 50% -10%, #0c2b2a 0%, #07110f 55%, #04070a 100%);
14
- display: flex; flex-direction: column;
15
- }
16
- a { color: var(--glow); }
17
- header {
18
- display: flex; align-items: center; gap: 1rem;
19
- padding: 1rem 1.5rem;
20
- }
21
- header .brand { font-weight: 700; color: var(--ink); text-decoration: none; font-size: 1.1rem; }
22
- header nav { margin-left: auto; display: flex; gap: 1rem; align-items: center; }
23
- .btn {
24
- display: inline-block; padding: 0.55rem 1.1rem; border-radius: 8px;
25
- font-weight: 600; text-decoration: none;
26
- color: #04070a; background: var(--glow);
27
- box-shadow: 0 0 18px rgba(56, 217, 200, 0.55);
28
- }
29
- .btn.ghost { color: var(--glow); background: transparent; border: 1px solid var(--glow2); box-shadow: none; }
30
- main { flex: 1; max-width: 860px; margin: 0 auto; padding: 2rem 1.5rem 4rem; text-align: center; }
31
- .ascii-wrap { overflow-x: auto; margin: 1rem 0 2.5rem; }
32
- pre.ascii {
33
- display: inline-block; margin: 0; text-align: left;
34
- font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
35
- font-size: clamp(0.5rem, 1.6vw, 0.95rem); line-height: 1.05;
36
- color: var(--glow);
37
- text-shadow:
38
- 0 0 4px var(--glow),
39
- 0 0 10px var(--glow),
40
- 0 0 22px var(--glow2),
41
- 0 0 40px var(--glow2);
42
- }
43
- h1 { font-size: clamp(1.6rem, 4vw, 2.6rem); margin: 0 0 0.5rem; }
44
- .tagline { color: var(--muted); font-size: 1.1rem; margin: 0 auto 2.5rem; max-width: 36rem; }
45
- ul.values { list-style: none; padding: 0; margin: 0 auto 2.5rem; max-width: 40rem; text-align: left; }
46
- ul.values li {
47
- padding: 0.9rem 1.1rem; margin: 0.6rem 0; border-radius: 10px;
48
- background: rgba(56, 217, 200, 0.06); border: 1px solid rgba(56, 217, 200, 0.18);
49
- font-size: 1.05rem;
50
- }
51
- ul.values li strong { color: var(--glow); }
52
- .cta { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
53
- footer { padding: 1.5rem; text-align: center; color: var(--muted); font-size: 0.9rem; }
54
- </style>
55
-</head>
56
-<body>
57
-<header>
58
- <a class="brand" href="/">🦈 git-shark</a>
59
- <nav>
60
- <a href="/explore">Browse public repositories</a>
61
- <a class="btn" href="/login">Log in</a>
62
- </nav>
63
-</header>
64
-<main>
65
- <div class="ascii-wrap">
66
-<pre class="ascii">
67
- ,-
68
- _.-'' |
69
- _.-'' | git-shark
70
- _.-'' .-. |
71
- ,______.-'' \ o`. |
72
- / \ `.`-._
73
- | . | `-. `-._
74
- | |`. | `-. `.
75
- | | `. \ `-.`.
76
- \ \ `. `. `.`.
77
- `. `. `-. `. `|
78
- `._ `-._ `-.________`.__________/
79
- `-._ `-._______________.--''
80
- `-.________.--''
81
-</pre>
1
+{#include layout}
2
+{#title}git-shark — self-hosted Git, AI as a tool{/title}
3
+{#nav}
4
+<a href="/explore">Browse public repositories</a>
5
+<a class="btn btn-primary" href="/login">Log in</a>
6
+{/nav}
7
+<section class="hero">
8
+ <img src="/img/shark-logo.png" alt="git-shark logo">
9
+ <div>
10
+ <h1>git-shark</h1>
11
+ <p class="tagline">self-hosted git hosting for people who still write the code</p>
82
12
</div>
83
- <h1>Self-hosted Git, for people who still write the code</h1>
84
- <p class="tagline">A single natively-compiled binary. Your repositories, your server, no feed.</p>
13
+</section>
85
14
86
- <ul class="values">
87
- <li><strong>Use AI as a tool, not as a feature.</strong> It assists when you ask; it never takes the wheel.</li>
88
- <li><strong>Focus on co-working, not lazy feeds.</strong> Built for collaborating on code, not doomscrolling activity streams.</li>
89
- <li><strong>Easy and painless to self-host.</strong> One binary, Postgres, done — fast startup, tiny footprint.</li>
90
- </ul>
15
+<ul class="values">
16
+ <li><strong>Use AI as a tool, not as a feature.</strong> It assists when you ask; it never takes the wheel.</li>
17
+ <li><strong>Focus on co-working, not lazy feeds.</strong> Built for collaborating on code, not doomscrolling activity streams.</li>
18
+ <li><strong>Easy and painless to self-host.</strong> One natively-compiled binary plus Postgres — fast startup, tiny footprint.</li>
19
+</ul>
91
20
92
- <div class="cta">
93
- <a class="btn" href="/login">Log in</a>
94
- <a class="btn ghost" href="https://github.com/workaround/git-shark">Self-host it</a>
95
- </div>
96
-</main>
97
-<footer>🦈 git-shark — bare Git over HTTP & SSH, Qute UI, OIDC login.</footer>
98
-</body>
99
-</html>
21
+<p>
22
+ <a class="btn btn-primary" href="/login">Log in</a>
23
+ <a class="btn btn-secondary" href="https://github.com/workaround/git-shark">Self-host it</a>
24
+</p>
25
+{/include}
MODIFY
src/main/resources/templates/layout.html
+2 -0
@@ -12,9 +12,11 @@
12
12
<header class="site">
13
13
<a class="brand" href="/"><img src="/img/shark-logo.png" alt="git-shark logo">git-shark</a>
14
14
<nav>
15
+ {#insert nav}
15
16
<a href="/settings/keys">SSH keys</a>
16
17
<a href="/settings/tokens">Access tokens</a>
17
18
<a href="/logout">Logout</a>
19
+ {/}
18
20
</nav>
19
21
</header>
20
22
<main>
MODIFY
src/test/java/de/workaround/web/DesignSystemTest.java
+2 -2
@@ -58,12 +58,12 @@
58
58
}
59
59
60
60
@Test
61
- void landingPageShowsVisibilityBadges()
61
+ void explorePageShowsVisibilityBadges()
62
62
{
63
63
User owner = persistUser("ds-owner-" + unique());
64
64
service.create(owner, "ds-badged", Repository.Visibility.PUBLIC, "demo");
65
65
66
- given().when().get("/")
66
+ given().when().get("/explore")
67
67
.then().statusCode(200)
68
68
.body(containsString("class=\"badge"));
69
69
}