Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
675fa61
chore: restore pnpm and quality toolchain
fu050409 Aug 9, 2026
65a7940
feat: add normalized repository download model
fu050409 Aug 9, 2026
0ac79f1
refactor: rebuild frontend with Luma Base UI
fu050409 Aug 9, 2026
f8d0f71
test: add browser accessibility and bundle gates
fu050409 Aug 9, 2026
d8d4487
docs: record completed frontend refactor
fu050409 Aug 9, 2026
13e013d
docs: plan optional GitHub token flow
fu050409 Aug 9, 2026
771d92e
feat: add optional GitHub token queries
fu050409 Aug 9, 2026
09a2cc7
feat: polish product copy and mobile flow
fu050409 Aug 9, 2026
dbf5646
docs: record token and mobile completion
fu050409 Aug 9, 2026
a522a44
docs: plan shadcn form refinement
fu050409 Aug 9, 2026
34a0dd0
refactor: compose search form with shadcn fields
fu050409 Aug 9, 2026
3aa2aa0
docs: record shadcn form completion
fu050409 Aug 9, 2026
1bec836
docs: plan input group alignment regression
fu050409 Aug 9, 2026
c7e69b6
fix: lock input group addon alignment
fu050409 Aug 9, 2026
30300ff
docs: approve complete css budget
fu050409 Aug 9, 2026
7d205c7
build: align complete css bundle budget
fu050409 Aug 9, 2026
f8b17c0
docs: record input group alignment completion
fu050409 Aug 9, 2026
4488a60
docs: plan selective upstream sync
fu050409 Aug 9, 2026
f75c7cf
docs: require worker deployment rename
fu050409 Aug 9, 2026
f2310ca
chore: rename worker deployment target
fu050409 Aug 9, 2026
cc9524b
docs: record worker rename completion
fu050409 Aug 9, 2026
b5b5a15
chore: migrate canonical repository links
fu050409 Aug 9, 2026
b8bbb4f
fix: preserve proxied download filenames
fu050409 Aug 9, 2026
725cc65
feat: add base ui combobox primitive
fu050409 Aug 9, 2026
4045704
refactor: make release and asset selectors searchable
fu050409 Aug 9, 2026
648b1ce
test: harden searchable selector workflows
fu050409 Aug 9, 2026
47776c0
docs: record selective upstream sync completion
fu050409 Aug 9, 2026
ee30c52
docs: align data boundary with pr review
fu050409 Aug 9, 2026
0afaa20
refactor: query github directly from browser
fu050409 Aug 9, 2026
fe02107
docs: record pr review completion
fu050409 Aug 9, 2026
8b9a37d
chore: adjust to fit the viewport
Craun718 Aug 10, 2026
91d4661
chore: adjust to fit the viewport of api document
Craun718 Aug 10, 2026
b13bc8e
refactor: move download page to new page
Craun718 Aug 10, 2026
1a50fe2
feat: prefer release formats over config metadata in asset recommenda…
Craun718 Aug 10, 2026
7eaba50
docs: add first-screen design principle to documentation
Craun718 Aug 10, 2026
0eb4e10
test(e2e): improve stability of release selection expansion
Craun718 Aug 11, 2026
fecbf4f
Merge branch 'main' into refactor-v2
Craun718 Aug 11, 2026
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
48 changes: 28 additions & 20 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,42 +1,50 @@
name: Lint
name: Quality

on:
push:
branches: ["**"]

jobs:
lint-and-fix:
name: Lint and Fix
quality:
name: Typecheck, lint, test and build
runs-on: ubuntu-latest
permissions:
contents: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Markdown lint and fix
uses: DavidAnson/markdownlint-cli2-action@v20
- name: Install pnpm
uses: pnpm/action-setup@v4.1.0
with:
globs: |
"**/*.md"
fix: true
version: 11.9.0

- name: Install pnpm via corepack
run: corepack enable && corepack install

- name: Set node LTS
- name: Set Node.js
uses: actions/setup-node@v4
with:
node-version: latest
node-version: 24
cache: pnpm

- name: Install
run: pnpm install --frozen-lockfile

- name: Code Lint and Fix
run: pnpm lint:fix
- name: Typecheck
run: pnpm typecheck

- name: Commit and Push changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "chore: format and lint fix [skip ci]"
- name: Lint
run: pnpm lint

- name: Test
run: pnpm test

- name: Build
run: pnpm build

- name: Bundle budget
run: pnpm check:bundle

- name: Install Playwright browser
run: pnpm exec playwright install --with-deps chromium

- name: End-to-end and accessibility tests
run: pnpm test:e2e
70 changes: 70 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Repository instructions

@/Users/fu050409/.codex/RTK.md

## Source of truth

- `docs/DESIGN.md` is the authoritative and complete description of the current
workspace architecture, interaction design, constraints, priorities, and
acceptance criteria.
- Before developing any request, read `docs/DESIGN.md` and verify that it still
reflects the user's current request.
- If requirements or technical decisions change, update `docs/DESIGN.md`
first, then regenerate or reorder the unimplemented work in root `TODO.md`,
and only then implement code.
- `TODO.md` is a derived list of work that has not landed. It must never
override `docs/DESIGN.md`.
- When existing code, comments, historical conventions, or `TODO.md` conflict
with `docs/DESIGN.md`, follow `docs/DESIGN.md` unless the user explicitly
changes the requirement in the current conversation.

## Implementation gate

- Do not modify source code, styles, dependencies, build configuration, quality
configuration, generated components, or lockfiles until the user explicitly
asks to begin implementation or to modify code.
- Until that authorization is given, only inspection and maintenance of
planning/instruction documentation are allowed.
- Existing violations are migration tasks. Do not opportunistically fix them
while doing documentation or investigation work.

## Required frontend conventions

- Build the frontend with shadcn/ui using Luma style and Base UI
(`@base-ui/react`) primitives.
- Preserve the current light and dark OKLCH color tokens and overall color
palette exactly unless the user explicitly approves a palette change.
- Use Tailwind CSS for component and page styling. Keep global CSS limited to
Tailwind imports, design tokens, base reset, and unavoidable global rules.
- Keep the shadcn/ui-compatible layout and aliases, including reusable
primitives under `src/components/ui/` and utilities under `src/lib/`.
- shadcn/ui does not prescribe `app/`, `features/`, or `services/` layers. Do
not introduce those top-level directories solely as an architectural pattern;
preserve the Farm SPA entry points and pages, place composed business UI
under `src/components/`, and place API clients and pure utilities under
`src/lib/`.
- Every code filename must use kebab-case. Use kebab-case for code directories
as well. Component and type identifiers inside code may use PascalCase.
- Use Zustand for shared, asynchronous, or persistent client data. Put domain
models, stores, actions, selectors, schemas, and associated types under
`src/models/`.
- Do not keep duplicated state that can be derived by selectors.
- Keep pages in a first-screen design: keep content height as small as possible
and avoid requiring users to scroll vertically.

## Formatting and review

- Use Biome.js for formatting, linting, and import organization.
- JavaScript, TypeScript, JSX, and TSX use single quotes.
- Indent with spaces, never tabs, at 2 spaces per level.
- Biome must review checked-in shadcn/ui code as well as application code.
- Prefer read-only `biome check` during validation. Do not run write/fix mode
outside the explicitly authorized change scope.
- CI checks must not auto-fix and push commits to the user's branch.

## Completion discipline

- Follow the priority order in `docs/DESIGN.md` and root `TODO.md`.
- A task is complete only after relevant type checks, Biome checks, tests, and
builds pass, and after `docs/DESIGN.md` and `TODO.md` are synchronized with
the resulting implementation.
197 changes: 86 additions & 111 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,160 +1,135 @@
# ghproxy-plus

A GitHub release asset download service inspired by gh-proxy
ghproxy-plus finds a suitable GitHub Release asset for the current device and
downloads it through a self-hosted GitHub proxy. It also keeps the low-level
proxy API available for direct use.

This project is built with **React**, **Hono**, **Tailwind CSS**, and **shadcn/ui**.
Pages keep a first-screen design: content height should be as small as possible
and users should rarely need to scroll vertically. (页面保持首屏设计风格,页面内容
高度尽可能要小,尽量不要让用户上下滚动。)

**The old version is archived now. See v1 branch for the old version.**
Canonical repository: [Craun718/ghproxy-plus](https://github.com/Craun718/ghproxy-plus)

## Deploy
The frontend is a React 19 + Farm SPA. Its component layer uses shadcn/ui Luma
components generated on Base UI primitives, Tailwind CSS, and the existing
light/dark OKLCH palette. Shared repository state lives in a Zustand model and
all GitHub responses are normalized by the browser API client before reaching
the model or UI.
Searchable Release and Asset Comboboxes load on demand after repository results
arrive, while their transient search state remains local to each component.

### Cloudflare Workers (Recommended)
## Requirements

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/Craun718/ghproxy-plus.git)
- Node.js 22 or newer
- pnpm 11.9.0

Or deploy manually with wrangler:
Install the exact dependency graph:

```bash
pnpm deploy
pnpm install --frozen-lockfile
```

For local development with wrangler:
## Development

Run the frontend-only Farm server on `http://127.0.0.1:3000`:

```bash
pnpm dev:wrangler
pnpm dev
```

[Wrangler](https://developers.cloudflare.com/workers/wrangler/) is the official CLI for Cloudflare Workers, used here to deploy and manage the Workers deployment.

**Note:** Run `pnpm cf-typegen` to generate Cloudflare bindings types after updating `wrangler.jsonc`.

### Node.js

Clone the Repository
The Farm server can query public GitHub repositories directly from the browser.
To exercise `/api/ghproxy/` downloads as well, build the frontend and run the
complete Cloudflare Workers application locally with:

```bash
git clone https://github.com/your-username/ghproxy-plus.git
cd ghproxy-plus

# Install Dependencies
pnpm install

# Build the Project
pnpm build

# Start the Server
pnpm start
pnpm dev:wrangler
```

## API Manual

### 1. GitHub Proxy API
The main application is available at `/`; API documentation is route-lazy at
`/docs`. Cloudflare asset fallback is configured for direct SPA navigation and
refreshes on both routes.

## Architecture

```text
src/
api/ Hono API handlers
components/
ui/ shadcn/ui Luma + Base UI primitives
repository-download/ download workflow components
hooks/ URL state synchronization
lib/ API clients and pure matching/normalization
models/ Zustand state, schemas, types and selectors
pages/ route-level composition
globals.css Tailwind imports, tokens and global base rules
```

**Endpoint:** `/api/ghproxy/{github-url}`
The key request path is:

Proxies GitHub resources with CORS headers, allowing accelerated access to GitHub files, releases, and repositories.
```text
HomePage -> Zustand repository model -> browser GitHub API client
-> normalized repository/releases -> pure asset recommendation
-> /api/ghproxy/:github-url
```

**Supported URL Types:**
`docs/DESIGN.md` is the authoritative architecture and interaction contract.
Root `TODO.md` contains only work from that contract that has not landed.

- GitHub releases and archives: `github.com/{owner}/{repo}/releases/*`
- GitHub raw files: `github.com/{owner}/{repo}/blob/*` or `github.com/{owner}/{repo}/raw/*`
- GitHub raw content: `raw.githubusercontent.com/*` or `raw.github.com/*`
- GitHub gists: `gist.githubusercontent.com/*` or `gist.github.com/*`
- GitHub repository info: `github.com/{owner}/{repo}/info/*` or `github.com/{owner}/{repo}/git-*`
- GitHub tags: `github.com/{owner}/{repo}/tags/*`
## Quality checks

**Example:**
Run all non-browser checks, the production build, and the bundle budget:

```bash
curl https://your-domain.com/api/ghproxy/https://github.com/owner/repo/releases/download/v1.0.0/file.zip
pnpm check
```

**Response:**

- Success: Proxied content with CORS headers
- Error 400: Invalid or unsupported URL
- Error 403: URL blocked by whitelist (if configured)
- Error 500: Fetch error

---

### 2. Smart Download API

**Endpoint:** `/api/download/{github-repo-url}`

Automatically detects the user's operating system and architecture from the User-Agent header and downloads the most appropriate release asset from the latest release.

**Parameters:**

- `keyword` (optional): Additional keyword to filter assets
Install Chromium once and run desktop/mobile end-to-end checks:

**Example:**

~~curl -L [https://your-domain.com/api/download/https://github.com/owner/repo]~~

Don't fetch it! You can only access it through the browser.

**Detection Logic:**

- Parses User-Agent to determine OS (Windows, macOS, Linux, Android, iOS, etc.)
- Detects CPU architecture (x86_64, arm64, etc.)
- Automatically selects the best matching asset from the latest release
- Falls back to first asset if no match found

**Note:** The web UI provides an option to generate download URLs from the default branch when no releases are found.

**Response:**

- Success (302): Redirects to the download URL via `/api/ghproxy/`
- Error (302): Redirects to 404 page if repo not found or no suitable asset

---

### 3. Health Check API
```bash
pnpm exec playwright install chromium
pnpm test:e2e
```

**Endpoint:** `/api/ping`
The quality gates include TypeScript, read-only Biome checks, Vitest unit/model/
component tests, Farm production build, route bundle budgets, Playwright core
flows, target viewport overflow checks, keyboard navigation, axe, and Web
Vitals smoke budgets. CI runs the same gates without auto-fixing or committing
changes.

Health check endpoint that returns server status information.
## API

**Example:**
### GitHub proxy

```bash
curl https://your-domain.com/api/ping
```text
GET|HEAD /api/ghproxy/:github-url
```

**Response:**
Proxies supported GitHub release, archive, raw file, repository, tag, and gist
URLs with CORS response headers. Successful file responses force attachment
downloads and preserve the safely encoded filename from the original GitHub
URL across CDN redirects.

### Health check

```json
{
"message": "pong",
"uptime": 12345.67,
"timestamp": "2024-01-01T00:00:00.000Z",
"pid": 1234
}
```text
GET /api/ping
```

---
## Deployment

## Getting Started
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/Craun718/ghproxy-plus.git)

### Front-end Only
Deploy the Worker and `dist/` assets using Wrangler:

```bash
pnpm dev
pnpm deploy
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying files under `src/`. The page auto-updates as you edit.

### With Backend (Cloudflare Workers)

This runs the full stack with Hono API routes on Cloudflare Workers:
After changing Cloudflare bindings, regenerate their types with:

```bash
pnpm dev:wrangler
pnpm cf-typegen
```

## Thanks

[hunshcn/gh-proxy](https://github.com/hunshcn/gh-proxy)
The proxy core is derived from
[hunshcn/gh-proxy](https://github.com/hunshcn/gh-proxy).
10 changes: 10 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# ghproxy-plus 重构 TODO

> 权威方案:`docs/DESIGN.md`
>
> 当前状态:P13 资产推荐后缀与配置文件优先级已完成(2026-08-10)。

本文件只记录 `docs/DESIGN.md` 中尚未落地的工作。开始任何新需求前,必须先确认并
更新 `docs/DESIGN.md`,再按方案优先级把未实施事项写入本文件。

当前没有 `docs/DESIGN.md` 中尚未落地的重构事项。
Loading
Loading