✨ feat: animated glowing ASCII backdrop on landing page
Changes
3 files changed, +136 -20
MODIFY
src/main/resources/META-INF/resources/shark.css
+95 -3
@@ -154,13 +154,105 @@
154
154
color: var(--shark-fin);
155
155
}
156
156
157
-/* value list (landing page) */
157
+/* landing page */
158
+
159
+/* animated glowing symbol backdrop — light theme, sits behind all content */
160
+.ascii-bg {
161
+ position: fixed;
162
+ inset: 0;
163
+ z-index: 0;
164
+ overflow: hidden;
165
+ pointer-events: none;
166
+ display: flex;
167
+ flex-direction: column;
168
+ justify-content: space-around;
169
+ font-family: var(--font-mono);
170
+ color: var(--shark-fin);
171
+ -webkit-user-select: none;
172
+ user-select: none;
173
+}
174
+
175
+.ascii-bg .ascii-row {
176
+ margin: 0;
177
+ border: none;
178
+ padding: 0;
179
+ background: none;
180
+ white-space: nowrap;
181
+ font-size: clamp(1.1rem, 2.6vw, 1.9rem);
182
+ letter-spacing: 0.15em;
183
+ opacity: 0.16;
184
+ animation: ascii-glow 7s ease-in-out infinite, ascii-drift 48s linear infinite alternate;
185
+ will-change: transform, opacity, text-shadow;
186
+}
187
+
188
+.ascii-bg .ascii-row:nth-child(2) { animation-delay: -1.4s, -6s; font-size: clamp(1rem, 2.2vw, 1.6rem); }
189
+.ascii-bg .ascii-row:nth-child(3) { animation-delay: -2.8s, -12s; }
190
+.ascii-bg .ascii-row:nth-child(4) { animation-delay: -4.2s, -18s; font-size: clamp(1rem, 2.2vw, 1.6rem); }
191
+.ascii-bg .ascii-row:nth-child(5) { animation-delay: -5.6s, -24s; }
192
+.ascii-bg .ascii-row:nth-child(6) { animation-delay: -7s, -30s; font-size: clamp(1rem, 2.2vw, 1.6rem); }
193
+
194
+@keyframes ascii-glow {
195
+ 0%, 100% { opacity: 0.08; text-shadow: 0 0 4px var(--shark-fin); }
196
+ 50% { opacity: 0.30; text-shadow: 0 0 10px var(--shark-blue), 0 0 22px var(--shark-fin); }
197
+}
198
+
199
+@keyframes ascii-drift {
200
+ from { transform: translateX(0); }
201
+ to { transform: translateX(-14%); }
202
+}
203
+
204
+@media (prefers-reduced-motion: reduce) {
205
+ .ascii-bg .ascii-row { animation: none; opacity: 0.12; }
206
+}
207
+
208
+/* keep header and content above the backdrop */
209
+header.site, main { position: relative; z-index: 1; }
210
+
211
+/* centered hero distinct from the in-app repo hero */
212
+.landing {
213
+ text-align: center;
214
+ max-width: 44rem;
215
+ margin: var(--space-5) auto 0;
216
+}
217
+
218
+.landing .landing-logo {
219
+ width: 120px;
220
+ height: 120px;
221
+ border-radius: 50%;
222
+ border: 2px solid var(--shark-fin);
223
+ box-shadow: 0 0 0 6px rgba(79, 159, 224, 0.12), 0 0 24px rgba(21, 101, 192, 0.25);
224
+}
225
+
226
+.landing h1 {
227
+ font-family: var(--font-mono);
228
+ font-size: 2.2rem;
229
+ margin: var(--space-3) 0 var(--space-1);
230
+}
231
+
232
+.landing .tagline {
233
+ font-family: var(--font-mono);
234
+ color: var(--ink-muted);
235
+ margin: 0 0 var(--space-5);
236
+}
237
+
238
+.landing .tagline::before {
239
+ content: "$ ";
240
+ color: var(--shark-fin);
241
+}
242
+
243
+.landing-cta {
244
+ display: flex;
245
+ gap: var(--space-3);
246
+ justify-content: center;
247
+ flex-wrap: wrap;
248
+}
158
249
159
250
ul.values {
160
251
list-style: none;
161
252
padding: 0;
162
- margin: 0 0 var(--space-5);
163
- max-width: 44rem;
253
+ margin: 0 auto var(--space-5);
254
+ max-width: 40rem;
255
+ text-align: left;
164
256
}
165
257
166
258
ul.values li {
MODIFY
src/main/resources/templates/HomeResource/landing.html
+23 -17
@@ -4,22 +4,28 @@
4
4
<a href="/explore">Browse public repositories</a>
5
5
<a class="btn btn-primary" href="/login">Log in</a>
6
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>
12
- </div>
7
+<div class="ascii-bg" aria-hidden="true">
8
+<pre class="ascii-row"></> git commit -m "ship it" ~ <shark> { main } /push fetch\ >>= 0xC0DE ;; </> merge --no-ff ~~~ >_</pre>
9
+<pre class="ascii-row">~ >_ HEAD~1 ::= clone <origin> { } /\/\ rebase -i ~ 0101 <shark/> pull --ff-only ;; >>= </></pre>
10
+<pre class="ascii-row">{ } <branch> /\ tag -s v1.0 ~ >_ stash@{0} 0xFEED </> cherry-pick ;; ~~~ push --tags >>=</pre>
11
+<pre class="ascii-row">>>= /push <shark> ~ blame -L { HEAD } 0x5HARK reflog ;; </> bisect ~~~ >_ fsck --full /\</pre>
12
+<pre class="ascii-row">~ </> reset --hard ;; { } /\/\ 1100 >_ remote -v <origin/> ~ diff --stat 0xBEEF push >>=</pre>
13
+<pre class="ascii-row">{ main } ~ >_ log --oneline /\ <shark> ;; switch -c ~~~ 0x1337 </> worktree add >>= /push</pre>
14
+</div>
15
+<section class="landing">
16
+ <img class="landing-logo" src="/img/shark-logo.png" alt="git-shark logo">
17
+ <h1>git-shark</h1>
18
+ <p class="tagline">self-hosted git hosting for people who still write the code</p>
19
+
20
+ <ul class="values">
21
+ <li><strong>Use AI as a tool, not as a feature.</strong> It assists when you ask; it never takes the wheel.</li>
22
+ <li><strong>Focus on co-working, not lazy feeds.</strong> Built for collaborating on code, not doomscrolling activity streams.</li>
23
+ <li><strong>Easy and painless to self-host.</strong> One natively-compiled binary plus Postgres — fast startup, tiny footprint.</li>
24
+ </ul>
25
+
26
+ <p class="landing-cta">
27
+ <a class="btn btn-primary" href="/login">Log in</a>
28
+ <a class="btn btn-secondary" href="https://github.com/workaround/git-shark">Self-host it</a>
29
+ </p>
13
30
</section>
14
-
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>
20
-
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
31
{/include}
MODIFY
src/test/java/de/workaround/web/WebUiTest.java
+18 -0
@@ -57,6 +57,24 @@
57
57
}
58
58
59
59
@Test
60
+ void landingPageHasAnimatedAsciiBackground() throws Exception
61
+ {
62
+ // background symbol layer is present in the markup...
63
+ given()
64
+ .when().get("/")
65
+ .then()
66
+ .statusCode(200)
67
+ .body(containsString("class=\"ascii-bg\""));
68
+
69
+ // ...and the animation is defined in the shared stylesheet (no inline <style> on /)
70
+ given()
71
+ .when().get("/shark.css")
72
+ .then()
73
+ .statusCode(200)
74
+ .body(containsString("@keyframes ascii-glow"));
75
+ }
76
+
77
+ @Test
60
78
@TestSecurity(user = "ui-alice")
61
79
void ownerSeesOwnPrivateRepositoryOnHome() throws Exception
62
80
{