Skip to content

Commit ef86704

Browse files
authored
Merge pull request #9 from DoktorShift/deploy
Apps + Plugins + Community Skills + Deployment prepare
2 parents 1a768c3 + bee52a8 commit ef86704

26 files changed

Lines changed: 1160 additions & 55 deletions

.github/workflows/deploy.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
schedule:
8+
- cron: '0 6 * * 1' # Rebuild every Monday 6am UTC (picks up new extension READMEs, releases)
9+
10+
permissions:
11+
contents: read
12+
pages: write
13+
id-token: write
14+
15+
concurrency:
16+
group: pages
17+
cancel-in-progress: false
18+
19+
jobs:
20+
build:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@v4
24+
25+
- uses: actions/setup-node@v4
26+
with:
27+
node-version: 20
28+
cache: npm
29+
30+
- run: npm ci
31+
32+
- name: Generate extension pages
33+
run: node scripts/generate-extension-pages.mjs
34+
env:
35+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36+
37+
- name: Generate LLM files
38+
run: npm run generate:llm
39+
40+
- name: Build VitePress
41+
run: npm run docs:build
42+
43+
- uses: actions/upload-pages-artifact@v3
44+
with:
45+
path: docs/.vitepress/dist
46+
47+
deploy:
48+
needs: build
49+
runs-on: ubuntu-latest
50+
environment:
51+
name: github-pages
52+
url: ${{ steps.deployment.outputs.page_url }}
53+
steps:
54+
- id: deployment
55+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ Thumbs.db
2626
# Build artifacts
2727
.turbo/
2828
.parcel-cache/
29+
30+
deploy_plan.md

.node-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
20

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Official documentation for [LNbits](https://github.com/lnbits/lnbits), the free
1111
- **Developer Guide** - Architecture, building extensions, deploying, contributing
1212
- **Extensions** - 62 extension pages with docs and API references
1313
- **LLM Integration** - Agent-ready docs, system prompts, llms.txt
14+
- **Skills to Built** - Create own Skill.md files or use existing ones from Core Team and Community to built awesome stuff
1415

1516
## Local development
1617

docs/.vitepress/config.mjs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ export default withMermaid(defineConfig({
131131
],
132132
},
133133
{ text: 'Extensions', link: '/extensions/' },
134-
{ text: 'Apps', link: '/apps/tpos-wrapper' },
134+
{ text: 'Apps', link: '/apps/' },
135+
{ text: 'Plugins', link: '/plugins/' },
135136
{ text: 'Contribute', link: '/contribute/' },
136137
{
137138
text: 'Developers',
@@ -486,23 +487,52 @@ export default withMermaid(defineConfig({
486487
],
487488
},
488489
{
489-
text: 'Available Skills',
490+
text: 'Official Skills',
490491
collapsed: false,
491492
items: [
492493
{ text: 'Wallet & Payments', link: '/llm/skills/wallet-payments' },
493494
{ text: 'Lightning Address', link: '/llm/skills/lnurlp-pay-links' },
494495
{ text: 'Shared Wallet (Uncle Jim)', link: '/llm/skills/shared-wallet' },
495496
],
496497
},
498+
{
499+
text: 'Community Skills',
500+
collapsed: false,
501+
items: [
502+
{ text: 'Coming soon' },
503+
],
504+
},
497505
],
498506
'/apps/': [
499507
{
500508
text: 'Companion Apps',
509+
items: [
510+
{ text: 'Overview', link: '/apps/' },
511+
],
512+
},
513+
{
514+
text: 'Apps',
515+
collapsed: false,
501516
items: [
502517
{ text: 'TPoS Wrapper', link: '/apps/tpos-wrapper' },
503518
],
504519
},
505520
],
521+
'/plugins/': [
522+
{
523+
text: 'eCommerce Plugins',
524+
items: [
525+
{ text: 'Overview', link: '/plugins/' },
526+
],
527+
},
528+
{
529+
text: 'Plugins',
530+
collapsed: false,
531+
items: [
532+
{ text: 'WooCommerce', link: '/plugins/woocommerce' },
533+
],
534+
},
535+
],
506536
},
507537

508538
socialLinks: [

docs/.vitepress/theme/components/ContributePage.vue

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ const faqOpen = ref(new Set())
7575
7676
const roleData = {
7777
developer: {
78+
intro: {
79+
kicker: 'START BUILDING',
80+
headline: 'Write code that powers Lightning for thousands',
81+
sub: 'Pick a good first issue, set up FakeWallet, and ship your first PR. The codebase is Python + FastAPI on the backend, Vue 3 + Quasar on the frontend.',
82+
cta: { label: 'Browse good first issues', url: 'https://github.com/lnbits/lnbits/labels/good%20first%20issue' },
83+
},
7884
video: null,
7985
steps: [
8086
{
@@ -123,6 +129,12 @@ const roleData = {
123129
],
124130
},
125131
tester: {
132+
intro: {
133+
kicker: 'BREAK THINGS',
134+
headline: 'Every bug you catch saves a merchant',
135+
sub: 'Test pull requests, try every release, and report what breaks. Use FakeWallet locally or spin up a live instance on my.lnbits.com in under 3 minutes.',
136+
cta: { label: 'View open PRs to test', url: 'https://github.com/lnbits/lnbits/pulls?q=is%3Apr+is%3Aopen+label%3Aneeds-testing' },
137+
},
126138
video: null,
127139
steps: [
128140
{
@@ -199,6 +211,12 @@ const roleData = {
199211
],
200212
},
201213
writer: {
214+
intro: {
215+
kicker: 'TELL THE STORY',
216+
headline: 'Your words bring people closer to Bitcoin',
217+
sub: 'Pick an open issue in the docs or blog and start writing. No technical background needed. The best content comes from real experience.',
218+
cta: { label: 'Browse docs issues', url: 'https://github.com/DoktorShift/docs_lnbits/issues' },
219+
},
202220
video: null,
203221
steps: [
204222
{
@@ -275,6 +293,12 @@ const roleData = {
275293
],
276294
},
277295
designer: {
296+
intro: {
297+
kicker: 'MAKE IT SHINE',
298+
headline: 'Design the interface people trust',
299+
sub: 'Shape the LNbits UI with Vue 3 and Quasar, create visuals for marketing, or redesign extension flows. When it looks good, people trust it.',
300+
cta: { label: 'See design issues', url: 'https://github.com/lnbits/lnbits/issues?q=is%3Aissue+is%3Aopen+label%3Adesign' },
301+
},
278302
video: null,
279303
steps: [
280304
{
@@ -344,6 +368,12 @@ const roleData = {
344368
],
345369
},
346370
entrepreneur: {
371+
intro: {
372+
kicker: 'BUILD YOUR BUSINESS',
373+
headline: 'Turn LNbits into your product',
374+
sub: 'Deploy for your community, white-label it, sell extensions, or run it as a service. LNbits is the platform - you decide the business model.',
375+
cta: { label: 'Launch a SaaS instance', url: 'https://my.lnbits.com' },
376+
},
347377
video: null,
348378
blog: {
349379
title: 'How to set up your own LNbits server',
@@ -402,6 +432,12 @@ const roleData = {
402432
],
403433
},
404434
ambassador: {
435+
intro: {
436+
kicker: 'LEAD THE CHARGE',
437+
headline: 'Bring Lightning to your community',
438+
sub: 'Deploy LNbits, onboard merchants, host meetups, and spread the word. You are the bridge between Bitcoin and everyday commerce.',
439+
cta: { label: 'Get the install guide', url: '/guide/installation/' },
440+
},
405441
video: { id: 'ZTjFalYeOlA', title: 'LNbits Extensions Deep-Dive' },
406442
steps: [
407443
{
@@ -789,6 +825,21 @@ onUnmounted(() => {
789825
<Transition name="cp-fade" mode="out-in">
790826
<div :key="activeRole" class="cp-flow">
791827

828+
<!-- Role intro -->
829+
<section v-if="active.intro" class="cp-role-intro">
830+
<div class="cp-w">
831+
<div class="cp-role-intro-inner">
832+
<span class="cp-role-kicker">{{ active.intro.kicker }}</span>
833+
<h2 class="cp-role-headline">{{ active.intro.headline }}</h2>
834+
<p class="cp-role-sub">{{ active.intro.sub }}</p>
835+
<a v-if="active.intro.cta" :href="active.intro.cta.url" class="cp-role-cta" :target="active.intro.cta.url.startsWith('http') ? '_blank' : undefined" :rel="active.intro.cta.url.startsWith('http') ? 'noopener noreferrer' : undefined">
836+
{{ active.intro.cta.label }}
837+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5l7 7-7 7"/></svg>
838+
</a>
839+
</div>
840+
</div>
841+
</section>
842+
792843
<!-- Video -->
793844
<section v-if="active.video" class="cp-vid-sec">
794845
<div class="cp-w">
@@ -1215,6 +1266,41 @@ onUnmounted(() => {
12151266
.cp-featured:hover .cp-featured-arr { color: var(--vp-c-brand-1); }
12161267
12171268
/* ═══ Steps ═══ */
1269+
/* ═══ Role Intro ═══ */
1270+
.cp-role-intro { padding: 48px 0 32px; }
1271+
.cp-role-intro-inner {
1272+
max-width: 640px; margin: 0 auto; text-align: center;
1273+
}
1274+
.cp-role-kicker {
1275+
display: inline-block;
1276+
font-size: 11px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase;
1277+
color: var(--vp-c-brand-1);
1278+
margin-bottom: 12px;
1279+
}
1280+
.cp-role-headline {
1281+
font-size: 28px; font-weight: 800; line-height: 1.2;
1282+
color: var(--vp-c-text-1);
1283+
margin: 0 0 16px;
1284+
}
1285+
.cp-role-sub {
1286+
font-size: 15px; line-height: 1.65; color: var(--vp-c-text-2);
1287+
margin: 0 0 24px;
1288+
}
1289+
.cp-role-cta {
1290+
display: inline-flex; align-items: center; gap: 6px;
1291+
padding: 10px 24px;
1292+
font-size: 14px; font-weight: 600;
1293+
color: var(--vp-c-white); background: var(--vp-c-brand-1);
1294+
border-radius: 8px; text-decoration: none;
1295+
transition: background .2s ease, transform .15s ease;
1296+
}
1297+
.cp-role-cta:hover {
1298+
background: var(--vp-c-brand-2);
1299+
transform: translateY(-1px);
1300+
}
1301+
.cp-role-cta svg { transition: transform .2s ease; }
1302+
.cp-role-cta:hover svg { transform: translateX(3px); }
1303+
12181304
.cp-flow { padding-bottom: 24px; }
12191305
.cp-step { position: relative; }
12201306
.cp-step-line { height: 1px; background: linear-gradient(to right, transparent, var(--vp-c-divider) 15%, var(--vp-c-divider) 85%, transparent); }
@@ -1425,6 +1511,12 @@ onUnmounted(() => {
14251511
.cp-title { font-size: 1.6rem; letter-spacing: -.03em; margin-bottom: 12px; }
14261512
.cp-sub { font-size: 0.95rem; max-width: 100%; line-height: 1.7; }
14271513
1514+
/* Role intro */
1515+
.cp-role-intro { padding: 32px 0 24px; }
1516+
.cp-role-headline { font-size: 22px; }
1517+
.cp-role-sub { font-size: 14px; }
1518+
.cp-role-cta { font-size: 13px; padding: 9px 20px; }
1519+
14281520
/* Contributors carousel */
14291521
.cp-contributors { padding: 0 0 32px; }
14301522
.cp-contrib-label { font-size: 12px; margin-bottom: 14px; }

docs/.vitepress/theme/components/MegaMenu.vue

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const columns = [
4040
items: [
4141
{ name: 'Wallet Backends', desc: '20+ funding sources', link: '/guide/wallets/', icon: 'wallet' },
4242
{ name: 'Core Features', desc: 'Payments, LNURL, labels', link: '/guide/core/', icon: 'zap' },
43-
{ name: 'Extensions', desc: '60+ plugins', link: '/guide/using-extensions', icon: 'puzzle' },
43+
{ name: 'Extensions', desc: '60+ extensions', link: '/guide/using-extensions', icon: 'puzzle' },
4444
{ name: 'Admin Dashboard', desc: 'Server management', link: '/guide/admin-dashboard', icon: 'settings' },
4545
{ name: 'User Management', desc: 'Roles & permissions', link: '/guide/core/user-management/', icon: 'users' },
4646
{ name: 'FAQ', desc: '80+ common questions', link: '/guide/faq/', icon: 'help' },
@@ -121,13 +121,19 @@ const columns = [
121121
{
122122
heading: 'Extensions',
123123
items: [
124-
{ name: 'Browse Extensions', desc: '60+ plugins ready to use', link: '/extensions/', icon: 'puzzle' },
124+
{ name: 'Browse Extensions', desc: '60+ extensions ready to use', link: '/extensions/', icon: 'puzzle' },
125125
],
126126
},
127127
{
128128
heading: 'Companion Apps',
129129
items: [
130-
{ name: 'TPoS Wrapper', desc: 'Android Tap to Pay', link: '/apps/tpos-wrapper', icon: 'zap' },
130+
{ name: 'Browse Apps', desc: 'Standalone apps for LNbits', link: '/apps/', icon: 'zap' },
131+
],
132+
},
133+
{
134+
heading: 'eCommerce Plugins',
135+
items: [
136+
{ name: 'Browse Plugins', desc: 'WooCommerce, Shopify and more', link: '/plugins/', icon: 'shopping-cart' },
131137
],
132138
},
133139
{
@@ -196,6 +202,7 @@ const columns = [
196202
<svg v-if="item.icon==='shield'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
197203
<svg v-if="item.icon==='plus'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
198204
<svg v-if="item.icon==='layers'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>
205+
<svg v-if="item.icon==='shopping-cart'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 002 1.61h9.72a2 2 0 002-1.61L23 6H6"/></svg>
199206
<svg v-if="item.icon==='database'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>
200207
<svg v-if="item.icon==='code'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
201208
<svg v-if="item.icon==='clock'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>

docs/.vitepress/theme/components/NavSwitch.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import MegaMenu from './MegaMenu.vue'
55
66
const route = useRoute()
77
const isIndex = computed(() => route.path === '/' || route.path === '/index.html')
8+
const isContribute = computed(() => route.path.startsWith('/contribute'))
89
910
const sections = [
1011
{ text: 'Guide', link: '/guide/', match: '/guide' },
1112
{ text: 'API', link: '/api/', match: '/api' },
1213
{ text: 'Extensions', link: '/extensions/', match: '/extensions' },
13-
{ text: 'Apps', link: '/apps/tpos-wrapper', match: '/apps' },
14+
{ text: 'Apps', link: '/apps/', match: '/apps' },
15+
{ text: 'Plugins', link: '/plugins/', match: '/plugins' },
1416
{ text: 'Developers', link: '/dev/architecture', match: '/dev' },
1517
{ text: 'LLM', link: '/llm/', match: '/llm' },
1618
{ text: 'Contribute', link: '/contribute/', match: '/contribute' },
@@ -24,10 +26,10 @@ const activeSection = computed(() => {
2426
})
2527
2628
function syncClass() {
27-
document.body.classList.toggle('has-section-bar', !isIndex.value)
29+
document.body.classList.toggle('has-section-bar', !isIndex.value && !isContribute.value)
2830
}
2931
30-
watch(isIndex, syncClass)
32+
watch([isIndex, isContribute], syncClass)
3133
onMounted(syncClass)
3234
onUnmounted(() => document.body.classList.remove('has-section-bar'))
3335
</script>
@@ -38,7 +40,7 @@ onUnmounted(() => document.body.classList.remove('has-section-bar'))
3840

3941
<!-- Doc pages: section bar below header -->
4042
<Teleport to="body">
41-
<nav v-if="!isIndex" class="sb" aria-label="Section navigation">
43+
<nav v-if="!isIndex && !isContribute" class="sb" aria-label="Section navigation">
4244
<div class="sb-inner">
4345
<a
4446
v-for="s in sections"

0 commit comments

Comments
 (0)