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
6 changes: 6 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -81,6 +81,12 @@ pnpm dlx @varo/cli add --target weapp-vite button input card
- **渐进接入:** 先稳定构建链路,再按页面引入新写法,不要求一次性重写业务。
- **结果可验证:** 源码、发布记录、运行日志与截图链路公开,构建结果可以复现。

## 赞助与贡献者计划

已确认的开源赞助按净额拆成三桶:60% 核心维护、25% 贡献者基金、15% 周边开源。贡献者基金按季发放给有效合并的修复、功能、测试和文档,不是工资或兼职。

[中文规则](https://weapp.dev/contributors/) · [English](https://weapp.dev/en/contributors/) · [赞助页](https://weapp.dev/pricing/#sponsor)

## 维护者与许可

weapp.dev 由 [sonofmagic](https://github.com/sonofmagic) 发起并持续维护,汇集面向小程序开发的开源项目、文档与实践。
Expand Down
4 changes: 2 additions & 2 deletions apps/web/public/llms-full.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,8 +39,8 @@ Use the canonical project pages and linked official sources as the authority for

## Delivery and sponsorship

The delivery page at https://weapp.dev/pricing/ describes what can be delivered today and what remains on the roadmap. Human-delivered migration and training services are available by discussion. Cloud builds, official templates, and private component registries are still in development.
The delivery page at https://weapp.dev/pricing/ describes what can be delivered today and what remains on the roadmap. Human-delivered migration and training services are available by discussion. Cloud builds, official templates, and private component registries are still in development. The contributor program at https://weapp.dev/contributors/ explains how confirmed sponsorship is shared with people who land eligible work.

Open-source sponsorship uses one-time permanent recognition tiers: ¥20 supporter, ¥200 Bronze, and ¥1,000 Silver. ¥200 and above may display a GitHub avatar, username, and profile link after GitHub identity confirmation, maintainer review, and explicit authorization. Approved records may be shown on weapp.dev, tw.weapp.dev, and vite.weapp.dev. Gold business partnerships follow icebreaker.top terms: ¥2,000 for one-site monthly advertising, ¥3,000 for dual-site monthly advertising, ¥8,000 for a dual-site quarterly partnership, or custom discussion.

20% of sponsorship income funds mini-app ecosystem open-source projects. The remaining funds support weapp.dev maintenance, documentation, testing, build infrastructure, and community operations; destinations are announced monthly or quarterly. Sponsorship is not a purchase of technical support, templates, cloud-build minutes, or subscription access, and public recognition never exposes payment amounts or private ledger data.
Confirmed open-source sponsorship is split net of payment fees: 60% core maintenance, 25% contributors fund, and 15% nearby open source. The contributors fund pays quarterly thank-you amounts for eligible merged work and optional bounties; if a quarter is under ¥500 it rolls forward. Product revenue such as future Pro, Team, or implementation fees stays out of this fund. Destinations are announced quarterly. Sponsorship is not a purchase of technical support, templates, cloud-build minutes, or subscription access, and public recognition never exposes payment amounts or private ledger data.
5 changes: 4 additions & 1 deletion apps/web/public/llms.txt
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@
- [Varo](https://weapp.dev/projects/varo/): Registry-first editable components, primitives, business blocks, and Agent UI for H5 and weapp-vite mini-programs.
- [English project index](https://weapp.dev/en/): English overview of the stack.
- [Delivery and sponsorship](https://weapp.dev/pricing/): Human migration services, roadmap status, and one-time open-source sponsorship tiers.
- [Contributor program](https://weapp.dev/contributors/): Quarterly sharing of confirmed sponsorship with eligible contributors.

## Official sources

Expand All@@ -27,7 +28,7 @@
- One-time tiers: ¥20 supporter, ¥200 Bronze, and ¥1,000 Silver.
- ¥200 and above may receive public GitHub link recognition after identity confirmation, maintainer review, and explicit authorization.
- Approved public recognition can be synchronized across weapp.dev, tw.weapp.dev, and vite.weapp.dev.
- 20% of sponsorship income is allocated to mini-app ecosystem open-source projects; destinations are announced monthly or quarterly.
- Confirmed sponsorship is split 60% core maintenance, 25% contributors fund, and 15% nearby open source; destinations are announced quarterly.
- Sponsorship is not a purchase of technical support, templates, cloud-build minutes, or subscription access.

## Canonical pages
Expand All@@ -36,6 +37,8 @@
- [English homepage](https://weapp.dev/en/)
- [Chinese privacy notice](https://weapp.dev/privacy/)
- [English privacy notice](https://weapp.dev/en/privacy/)
- [Chinese contributor program](https://weapp.dev/contributors/)
- [English contributor program](https://weapp.dev/en/contributors/)
- [Release feed](https://weapp.dev/releases.xml)
- [Sitemap](https://weapp.dev/sitemap-index.xml)

Expand Down
2 changes: 2 additions & 0 deletions apps/web/scripts/validate-build.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,6 +18,8 @@ const expectedFiles = [
'en/projects/weapp-vite/index.html',
'privacy/index.html',
'en/privacy/index.html',
'contributors/index.html',
'en/contributors/index.html',
'en/projects/varo/index.html',
'releases.xml',
'sitemap-index.xml',
Expand Down
111 changes: 111 additions & 0 deletions apps/web/src/components/ContributorsPage.astro
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
---
import { ArrowRight, Heart } from '@lucide/astro'
import type { Locale } from '../types/project'
import { localizePath, siteCopy } from '../i18n/ui'
import { buttonSecondary, section, shell } from '../styles/classes'

interface Props {
locale: Locale
}

const { locale } = Astro.props
const copy = siteCopy[locale].contributors
---

<main id="main-content">
<section class:list={[section, shell]}>
<header data-reveal class="mb-16 grid grid-cols-[.7fr_1.3fr] gap-16 max-[820px]:mb-12 max-[820px]:grid-cols-1 max-[820px]:gap-8">
<div>
<p class="mb-3 font-mono text-xs font-[650] text-brand">{copy.eyebrow}</p>
<h1 class="mb-5 text-[58px] font-[690] max-[720px]:text-[42px]">{copy.title}</h1>
<p class="mb-0 font-mono text-xs text-copy-muted">{copy.updated}</p>
</div>
<div class="self-end">
<p class="mb-6 max-w-[680px] text-xl leading-[1.6] text-copy-muted max-[720px]:text-lg">{copy.description}</p>
<a class={buttonSecondary} href={localizePath(locale, '/pricing/#sponsor')} data-analytics-event="navigate_page" data-analytics-page="pricing">
{copy.pricingAction}
<ArrowRight size={17} stroke-width={1.8} aria-hidden="true" />
</a>
</div>
</header>

<section data-reveal class="mb-20" aria-labelledby="allocation-title">
<h2 id="allocation-title" class="mb-6 text-xl font-[650]">{copy.allocationTitle}</h2>
<div class="contributors-bucket-grid">
{copy.buckets.map(bucket => (
<article>
<Heart class="mb-6 text-brand" size={22} stroke-width={1.7} aria-hidden="true" />
<strong class="mb-2 block font-mono text-[2rem] font-[720] leading-none">{bucket.share}</strong>
<h3 class="mb-2 text-lg font-[660]">{bucket.name}</h3>
<p class="mb-0 text-sm leading-[1.7] text-copy-muted">{bucket.body}</p>
</article>
))}
</div>
</section>

<div class="grid grid-cols-[280px_1fr] items-start gap-16 max-[820px]:grid-cols-1 max-[820px]:gap-10">
<nav data-reveal class="sticky top-24 border-t border-line max-[820px]:static" aria-label={copy.contents}>
<h2 class="py-4 font-mono text-xs font-[650] text-copy-muted">{copy.contents}</h2>
{copy.sections.map((sectionCopy, index) => (
<a class="block border-t border-line py-3 text-sm font-[590] transition-colors hover:text-brand" href={`#contributors-section-${index + 1}`}>{sectionCopy.title}</a>
))}
</nav>
<div class="border-t border-line">
{copy.sections.map((sectionCopy, index) => (
<section data-reveal id={`contributors-section-${index + 1}`} class="scroll-mt-24 border-b border-line py-9">
<h2 class="mb-4 text-[27px] font-[660]">{sectionCopy.title}</h2>
<p class="mb-0 max-w-[820px] leading-[1.8] text-copy-muted">{sectionCopy.body}</p>
</section>
))}

<section data-reveal class="scroll-mt-24 border-b border-line py-9">
<h2 class="mb-4 text-[27px] font-[660]">{copy.weightsTitle}</h2>
<table class="contributors-table w-full border-collapse text-left text-sm">
<tbody>
{copy.weights.map(weight => (
<tr>
<th scope="row" class="w-16 font-mono text-brand">{weight.points}</th>
<td class="font-[650]">{weight.name}</td>
<td class="text-copy-muted">{weight.rule}</td>
</tr>
))}
</tbody>
</table>
</section>

<section data-reveal class="scroll-mt-24 border-b border-line py-9">
<h2 class="mb-4 text-[27px] font-[660]">{copy.reposTitle}</h2>
<ul class="m-0 mb-4 grid list-none gap-2 p-0">
{copy.repos.map(repo => (
<li>
<a class="inline-flex items-center gap-2 text-sm font-[620] hover:text-brand" href={repo.url} target="_blank" rel="noreferrer">{repo.name}</a>
</li>
))}
</ul>
<p class="mb-0 max-w-[820px] text-sm leading-[1.8] text-copy-muted">{copy.reposNote}</p>
</section>

<section data-reveal class="scroll-mt-24 py-9">
<h2 class="mb-4 text-[27px] font-[660]">{copy.payoutTitle}</h2>
<ol class="m-0 grid max-w-[820px] list-decimal gap-3 py-0 pl-5 text-sm leading-[1.8] text-copy-muted">
{copy.payout.map(item => <li>{item}</li>)}
</ol>
</section>
</div>
</div>
</section>
</main>

<style is:global>
.contributors-bucket-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; overflow: hidden; border: 1px solid var(--border); background: var(--border); }
.contributors-bucket-grid article { min-height: 210px; padding: 1.75rem; background: var(--surface); }
.contributors-table th, .contributors-table td { padding: .9rem .75rem .9rem 0; border-bottom: 1px solid var(--border); vertical-align: top; }
@media (max-width: 760px) {
.contributors-bucket-grid { grid-template-columns: 1fr; }
.contributors-bucket-grid article { min-height: 0; }
.contributors-table, .contributors-table tbody, .contributors-table tr, .contributors-table th, .contributors-table td { display: block; width: 100%; }
.contributors-table th { padding-bottom: .2rem; }
.contributors-table td { border-bottom: 0; }
.contributors-table tr { border-bottom: 1px solid var(--border); padding: .75rem 0; }
}
</style>
1 change: 1 addition & 0 deletions apps/web/src/components/Footer.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -40,6 +40,7 @@ const copy = siteCopy[locale]
</a>
<a class="mb-3 flex w-fit items-center gap-2 text-sm hover:text-brand" href={localizePath(locale, '/privacy/')}>{copy.footer.privacy}</a>
<a class="mb-3 flex w-fit items-center gap-2 text-sm hover:text-brand" href={localizePath(locale, '/pricing/')} data-analytics-event="navigate_page" data-analytics-page="pricing">{copy.nav.pricing}</a>
<a class="mb-3 flex w-fit items-center gap-2 text-sm hover:text-brand" href={localizePath(locale, '/contributors/')} data-analytics-event="navigate_page" data-analytics-page="contributors">{copy.footer.contributors}</a>
<a class="mb-3 flex w-fit items-center gap-2 text-sm hover:text-brand" href="/releases.xml" data-analytics-event="navigate_section" data-analytics-section="release_feed">
<Rss size={15} stroke-width={1.8} aria-hidden="true" />
{copy.footer.releases}
Expand Down
21 changes: 18 additions & 3 deletions apps/web/src/components/PricingPage.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -100,7 +100,20 @@ const planIcons = [Layers2, Cloud, LockKeyhole, ShieldCheck]
</div>
<div data-reveal class="pricing-sponsor-allocation">
<p class="mb-2 font-[650]">{locale === 'zh-CN' ? '资金去向' : 'Where it goes'}</p>
<p class="mb-0 text-sm leading-[1.7] text-copy-muted">{pricing.sponsorAllocation}</p>
<p class="mb-6 max-w-[760px] text-sm leading-[1.7] text-copy-muted">{pricing.sponsorAllocation}</p>
<div class="pricing-allocation-grid">
{pricing.sponsorAllocationBuckets.map(bucket => (
<article>
<strong class="mb-2 block font-mono text-[1.6rem] font-[720] leading-none">{bucket.share}</strong>
<h3 class="mb-2 text-base font-[660]">{bucket.name}</h3>
<p class="mb-0 text-sm leading-[1.7] text-copy-muted">{bucket.body}</p>
</article>
))}
</div>
<a class="mt-6 inline-flex items-center gap-2 text-sm font-[650] hover:text-brand" href={localizePath(locale, '/contributors/')} data-analytics-event="navigate_page" data-analytics-page="contributors">
{pricing.sponsorAllocationAction}
<ArrowRight size={16} stroke-width={1.8} aria-hidden="true" />
</a>
</div>
<p data-reveal class="mt-5 mb-0 text-xs text-copy-muted">{pricing.sponsorNote}</p>
<div data-reveal class="pricing-public-sponsors">
Expand DownExpand Up@@ -229,7 +242,9 @@ const planIcons = [Layers2, Cloud, LockKeyhole, ShieldCheck]
.pricing-sponsor-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; overflow: hidden; border: 1px solid var(--border); background: var(--border); }
.pricing-sponsor-tier { display: flex; flex-direction: column; min-width: 0; min-height: 280px; padding: 1.75rem; background: var(--surface); }
.pricing-sponsor-button { margin-top: auto; width: fit-content; }
.pricing-sponsor-allocation { max-width: 760px; margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--border); }
.pricing-sponsor-allocation { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--border); }
.pricing-allocation-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; overflow: hidden; border: 1px solid var(--border); background: var(--border); }
.pricing-allocation-grid article { min-width: 0; min-height: 148px; padding: 1.25rem; background: var(--surface); }
.pricing-public-sponsors { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
.pricing-public-sponsor-list { display: grid; gap: 1.25rem; }
.pricing-public-sponsor-group ul { display: flex; flex-wrap: wrap; gap: .75rem; }
Expand All@@ -253,6 +268,6 @@ const planIcons = [Layers2, Cloud, LockKeyhole, ShieldCheck]
.pricing-cta .button-primary { background: var(--accent); color: var(--accent-contrast); }
@media (max-width: 1000px) { .pricing-plan-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 1000px) { .pricing-sponsor-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 760px) { .pricing-hero-inner { grid-template-columns: 1fr; gap: 2rem; min-height: 0; padding-top: 3.5rem; padding-bottom: 3.5rem; } .pricing-template-grid, .pricing-boundary-grid, .pricing-sponsor-grid { grid-template-columns: 1fr; } .pricing-service-list article { grid-template-columns: 2rem 1fr; padding: 1.2rem 0; } .pricing-service-list article > strong { grid-column: 2; } }
@media (max-width: 760px) { .pricing-hero-inner { grid-template-columns: 1fr; gap: 2rem; min-height: 0; padding-top: 3.5rem; padding-bottom: 3.5rem; } .pricing-template-grid, .pricing-boundary-grid, .pricing-sponsor-grid, .pricing-allocation-grid { grid-template-columns: 1fr; } .pricing-service-list article { grid-template-columns: 2rem 1fr; padding: 1.2rem 0; } .pricing-service-list article > strong { grid-column: 2; } }
@media (max-width: 560px) { .pricing-plan-grid { grid-template-columns: 1fr; } .pricing-plan { padding: 1.4rem; } .pricing-plan ul { min-height: 0; } .pricing-template { min-height: 0; } }
</style>
14 changes: 14 additions & 0 deletions apps/web/src/i18n/ui.test.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
import { describe, expect, it } from 'vitest'
import { siteCopy } from './ui'

describe('sponsorship allocation copy', () => {
it('keeps Chinese and English buckets at 60/25/15', () => {
for (const locale of ['zh-CN', 'en'] as const) {
const buckets = siteCopy[locale].pricing.sponsorAllocationBuckets
const shares = buckets.map(bucket => Number.parseInt(bucket.share, 10))
expect(shares).toEqual([60, 25, 15])
expect(shares.reduce((sum, share) => sum + share, 0)).toBe(100)
expect(siteCopy[locale].contributors.buckets.map(bucket => bucket.share)).toEqual(['60%', '25%', '15%'])
}
})
})
Loading
Loading