Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules
docs/.vitepress/cache
docs/.vitepress/dist
chunks.json

# OS files
.DS_Store
Expand Down
13 changes: 12 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing to LNbits Docs

Thanks for helping improve the documentation. Every fix, tutorial, and FAQ answer makes LNbits easier to use.
Thanks for helping improve LNbits. Every fix, tutorial, and FAQ answer makes LNbits easier to use.

## Quick wins

Expand Down Expand Up @@ -32,8 +32,19 @@ Extension pages in `docs/extensions/` are auto-generated from each extension's G

Not sure where to start? The [Contribute page](https://docs.lnbits.com/contribute/) has role-specific guides for developers, testers, writers, designers, entrepreneurs, and ambassadors.

## Labels that surface work to contributors

The [Contribute page](https://docs.lnbits.com/contribute/) links to filtered views of open issues and PRs on [`lnbits/lnbits`](https://github.com/lnbits/lnbits). Three labels power those views - apply them when opening or triaging so your issue or PR shows up for the right audience:

- [`good first issue`](https://github.com/lnbits/lnbits/labels/good%20first%20issue) - Small, well-scoped tasks suitable for a first-time contributor. Use sparingly: the issue must be solvable without deep project context.
- [`needs-testing`](https://github.com/lnbits/lnbits/labels/needs-testing) - A PR or issue that needs community testing (run it locally, exercise the feature, report back) before it can be merged or closed. This is distinct from `awaiting review`, which is for maintainer code review.
- [`design`](https://github.com/lnbits/lnbits/labels/design) - UI, UX, or visual design work - mockups, flows, styling, illustrations. Narrower than `frontend`, which covers any user-facing code change.

If you are a maintainer, add these labels as part of triage. If you are opening an issue or PR, suggesting one of these labels in the description is welcome.

## Community

- [Telegram](https://t.me/lnbits) - Main community chat
- [Community Forum](https://community.lnbits.com) - Searchable discussions. Common Forum for all LNbits related questions.
- [GitHub Issues](https://github.com/lnbits/lnbits/issues) - Bug reports
- [GitHub Discussions](https://github.com/lnbits/lnbits/discussions) - Longer questions
4 changes: 2 additions & 2 deletions docs/.vitepress/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ export default withMermaid(defineConfig({
],

footer: {
message: '<a href="https://news.lnbits.com" target="_blank">News</a> · <a href="https://shop.lnbits.com" target="_blank">Shop</a> · <a href="https://my.lnbits.com" target="_blank">SaaS</a> · <a href="https://t.me/lnbits" target="_blank">Telegram</a> · Released under the MIT License.',
message: '<a href="https://news.lnbits.com" target="_blank">News</a> · <a href="https://shop.lnbits.com" target="_blank">Shop</a> · <a href="https://my.lnbits.com" target="_blank">SaaS</a> · <a href="https://t.me/lnbits" target="_blank">Telegram</a> · <a href="https://community.lnbits.com" target="_blank">Forum</a> · Released under the MIT License.',
copyright: 'Copyright 2018-present LNbits Contributors',
},

Expand All @@ -573,7 +573,7 @@ export default withMermaid(defineConfig({
},

editLink: {
pattern: 'https://github.com/lnbits/lnbits-docs/edit/main/docs/:path',
pattern: 'https://github.com/lnbits/docs/edit/main/docs/:path',
text: 'Edit this page on GitHub',
},
},
Expand Down
10 changes: 8 additions & 2 deletions docs/.vitepress/theme/components/ContributePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ const roles = [

const communityLinks = [
{ name: 'Telegram', url: 'https://t.me/lnbits', icon: 'telegram', desc: 'Chat with the community and core team' },
{ name: 'Community Forum', url: 'https://community.lnbits.com', icon: 'forum', desc: 'Async, searchable discussions' },
{ name: 'GitHub', url: 'https://github.com/lnbits/lnbits', icon: 'github', desc: 'Report bugs, propose features, submit code' },
{ name: 'Follow on X', url: 'https://x.com/lnbits', icon: 'x', desc: 'Follow for updates and announcements' },
{ name: 'Nostr', url: 'https://primal.net/p/npub10efcj7x65z2ak6vd69xr8f2hvqwuaqrhlygl3yqa4y63hfvc02mqwzaeh3', icon: 'nostr', desc: 'Find us on the decentralized social network' },
]

const allFaqItems = [
// ── General (shown for every role) ──
{ q: 'Where do I ask for help?', roles: '*', a: 'The <a href="https://t.me/lnbits" target="_blank">Telegram group</a> is the heartbeat of the community. Core devs, extension builders, and users are all there. For longer questions, open a <a href="https://github.com/lnbits/lnbits/discussions" target="_blank">GitHub Discussion</a>.' },
{ q: 'Where do I ask for help?', roles: '*', a: 'The <a href="https://t.me/lnbits" target="_blank">Telegram group</a> is the heartbeat of the community - core devs, extension builders, and users are all there. For async, searchable threads use the <a href="https://community.lnbits.com" target="_blank">Community Forum</a>. For longer technical questions, open a <a href="https://github.com/lnbits/lnbits/discussions" target="_blank">GitHub Discussion</a>.' },
{ q: 'Can I get paid for contributing?', roles: '*', a: 'LNbits is volunteer open-source, but there are paths. <a href="https://opensats.org" target="_blank">OpenSats</a> and <a href="https://hrf.org" target="_blank">HRF</a> fund contributors. Extension developers can <a href="/dev/extensions/monetization">monetize via pay-to-install</a> in the registry. Some community members tip contributors over Lightning directly.' },
{ q: 'What license does LNbits use?', roles: '*', a: 'MIT. Use it, fork it, sell it, remix it. The only rule is keeping the license notice. See the <a href="https://github.com/lnbits/lnbits/blob/main/LICENSE" target="_blank">LICENSE file</a>.' },

Expand Down Expand Up @@ -326,7 +327,7 @@ const roleData = {
],
},
{
num: '02', title: 'What we need', illust: 'tips',
num: '02', title: 'Where you can help', illust: 'tips',
desc: 'Pick what excites you. Every area has open opportunities.',
columns: [
{
Expand All @@ -339,6 +340,7 @@ const roleData = {
{
label: 'Creative design',
items: [
{ name: 'Media kit', desc: 'Logos, brand assets, press material', logo: '/logos/lnbits.svg', url: 'https://media.lnbits.com' },
{ name: 'Media repo', desc: 'Existing assets, logos, and creative work', icon: 'devicon-github-original', url: 'https://github.com/lnbits/lnbits_media' },
{ name: 'Blog and news headers', desc: 'Hero images for articles', icon: 'devicon-figma-plain', url: 'https://news.lnbits.com' },
{ name: 'Illustrations for marketing', desc: 'Visuals that help us tell the LNbits story', icon: 'devicon-figma-plain', url: 'https://t.me/lnbits' },
Expand Down Expand Up @@ -428,6 +430,7 @@ const roleData = {
{ name: 'LNbits SaaS', url: 'https://my.lnbits.com', badge: 'Launch fast' },
{ name: 'Extension monetization', url: '/dev/extensions/monetization', badge: 'Earn sats' },
{ name: 'Share your story on Telegram', url: 'https://t.me/lnbits' },
{ name: 'Community Forum', url: 'https://community.lnbits.com' },
{ name: 'GitHub Discussions', url: 'https://github.com/lnbits/lnbits/discussions' },
],
action: { label: 'Get started', url: 'https://my.lnbits.com' },
Expand Down Expand Up @@ -503,7 +506,9 @@ const roleData = {
items: [
{ name: 'Create YouTube tutorials', url: 'https://www.youtube.com/@lnbits', badge: 'High impact' },
{ name: 'Share on X', url: 'https://x.com/intent/tweet?text=I%27m+onboarding+merchants+to+Lightning+with+%40lnbits' },
{ name: 'Media kit', url: 'https://media.lnbits.com', badge: 'Logos and brand assets' },
{ name: 'Telegram community', url: 'https://t.me/lnbits' },
{ name: 'Community Forum', url: 'https://community.lnbits.com' },
{ name: 'GitHub Discussions', url: 'https://github.com/lnbits/lnbits/discussions' },
],
action: { label: 'Deploy LNbits now', url: '/guide/installation/' },
Expand Down Expand Up @@ -1081,6 +1086,7 @@ onUnmounted(() => {
<a v-for="l in communityLinks" :key="l.name" :href="l.url" target="_blank" rel="noopener noreferrer" class="cp-contact-card">
<div class="cp-contact-icon">
<svg v-if="l.icon==='telegram'" viewBox="0 0 24 24" fill="currentColor"><path d="M11.944 0A12 12 0 000 12a12 12 0 0012 12 12 12 0 0012-12A12 12 0 0012 0a12 12 0 00-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 01.171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>
<svg v-if="l.icon==='forum'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<svg v-if="l.icon==='github'" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
<svg v-if="l.icon==='x'" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
<svg v-if="l.icon==='nostr'" viewBox="46 19 172 192" fill="currentColor"><path d="M210.8 199.4c0 3.1-2.5 5.7-5.7 5.7h-68c-3.1 0-5.7-2.5-5.7-5.7v-15.5c.3-19 2.3-37.2 6.5-45.5 2.5-5 6.7-7.7 11.5-9.1 9.1-2.7 24.9-.9 31.7-1.2 0 0 20.4.8 20.4-10.7s-9.1-8.6-9.1-8.6c-10 .3-17.7-.4-22.6-2.4-8.3-3.3-8.6-9.2-8.6-11.2-.4-23.1-34.5-25.9-64.5-20.1-32.8 6.2.4 53.3.4 116.1v8.4c0 3.1-2.6 5.6-5.7 5.6H57.7c-3.1 0-5.7-2.5-5.7-5.7v-144c0-3.1 2.5-5.7 5.7-5.7h31.7c3.1 0 5.7 2.5 5.7 5.7 0 4.7 5.2 7.2 9 4.5 11.4-8.2 26-12.5 42.4-12.5 36.6 0 64.4 21.4 64.4 68.7v83.2ZM150 99.3c0-6.7-5.4-12.1-12.1-12.1s-12.1 5.4-12.1 12.1 5.4 12.1 12.1 12.1S150 106 150 99.3Z"/></svg>
Expand Down
39 changes: 23 additions & 16 deletions docs/.vitepress/theme/components/HomePage.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script setup>
import { ref, onMounted, computed } from 'vue'
import { useData } from 'vitepress'
import { ref, onMounted } from 'vue'
import { Code, SearchCheck, PenLine, Palette, Rocket, Megaphone } from 'lucide-vue-next'
import openaiIcon from '@lobehub/icons-static-svg/icons/openai.svg'
import claudeIcon from '@lobehub/icons-static-svg/icons/claude-color.svg'
Expand All @@ -12,7 +11,6 @@ const mounted = ref(false)
const toast = ref('')
const ghStars = ref('')
const contribVideoActive = ref(false)
const { isDark } = useData()

onMounted(() => {
mounted.value = true
Expand Down Expand Up @@ -101,7 +99,10 @@ const mainCards = [
},
]

const backendsData = [
// Each backend ships a light and a dark variant. Both <img> tags are rendered
// and toggled via the `.dark` class on <html>, so the correct logo shows
// immediately on first paint — no hydration flicker when dark mode is active.
const backends = [
{ name: 'LND', dark: '/logos/backends/lnd.png', light: '/logos/backends/lnd.png' },
{ name: 'Core Lightning', dark: '/logos/backends/cln.png', light: '/logos/backends/clnl.png' },
{ name: 'Phoenixd', dark: '/logos/backends/phoenixd.png', light: '/logos/backends/phoenixdl.png' },
Expand All @@ -118,13 +119,6 @@ const backendsData = [
{ name: 'RaspiBlitz', dark: '/logos/backends/blitz.png', light: '/logos/backends/blitzl.png' },
]

const backends = computed(() =>
backendsData.map(b => ({
name: b.name,
img: isDark.value ? b.dark : b.light,
}))
)

const quickLinks = [
{ title: 'Installation', desc: 'uv, Poetry, Docker, Nix, Fly.io', link: '/guide/installation/', icon: 'download' },
{ title: 'Wallet Backends', desc: '20+ funding sources', link: '/guide/wallets/', icon: 'wallet' },
Expand Down Expand Up @@ -176,15 +170,17 @@ const quickLinks = [
</button>

<!-- Funding Sources Carousel -->
<div class="carousel-wrap" :key="isDark ? 'dark' : 'light'">
<div class="carousel-wrap">
<span class="carousel-label">Funding Sources</span>
<div class="carousel">
<div class="carousel-track">
<div v-for="b in backends" :key="b.name + '-1'" class="carousel-item">
<img :src="b.img" :alt="b.name" loading="lazy" />
<img :src="b.light" :alt="b.name" class="carousel-img carousel-img--light" loading="lazy" />
<img :src="b.dark" :alt="b.name" class="carousel-img carousel-img--dark" loading="lazy" />
</div>
<div v-for="b in backends" :key="b.name + '-2'" class="carousel-item" aria-hidden="true">
<img :src="b.img" :alt="b.name" loading="lazy" />
<img :src="b.light" alt="" class="carousel-img carousel-img--light" loading="lazy" />
<img :src="b.dark" alt="" class="carousel-img carousel-img--dark" loading="lazy" />
</div>
</div>
</div>
Expand Down Expand Up @@ -432,6 +428,13 @@ const quickLinks = [
<span>Chat with the community</span>
</div>
</a>
<a href="https://community.lnbits.com" target="_blank" rel="noopener noreferrer" class="community-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<div>
<strong>Community Forum</strong>
<span>Async, searchable discussions</span>
</div>
</a>
<a href="https://github.com/lnbits/lnbits" target="_blank" rel="noopener noreferrer" class="community-link">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
<div>
Expand Down Expand Up @@ -468,7 +471,7 @@ const quickLinks = [
Layout
═══════════════════════════════════ */
.home {
max-width: 840px;
max-width: 1152px;
margin: 0 auto;
padding: 0 24px 96px;
background-image:
Expand Down Expand Up @@ -707,12 +710,16 @@ const quickLinks = [
flex-shrink: 0;
}

.carousel-item img {
.carousel-img {
width: 72px;
height: 72px;
object-fit: contain;
}

/* The show/hide toggle between .carousel-img--light and .carousel-img--dark
lives in custom.css because it depends on `.dark` on <html> — a global
state, better expressed with global CSS than scoped + :global() rules. */

@keyframes scroll-carousel {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
Expand Down
Loading