Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
},
"dependencies": {
"@devcard/shared": "workspace:*"
"@devcard/shared": "workspace:*",
"lucide-svelte": "^1.0.1"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^7.0.0",
Expand Down
79 changes: 19 additions & 60 deletions apps/web/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
<script>
import { onMount } from 'svelte';
import {
Moon,
Sun,
Zap,
Star,
ChevronDown,
Link,
Lock,
} from 'lucide-svelte';

let theme = 'light';

Expand Down Expand Up @@ -40,14 +49,18 @@
<main class="landing">
<nav class="glass">
<div class="nav-content">
<div class="logo"> <span class="gradient-text">DevCard</span></div>
<div class="logo"><Zap size={24} strokeWidth={2.5} fill="currentColor" /> <span class="gradient-text">DevCard</span></div>
<button
id="theme-toggle"
class="theme-toggle"
on:click={toggleTheme}
aria-label="Toggle theme"
>
{theme === 'light' ? '🌙' : '☀️'}
{#if theme === 'light'}
<Moon size={20} />
{:else}
<Sun size={20} />
{/if}
</button>
</div>
</nav>
Expand All @@ -65,25 +78,25 @@
target="_blank"
rel="noopener"
>
Star on GitHub
<Star size={18} fill="currentColor" style="display: inline; vertical-align: middle; margin-right: 4px;" /> Star on GitHub
</a>
<a href="/u/devcard-demo" class="btn-secondary">View Demo Profile →</a>
</div>
</section>

<section id="features" class="features">
<div class="feature-card glass">
<div class="feature-icon">🔗</div>
<div class="feature-icon"><Link size={32} /></div>
<h3>Unified Identity</h3>
<p>Combine your fragmented online presence into a cohesive professional identity.</p>
</div>
<div class="feature-card glass">
<div class="feature-icon"></div>
<div class="feature-icon"><Zap size={32} /></div>
<h3>Instant Follow</h3>
<p>Integrated APIs allow followers to connect with you instantly across platforms.</p>
</div>
<div class="feature-card glass">
<div class="feature-icon">🔒</div>
<div class="feature-icon"><Lock size={32} /></div>
<h3>Private by Design</h3>
<p>No tracking, no data selling. Your information stays where it belongs: with you.</p>
</div>
Expand Down Expand Up @@ -237,60 +250,6 @@
transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}

@media (max-width: 640px) {
.features {
display: grid;
grid-template-columns: 1fr; /* single column */
gap: 16px;
padding: 0 12px;
}
}

.feature-card {
min-height: 140px;
padding: 16px;
}
@media (max-width: 640px) {
.feature-card {
margin-bottom: 12px;
}
}

.feature-card {
min-height: 140px;
padding: 16px;
}

.feature-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 2rem;
min-height: 140px;

/* normal shadow (very light) */
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);

/* smooth transition */
transition: all 0.25s ease;
}



.feature-card:hover {
/* halka lift */
transform: translateY(-3px);

/* stronger but soft shadow */
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12);
}

@media (max-width: 640px) {
.feature-card {
margin-bottom: 12px;
}
}

.feature-card:hover {
transform: translateY(-8px);
border-color: rgba(99, 102, 241, 0.4);
Expand Down
24 changes: 15 additions & 9 deletions apps/web/src/routes/u/[username]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<script lang="ts">
import { PLATFORMS, getProfileUrl } from '@devcard/shared';
import { onMount } from 'svelte';
import { PLATFORMS, getProfileUrl } from '@devcard/shared';
import {
Frown,
ArrowLeft,
ArrowRight,
Zap,
} from 'lucide-svelte';

let { data } = $props();
const profile = data.profile;
Expand Down Expand Up @@ -37,9 +43,7 @@
clearTimeout(copyMessageTimeout);
}

clearTimeout(copyTimeout);

copyTimeout = setTimeout(() => {
copyMessageTimeout = setTimeout(() => {
copyMessage = '';
}, 3000);
}
Expand Down Expand Up @@ -73,10 +77,10 @@
<main class="profile-container {mounted ? 'loaded' : ''}">
{#if error || !profile}
<div class="error-glass glass">
<div class="error-emoji">😕</div>
<div class="error-emoji"><Frown size={64} style="display: inline;" /></div>
<h1>Profile not found</h1>
<p>This DevCard has vanished into the digital void.</p>
<a href="/" class="btn-primary">Return Home</a>
<a href="/" class="btn-primary"><ArrowLeft size={18} style="display: inline; vertical-align: middle; margin-right: 4px;" /> Return Home</a>
</div>
{:else}
<div class="profile-card glass" style="--accent: {profile.accentColor}">
Expand Down Expand Up @@ -122,21 +126,21 @@
<span class="platform-name">{platform?.name || link.platform}</span>
<span class="username">@{link.username}</span>
</div>
<span class="arrow"></span>
<span class="arrow"><ArrowRight size={18} /></span>
</a>
{/each}
</div>

<footer class="card-footer">
<p>Verified Developer Profile</p>
<div class="logo-sm"> DevCard</div>
<div class="logo-sm"><Zap size={14} style="display: inline; vertical-align: middle;" /> DevCard</div>
</footer>
</div>

<div class="get-your-own">
<p>Want a card like this?</p>
<div class="profile-actions">
<a href="/" class="gradient-text get-devcard-link">Create your DevCard </a>
<a href="/" class="gradient-text get-devcard-link">Create your DevCard <Zap size={18} style="display: inline; vertical-align: middle; margin-left: 2px;" fill="currentColor" /></a>
<button type="button" class="copy-link-button" onclick={copyProfileUrl}>
Copy Link
</button>
Expand Down Expand Up @@ -325,6 +329,8 @@
.arrow {
opacity: 0.45;
font-size: 1.2rem;
display: flex;
align-items: center;
transition: transform 0.25s ease, opacity 0.25s ease;
}

Expand Down
Loading