Skip to content

Commit 8fbbb53

Browse files
committed
feat: macos esque page
1 parent 00997f0 commit 8fbbb53

9 files changed

Lines changed: 1667 additions & 426 deletions

File tree

.astro/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
{
22
"_variables": {
33
"lastUpdateCheck": 1749377719288
4+
},
5+
"devToolbar": {
6+
"enabled": false
47
}
58
}

src/layouts/BaseLayout.astro

Lines changed: 810 additions & 48 deletions
Large diffs are not rendered by default.

src/pages/about.astro

Lines changed: 230 additions & 61 deletions
Large diffs are not rendered by default.

src/pages/blog.astro

Lines changed: 89 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,95 @@ const sortedPosts = posts.sort((a, b) =>
1010
---
1111

1212
<BaseLayout title="Blog - Johan Wulf">
13-
<h1 class="text-2xl font-normal mb-8">Blog</h1>
14-
<div class="space-y-6">
15-
{sortedPosts.map((post) => (
16-
<article class="pb-6 border-b border-surface-0 last:border-0">
17-
<a href={`/blog/${post.slug}`} class="group block">
18-
<h2 class="text-lg text-text group-hover:text-blue mb-2">
19-
{post.data.title}
20-
</h2>
21-
{post.data.description && (
22-
<p class="text-overlay-0 text-sm mb-2">
23-
{post.data.description}
24-
</p>
25-
)}
26-
<div class="flex items-center gap-4 text-xs text-overlay-0">
27-
<span>{formatDate(post.data.date)}</span>
28-
<span>·</span>
29-
<span>{getReadingTime(post)}</span>
30-
{post.data.tags && post.data.tags.length > 0 && (
31-
<>
32-
<span>·</span>
33-
<div class="flex gap-2">
34-
{post.data.tags.map(tag => (
35-
<span class="px-2 py-1 bg-surface-0 text-overlay-1 rounded">
36-
#{tag}
37-
</span>
38-
))}
13+
<!-- Hero Section -->
14+
<section class="apple-section-large bg-gradient-to-b from-green-50 to-white">
15+
<div class="apple-container text-center">
16+
<h1 class="apple-title mb-6">Blog</h1>
17+
<p class="apple-subtitle max-w-3xl mx-auto">
18+
Thoughts, insights, and learnings from my journey in software engineering and technology.
19+
</p>
20+
</div>
21+
</section>
22+
23+
<!-- Posts Section -->
24+
<section class="apple-section bg-white">
25+
<div class="apple-container">
26+
<div class="max-w-4xl mx-auto space-y-8">
27+
{sortedPosts.map((post) => (
28+
<article class="apple-card apple-card-hover">
29+
<a href={`/blog/${post.slug}`} class="block p-8 apple-transition">
30+
<div class="flex flex-col lg:flex-row lg:items-center lg:justify-between">
31+
<div class="flex-1">
32+
<h2 class="text-2xl font-semibold text-gray-900 mb-3 hover:text-blue-600 apple-transition">
33+
{post.data.title}
34+
</h2>
35+
{post.data.description && (
36+
<p class="apple-body mb-4">
37+
{post.data.description}
38+
</p>
39+
)}
40+
<div class="flex items-center space-x-4 apple-caption mb-4">
41+
<time datetime={post.data.date.toISOString()}>
42+
{formatDate(post.data.date)}
43+
</time>
44+
<span>•</span>
45+
<span>{getReadingTime(post)}</span>
46+
</div>
47+
{post.data.tags && post.data.tags.length > 0 && (
48+
<div class="flex flex-wrap gap-2">
49+
{post.data.tags.map(tag => (
50+
<span class="apple-badge-gray">
51+
{tag}
52+
</span>
53+
))}
54+
</div>
55+
)}
56+
</div>
57+
<div class="mt-6 lg:mt-0 lg:ml-8 flex-shrink-0">
58+
<div class="inline-flex items-center text-blue-600 font-medium">
59+
Read More
60+
<svg class="ml-2 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
61+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"/>
62+
</svg>
63+
</div>
3964
</div>
40-
</>
41-
)}
65+
</div>
66+
</a>
67+
</article>
68+
))}
69+
</div>
70+
71+
{sortedPosts.length === 0 && (
72+
<div class="text-center py-12">
73+
<div class="w-16 h-16 bg-gray-100 rounded-2xl mx-auto mb-6 flex items-center justify-center">
74+
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
75+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
76+
</svg>
4277
</div>
78+
<h3 class="text-xl font-semibold text-gray-900 mb-2">No posts yet</h3>
79+
<p class="apple-body">Check back soon for new content!</p>
80+
</div>
81+
)}
82+
</div>
83+
</section>
84+
85+
<!-- Newsletter Section -->
86+
<section class="apple-section bg-gray-50">
87+
<div class="apple-container">
88+
<div class="max-w-2xl mx-auto text-center">
89+
<div class="w-16 h-16 bg-gradient-to-br from-blue-400 to-purple-500 rounded-2xl mx-auto mb-6 flex items-center justify-center">
90+
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
91+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
92+
</svg>
93+
</div>
94+
<h2 class="apple-headline mb-4">Stay Updated</h2>
95+
<p class="apple-subtitle mb-8">
96+
Get notified when I publish new articles about software engineering, technology, and design.
97+
</p>
98+
<a href="mailto:johan@wulf.gg?subject=Newsletter Subscription" class="apple-button">
99+
Subscribe via Email
43100
</a>
44-
</article>
45-
))}
46-
</div>
47-
</BaseLayout>
101+
</div>
102+
</div>
103+
</section>
104+
</BaseLayout>

src/pages/blog/[slug].astro

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,36 @@ const { Content } = await post.render()
1717

1818
<BaseLayout title={`${post.data.title} - Johan Wulf`}>
1919
<article>
20-
<div class="mb-12">
21-
<h1 class="text-3xl font-normal text-text mb-4">{post.data.title}</h1>
22-
<div class="flex items-center gap-4 text-sm text-overlay-0 mb-6">
20+
<div class="mb-12 glass-card">
21+
<h1 class="text-3xl font-bold text-glass mb-4">{post.data.title}</h1>
22+
<div class="flex items-center gap-4 text-sm text-glass-dim mb-6">
2323
<span>{formatDate(post.data.date)}</span>
2424
<span>·</span>
2525
<span>{getReadingTime(post)}</span>
2626
</div>
27-
<div class="flex flex-wrap gap-2 mb-8">
27+
<div class="flex flex-wrap gap-2">
2828
{post.data.tags.map(tag => (
29-
<span class="text-xs px-3 py-1 bg-surface-0 text-overlay-1 rounded">
29+
<span class="text-xs px-3 py-1 glass text-white/70 rounded-lg">
3030
#{tag}
3131
</span>
3232
))}
3333
</div>
3434
</div>
3535

36-
<div class="prose prose-invert max-w-none
37-
prose-headings:font-normal
38-
prose-h1:text-3xl prose-h1:text-text prose-h1:mt-8 prose-h1:mb-4
39-
prose-h2:text-2xl prose-h2:text-blue prose-h2:mt-6 prose-h2:mb-3
40-
prose-h3:text-xl prose-h3:text-text prose-h3:mt-4 prose-h3:mb-2
41-
prose-p:text-text prose-p:mb-4 prose-p:leading-relaxed
42-
prose-a:text-blue hover:prose-a:underline
43-
prose-blockquote:border-l-4 prose-blockquote:border-blue prose-blockquote:pl-4 prose-blockquote:text-overlay-1
44-
prose-code:bg-surface-0 prose-code:text-peach prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm
45-
prose-pre:bg-surface-0 prose-pre:rounded-lg prose-pre:p-4
46-
prose-strong:text-text prose-strong:font-bold
36+
<div class="prose prose-invert max-w-none glass-card
37+
prose-headings:font-semibold
38+
prose-h1:text-3xl prose-h1:text-glass prose-h1:mt-8 prose-h1:mb-4
39+
prose-h2:text-2xl prose-h2:text-blue-400 prose-h2:mt-6 prose-h2:mb-3 prose-h2:text-glow
40+
prose-h3:text-xl prose-h3:text-glass prose-h3:mt-4 prose-h3:mb-2
41+
prose-p:text-glass prose-p:mb-4 prose-p:leading-relaxed
42+
prose-a:text-blue-400 hover:prose-a:text-blue-300 hover:prose-a:transition-colors
43+
prose-blockquote:border-l-4 prose-blockquote:border-blue-400/50 prose-blockquote:pl-4 prose-blockquote:text-glass-dim
44+
prose-code:bg-white/10 prose-code:text-blue-300 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded-lg prose-code:text-sm
45+
prose-pre:bg-transparent prose-pre:p-0
46+
prose-strong:text-white prose-strong:font-bold
4747
prose-ul:list-disc prose-ul:list-inside
4848
prose-ol:list-decimal prose-ol:list-inside
49-
prose-li:text-text prose-li:ml-4">
49+
prose-li:text-glass prose-li:ml-4">
5050
<Content />
5151
</div>
5252
</article>

src/pages/index.astro

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,8 @@
11
---
22
import BaseLayout from '../layouts/BaseLayout.astro'
3-
import { getCollection } from 'astro:content'
4-
import { getReadingTime, formatDate } from '../utils/blog'
5-
6-
const posts = await getCollection('blog')
7-
const sortedPosts = posts.sort((a, b) =>
8-
b.data.date.getTime() - a.data.date.getTime()
9-
).slice(0, 3)
103
---
114

125
<BaseLayout title="Johan Wulf">
13-
<section class="mb-12">
14-
<h1 class="text-2xl font-normal mb-4">
15-
<span id="typewriter">Hi, I'm Johan</span>
16-
</h1>
17-
<p class="text-overlay-0 mb-2">
18-
<span class="prompt">$</span> Software developer based in Sweden
19-
</p>
20-
</section>
21-
22-
<section class="mt-12">
23-
<h2 class="text-lg text-blue mb-8">## Recent Posts</h2>
24-
<div class="space-y-6">
25-
{sortedPosts.map((post) => (
26-
<div class="flex justify-between items-baseline pb-6 border-b border-surface-0 last:border-0">
27-
<a href={`/blog/${post.slug}`} class="text-text hover:text-blue hover:underline">
28-
{post.data.title}
29-
</a>
30-
<span class="text-overlay-0 text-xs whitespace-nowrap ml-8">
31-
{formatDate(post.data.date)} · {getReadingTime(post)}
32-
</span>
33-
</div>
34-
))}
35-
</div>
36-
</section>
37-
</BaseLayout>
38-
39-
<script>
40-
const typewriter = document.getElementById('typewriter')
41-
42-
if (typewriter) {
43-
typewriter.classList.add('typewriter-text')
44-
45-
setTimeout(() => {
46-
typewriter.classList.add('typing-complete')
47-
}, 1500)
48-
}
49-
</script>
6+
<!-- The desktop interface is handled entirely by the BaseLayout -->
7+
<!-- This page serves as the desktop environment -->
8+
</BaseLayout>

0 commit comments

Comments
 (0)