Initial commit
This commit is contained in:
107
src/pages/index.astro
Normal file
107
src/pages/index.astro
Normal file
@@ -0,0 +1,107 @@
|
||||
---
|
||||
import Base from '../layouts/Base.astro';
|
||||
import SkillCard from '../components/SkillCard.astro';
|
||||
import SkillSearch from '../components/SkillSearch.vue';
|
||||
import { listSkills } from '../lib/skills';
|
||||
import { buildSyncScript } from '../lib/sync';
|
||||
|
||||
const accept = Astro.request.headers.get('accept') || '';
|
||||
if (!accept.includes('text/html')) {
|
||||
const script = await buildSyncScript(Astro.url.origin, '.claude/skills');
|
||||
return new Response(script, {
|
||||
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
|
||||
});
|
||||
}
|
||||
|
||||
const skills = await listSkills();
|
||||
---
|
||||
|
||||
<Base title="Skillit — Claude Code Skills">
|
||||
{skills.length === 0 ? (
|
||||
<div class="text-center py-24">
|
||||
<div class="inline-flex h-16 w-16 items-center justify-center rounded-2xl bg-surface-200 border border-white/[0.06] mb-6">
|
||||
<svg class="h-7 w-7 text-gray-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m3.75 9v6m3-3H9m1.5-12H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p class="text-gray-500 text-lg mb-2">No skills yet</p>
|
||||
<p class="text-gray-600 text-sm mb-6">Create your first skill to get started.</p>
|
||||
<a
|
||||
href="/new"
|
||||
class="inline-flex items-center gap-1.5 rounded-lg bg-accent-500 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-accent-500/20 hover:bg-accent-600 transition-all"
|
||||
>
|
||||
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||
</svg>
|
||||
Create your first skill
|
||||
</a>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<!-- Hero / Quick install -->
|
||||
<div class="mb-10">
|
||||
<h1 class="text-3xl font-extrabold tracking-tight text-white mb-2">Skills</h1>
|
||||
<p class="text-gray-500 mb-5 max-w-xl">Manage and distribute Claude Code skills. Skills are prompt files that Claude loads automatically to learn custom behaviors and workflows.</p>
|
||||
|
||||
<!-- Install instructions -->
|
||||
<div class="rounded-2xl border border-white/[0.06] bg-surface-100 p-6 max-w-2xl space-y-4">
|
||||
<h2 class="text-sm font-semibold text-white">Quick install</h2>
|
||||
<p class="text-xs text-gray-500 leading-relaxed">Run this in your project root to sync all skills. They'll be saved to <code class="text-gray-400 font-mono bg-white/[0.04] px-1 py-0.5 rounded">.claude/skills/</code> and Claude Code will pick them up automatically on the next conversation.</p>
|
||||
|
||||
<div class="flex items-center gap-3 rounded-xl bg-surface-50 border border-white/[0.06] px-4 py-3">
|
||||
<code id="install-cmd" class="flex-1 text-sm font-mono text-gray-400 select-all truncate">curl -fsSL {Astro.url.origin} | bash</code>
|
||||
<button
|
||||
id="copy-btn"
|
||||
class="shrink-0 rounded-md bg-white/[0.06] border border-white/[0.06] px-2.5 py-1 text-xs font-medium text-gray-400 hover:text-white hover:bg-white/[0.1] transition-all"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<details class="group">
|
||||
<summary class="text-xs text-gray-600 cursor-pointer hover:text-gray-400 transition-colors">More options</summary>
|
||||
<div class="mt-3 space-y-3 text-xs text-gray-500">
|
||||
<div>
|
||||
<p class="mb-1.5">Install globally (available in all projects):</p>
|
||||
<div class="flex items-center gap-3 rounded-lg bg-surface-50 border border-white/[0.06] px-3 py-2">
|
||||
<code class="flex-1 font-mono text-gray-400 select-all truncate">curl -fsSL {Astro.url.origin}/gi | bash</code>
|
||||
<button data-copy class="shrink-0 rounded bg-white/[0.06] border border-white/[0.06] px-2 py-0.5 font-medium text-gray-500 hover:text-white hover:bg-white/[0.1] transition-all">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mb-1.5">Push local skills to the server:</p>
|
||||
<div class="flex items-center gap-3 rounded-lg bg-surface-50 border border-white/[0.06] px-3 py-2">
|
||||
<code class="flex-1 font-mono text-gray-400 select-all truncate">curl -fsSL {Astro.url.origin}/p | bash</code>
|
||||
<button data-copy class="shrink-0 rounded bg-white/[0.06] border border-white/[0.06] px-2 py-0.5 font-medium text-gray-500 hover:text-white hover:bg-white/[0.1] transition-all">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search + Grid -->
|
||||
<SkillSearch client:load />
|
||||
<div id="skills-grid" class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{skills.map((skill) => (
|
||||
<div data-skill data-name={skill.name.toLowerCase()} data-description={skill.description.toLowerCase()} data-tools={skill['allowed-tools'].join(' ').toLowerCase()}>
|
||||
<SkillCard {...skill} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Base>
|
||||
|
||||
<script>
|
||||
document.querySelectorAll<HTMLButtonElement>('#copy-btn, [data-copy]').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
const code = btn.previousElementSibling?.textContent?.trim();
|
||||
if (code) {
|
||||
navigator.clipboard.writeText(code);
|
||||
btn.textContent = 'Copied!';
|
||||
setTimeout(() => btn.textContent = 'Copy', 1500);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user