Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# GitHub Sponsors is pending for Coding Moves. Until it is approved,
# the Sponsor button points to the project's professional support page.
custom:
- "https://coding-moves.github.io/diskern/support"
2 changes: 2 additions & 0 deletions .github/workflows/deploy-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ jobs:

- run: npm run build
working-directory: site
env:
VITE_WISE_PAYMENT_URL: ${{ vars.VITE_WISE_PAYMENT_URL }}

# GitHub Pages has no server-side routing: a direct visit to
# /diskern/docs would 404 before React Router ever loads. Serving
Expand Down
3 changes: 3 additions & 0 deletions site/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Public Wise receiving/payment link only. This value is visible in the built site.
# Do not enter bank account details, passwords, or API tokens.
VITE_WISE_PAYMENT_URL=
5 changes: 5 additions & 0 deletions site/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ public/latest-release.json
*.njsproj
*.sln
*.sw?

# Local sponsorship configuration (commit only the empty example).
.env
.env.*
!.env.example
30 changes: 30 additions & 0 deletions site/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,33 @@ The Vite `base` in `vite.config.js` is set to `/diskern/` to match this
repo's GitHub Pages URL (`coding-moves.github.io/diskern/` or your
configured custom domain). If the repo is ever renamed, update `base`
to match.

## Configure Wise sponsorship

The Support page uses a public Wise receiving/payment link. Bank details are
managed in Wise, not in the desktop app or this repository.
Supporters follow the link directly; the site does not require an invoice
request or a conversation with the maintainer before payment when configured.

For local development, copy `.env.example` to `.env.local` in this directory.
Set this value to the HTTPS payment link copied from your Wise account:

```dotenv
VITE_WISE_PAYMENT_URL=
```

Paste the link after the equals sign, then restart `npm run dev`.
The local file is ignored by Git. Only HTTPS links on `wise.com` are accepted;
a missing or invalid link shows “Discuss sponsorship” instead.

For the live site, open repository **Settings → Secrets and variables →
Actions → Variables → New repository variable**. Name it
`VITE_WISE_PAYMENT_URL` and paste the same public link as its value.
After this PR is merged, run **Actions → Deploy site to GitHub Pages →
Run workflow** on `main` to publish the setting. Updating a variable alone
does not rebuild the site.

Vite embeds this value in public JavaScript. Gitignore and GitHub secrets do
not make browser-visible values private. Do not put account numbers, passwords,
or Wise API tokens here. The GitHub Sponsor button continues to point to the
Support page through `.github/FUNDING.yml`.
2 changes: 2 additions & 0 deletions site/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Routes, Route } from 'react-router-dom'
import Layout from './components/Layout.jsx'
import Home from './pages/Home.jsx'
import NotFound from './pages/NotFound.jsx'
import Support from './pages/Support.jsx'

// All routes share <Layout/> (nav + footer). To add a new page later —
// e.g. /docs or /changelog — create src/pages/Docs.jsx and add
Expand All @@ -11,6 +12,7 @@ export default function App() {
<Routes>
<Route element={<Layout />}>
<Route index element={<Home />} />
<Route path="support" element={<Support />} />
<Route path="*" element={<NotFound />} />
</Route>
</Routes>
Expand Down
5 changes: 4 additions & 1 deletion site/src/components/Footer.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Link } from 'react-router-dom'

export default function Footer() {
return (
<footer className="footer">
Expand All @@ -10,7 +12,8 @@ export default function Footer() {
>
View the code on GitHub
</a>
.
.{' '}
<Link to="/support">Support the project</Link>.
</p>
</footer>
)
Expand Down
4 changes: 4 additions & 0 deletions site/src/components/NavBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export default function NavBar() {
Diskern
</Link>

<nav className="nav-links" aria-label="Main navigation">
<Link to="/support">Support</Link>
</nav>

<div className="nav-actions">
<button
type="button"
Expand Down
88 changes: 88 additions & 0 deletions site/src/pages/Support.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
const REPO_URL = 'https://github.com/Coding-Moves/diskern'
const ORG_URL = 'https://github.com/Coding-Moves'
const CONTACT_URL = 'https://github.com/Muawiya-contact'

// Only publish a Wise HTTPS link; incomplete configuration keeps contact available.
function getWisePaymentUrl(value) {
try {
const url = new URL(value)
return url.protocol === 'https:' && url.hostname === 'wise.com' &&
!url.username && !url.password ? url.href : null
} catch {
return null
}
}

const WISE_PAYMENT_URL = getWisePaymentUrl(import.meta.env.VITE_WISE_PAYMENT_URL)

export default function Support() {
return (
<main className="support-page container">
<section className="support-hero" aria-labelledby="support-title">
<p className="support-eyebrow">Sponsor open source maintenance</p>
<h1 id="support-title">Support Coding Moves</h1>
<p className="support-lead">
Your sponsorship helps maintain Diskern and future Coding Moves
projects: development time, testing, releases, documentation,
design polish, and contributor support.
</p>
<div className="support-actions">
<a className="support-button support-button-primary" href={WISE_PAYMENT_URL || CONTACT_URL}>
{WISE_PAYMENT_URL ? 'Sponsor through Wise' : 'Discuss sponsorship'}
</a>
<a className="support-button" href={REPO_URL}>
View Diskern on GitHub
</a>
</div>
</section>

<section className="support-card" aria-labelledby="payment-title">
<h2 id="payment-title">Sponsor through Wise</h2>
<p>
Make a voluntary contribution to support ongoing maintenance.
{WISE_PAYMENT_URL
? ' Follow the link to see the recipient and payment options on Wise before sending.'
: ' Contact the maintainer to arrange a Wise payment.'}
</p>
<p>
You can use the Wise link directly without requesting an invoice
through this site. For sponsorship questions, visit the
{' '}<a href={CONTACT_URL}>maintainer’s profile</a> for contact options.
</p>
</section>

<section className="support-grid" aria-label="What sponsorship funds">
<article className="support-card">
<h2>What it funds</h2>
<ul>
<li>Core Rust engine work and safety improvements.</li>
<li>Desktop UI polish, performance, and release packaging.</li>
<li>Documentation, contributor guidance, and issue triage.</li>
<li>Testing across Linux, Windows, and future platforms.</li>
</ul>
</article>

<article className="support-card">
<h2>Current sponsor route</h2>
<ul>
<li>Payments are handled through Wise.</li>
<li>Future route: GitHub Sponsors once the account is approved.</li>
</ul>
</article>
</section>

<section className="support-card" aria-labelledby="trust-title">
<h2 id="trust-title">Thank you for supporting the project</h2>
<p>
Every contribution helps us spend more time improving Diskern and
supporting its contributors.
</p>
<p>
Explore more work from <a href={ORG_URL}>Coding Moves</a> or open a
discussion in the repository if you want to support a specific feature
area.
</p>
</section>
</main>
)
}
162 changes: 162 additions & 0 deletions site/src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -462,3 +462,165 @@ section {
padding: 22px;
}
}

/* ---------- Support ---------- */

.nav-links {
display: flex;
align-items: center;
gap: 16px;
margin-left: auto;
margin-right: 12px;
}

.nav-links a {
color: var(--text-muted);
font-size: 0.92rem;
font-weight: 600;
text-decoration: none;
}

.nav-links a:hover {
color: var(--text);
}

.support-page {
padding-top: 56px;
padding-bottom: 72px;
}

.support-hero {
padding: 64px 0 40px;
text-align: center;
}

.support-eyebrow {
margin: 0 0 12px;
color: var(--accent);
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
font-size: 0.78rem;
}

.support-hero h1 {
margin: 0 0 16px;
font-size: clamp(2rem, 5vw, 3rem);
letter-spacing: -0.03em;
}

.support-lead {
max-width: 720px;
margin: 0 auto;
color: var(--text-muted);
font-size: 1.08rem;
line-height: 1.7;
}

.support-actions {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 12px;
margin-top: 28px;
}

.support-button {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 44px;
padding: 0 18px;
border-radius: 10px;
border: 1px solid var(--border);
background: var(--bg-elevated);
color: var(--text);
font-weight: 700;
text-decoration: none;
transition:
border-color 0.15s ease,
background-color 0.15s ease,
transform 0.1s ease;
}

.support-button:hover {
transform: translateY(-1px);
border-color: var(--accent);
background: var(--bg-elevated-hover);
}

.support-button-primary {
background: var(--accent);
color: var(--accent-text);
border-color: var(--accent);
}

.support-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 16px;
padding: 0;
margin: 16px 0;
}

.support-card {
margin: 0 0 16px;
padding: 28px;
border: 1px solid var(--border);
border-radius: 16px;
background: var(--bg-elevated);
box-shadow: var(--shadow);
}

.support-card h2 {
margin: 0 0 12px;
font-size: 1.2rem;
}

.support-card p,
.support-card li {
color: var(--text-muted);
line-height: 1.65;
}

.support-card p {
margin: 0 0 12px;
}

.support-card p:last-child {
margin-bottom: 0;
}

.support-card ul {
margin: 0;
padding-left: 20px;
}

.support-card a {
color: var(--accent);
font-weight: 700;
text-decoration: none;
}

.support-card a:hover {
text-decoration: underline;
}

@media (max-width: 640px) {
.nav-inner {
gap: 10px;
}

.nav-links {
margin-left: 0;
margin-right: 0;
}

.support-page {
padding-top: 32px;
}

.support-card {
padding: 22px;
}
}
Loading