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
63 changes: 63 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This is the documentation site for [MyNode](https://mynodebtc.com/), a Bitcoin and Lightning Network node software. Built with **VuePress v1.5.3**, deployed to GitHub Pages at https://mynodebtc.github.io/.

## Development Commands

```bash
# Install dependencies
yarn install

# Start local dev server (http://localhost:8080)
yarn docs:dev

# Production build (output: docs/.vuepress/dist/)
yarn docs:build
```

> VuePress requires the `NODE_OPTIONS=--openssl-legacy-provider` flag on newer Node.js versions. The GitHub Actions workflow sets this automatically; set it manually if builds fail locally.

## Repository Structure

```
docs/
├── .vuepress/
│ ├── config.js # Sidebar nav, plugins, theme config
│ └── public/ # Static assets: images at public/images/<topic>/
├── README.md # Homepage (hero + features frontmatter)
├── intro/ # Getting started guides
├── device/ # Hardware setup & management
├── bitcoin/ # Bitcoin node configuration
├── lightning/ # Lightning Network (RTL, ThunderHub, wallets)
├── electrum/ # Electrum wallet integration
├── advanced/ # SSH, terminal, custom configs, VMs
├── troubleshooting/ # Error resolution guides
└── [other topic dirs] # btcpay-server, tor, vpn, multisig, etc.
```

## Content Patterns

- All documentation lives in `docs/<topic>/<page>.md` as plain Markdown
- Images: store in `docs/.vuepress/public/images/<topic>/`, reference as `/images/<topic>/image.png`
- Adding a new page requires registering it in the sidebar in `docs/.vuepress/config.js`
- The sidebar uses collapsible groups; match the existing structure when adding entries

## Design

The docs site is a visual extension of the main marketing site at `D:\camilo\Documents\GitHub\mynode_web`.

**Hard rule: never modify guide content** (any `.md` file under `docs/` except `docs/README.md`). All changes must be limited to:
- `docs/.vuepress/config.js` — theme/plugin config
- `docs/.vuepress/public/css/mynode.css` — all visual styling
- `docs/.vuepress/public/` — static assets (images, fonts, icons)
- `docs/README.md` — homepage layout only

The design system lives in the main site repo. Before making any styling decision, check `D:\camilo\Documents\GitHub\mynode_web` for the canonical tokens, components, and patterns.

## Deployment

GitHub Actions automatically builds and deploys on every push to `master`. The built site is pushed to the `mynodebtc/mynodebtc.github.io` repository. Manual deployment is available via `deploy.sh` (force-pushes to the pages repo).
13 changes: 9 additions & 4 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,30 @@ module.exports = {
description: "Helpful guides and documentation for using MyNode and getting the most out of all it has to offer!",
base: "/",
head: [
['meta', { name: 'theme-color', content: '#3eaf7c' }],
// Must be first — sets data-theme before any CSS renders to prevent flash.
['script', {}, `(function(){var t=localStorage.getItem('mn-theme');if(t==='light')document.documentElement.setAttribute('data-theme','light');})()`],
['meta', { name: 'theme-color', content: '#F08E20' }],
['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }],
['link', { rel : 'icon', href: '/favicon.ico' }],
['link', { rel: 'icon', href: '/favicon.ico' }],
['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }],
['link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }],
['link', { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;900&display=swap' }],
['link', { rel : 'stylesheet', href: '/css/mynode.css' }],
['script',{async: true, src: 'https://www.googletagmanager.com/gtag/js?id=G-871EBBS9WR'},],
['script',{},["window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', 'G-871EBBS9WR');",],],
],
themeConfig: {
repo: 'mynodebtc/mynode_docs',
repoLabel: 'Contribute!',
repoLabel: 'Contribute',
editLinks: true,
editLinkText: 'Help us improve this page!',
docsDir: 'docs',
lastUpdated: false,
sidebarDepth: 0,
nav: [
{ text: "Back to MyNode", link: "https://www.mynodebtc.com/"},
{ text: "Order Now!", link: "https://www.mynodebtc.com/order_now"}
{ text: "Order Now", link: "https://www.mynodebtc.com/order_now"}
],
logo: "/images/logo.png",
sidebar: [
Expand Down
61 changes: 61 additions & 0 deletions docs/.vuepress/enhanceApp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
export default ({ Vue, router }) => {
if (typeof window === 'undefined') return

// Apply saved theme before first paint
const saved = localStorage.getItem('mn-theme')
if (saved === 'light') {
document.documentElement.setAttribute('data-theme', 'light')
}

// Fire on every component mount — ensureToggle is idempotent so it only
// actually does work the first time the navbar is in the DOM.
Vue.mixin({
mounted () {
ensureToggle()
}
})

// Also re-check after each SPA navigation in case the button got removed.
router.afterEach(() => {
Vue.nextTick(ensureToggle)
})
}

function ensureToggle () {
if (document.querySelector('.mn-theme-toggle')) return

const links = document.querySelector('.navbar .links')
if (!links) return

const btn = document.createElement('button')
btn.className = 'mn-theme-toggle'
btn.setAttribute('aria-label', 'Toggle color theme')
syncIcon(btn)

btn.addEventListener('click', () => {
const isLight = document.documentElement.getAttribute('data-theme') === 'light'
if (isLight) {
document.documentElement.removeAttribute('data-theme')
localStorage.setItem('mn-theme', 'dark')
} else {
document.documentElement.setAttribute('data-theme', 'light')
localStorage.setItem('mn-theme', 'light')
}
syncIcon(btn)
})

links.appendChild(btn)
}

function syncIcon (btn) {
const isLight = document.documentElement.getAttribute('data-theme') === 'light'
btn.innerHTML = isLight ? moonSvg() : sunSvg()
}

function sunSvg () {
return `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>`
}

function moonSvg () {
return `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>`
}
48 changes: 32 additions & 16 deletions docs/.vuepress/public/css/mynode.css
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
.app_screenshot {
border-color: #000000;
border-radius: 20px;
border-style: solid;
border-width: 3px;
width: 50%;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 15px;
margin-bottom: 25px;
// Utility classes referenced directly in guide content.
// Theme overrides live in docs/.vuepress/styles/index.styl

.app_screenshot,
.app-screenshot {
border: 1px solid rgba(255, 255, 255, 0.10);
border-radius: 16px;
width: 60%;
max-width: 100%;
display: block;
margin: 20px auto 30px;
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.45);
}

.danger {
background: #ff0e0e64;
border-radius: 10px;
padding: 0.5em 1em;
background: rgba(248, 113, 113, 0.09);
border-left: 4px solid #f87171;
border-radius: 10px;
padding: 0.5em 1em;
color: rgba(255, 255, 255, 0.55);
}

.danger h2 {
border-bottom: None;
}
border-bottom: none;
color: #f87171;
}

@media (max-width: 719px) {
.app_screenshot,
.app-screenshot {
width: 88%;
}

.theme-default-content {
padding: 1.75rem 1.25rem 4rem !important;
}
}
Loading