CLI tool
liaoliao666/v2ex avatar
liaoliao666/v2ex

V2Fun is a third-party native client for the V2EX forum

V2EX 好看的第三方客户端,原生 App,支持夜间模式。

797 stars46 forksTypeScriptMIT

At a glance

What is it?
V2Fun is an Expo and React Native client for V2EX, a Chinese developer forum, published for iOS and Android with a night mode and its own URL scheme. It is a community client built on unofficial endpoints, and it moves fast with frequent releases.
Who is it for?
Adopt V2Fun if you use V2EX from a phone and want an unofficial client with a native feel, night mode and a URL scheme you can open from other apps. Do not build on it as if it were a stable public API, because the repository documents no API contract and the search and hot-topic features lean on two separate community services.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 34 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A native client for a forum with no official mobile app to match

V2Fun is described in the repository README as a good-looking third-party client for V2EX, a native app with night mode support. The name in the package manifest is v2ex, and the product name used in the README and the URL scheme is V2Fun.

V2EX itself is a Chinese community forum with topics tagged by node, and it is used heavily by software developers, which shapes who wants this app. The audience is people who read V2EX on a phone and who want the thread list, replies and search to feel like a native application rather than a wrapped web page. Night mode is called out in the description itself, which tells you the target user reads at night.

Distribution is split by platform. iOS users install from the App Store, and Android users take an apk from the project's GitHub releases page. There is no Google Play listing in the README, which is a normal arrangement for a community client and also means Android updates arrive when you fetch the apk again.

The project also keeps a policy surface, with privacy-policy and terms-and-conditions files in both English and Chinese, and an eas.json configuration for building with EAS. That combination of a store listing, a policy document and a build service is what a project looks like when it is aimed at end users rather than at developers of a library.

Expo and React Native underneath the native shell

The stack is stated in the README through its pointer to the Expo documentation, and the package manifest confirms it. Expo is pinned at the ~57.0.24 range with matching version numbers across a large set of expo packages, from expo-blur through expo-clipboard, expo-constants, expo-device, expo-file-system, expo-font, expo-image, expo-image-picker, expo-linking and expo-sharing.

The package scripts show the two ways the app is developed. The ios script runs expo run:ios, and a separate ios:sim script sets EXPO_UNSTABLE_HEADLESS=1 and REACT_NATIVE_PACKAGER_HOSTNAME=127.0.0.1 before doing the same, which is the headless variant used for simulator runs. A web script exists too, expo start --web, so the same codebase can be opened in a browser during development. The start script is expo start --offline, which launches the dev server without network access.

Around the Expo core sit the libraries that shape the interface. Navigation uses @react-navigation/native with both native-stack and drawer packages, so the app has a tab or stack hierarchy plus a drawer. Lists are rendered with @shopify/flash-list, and styling uses tailwind with tailwind.config.js at the root. The state layer is jotai, with a jotai directory in the tree, and server data goes through @tanstack/react-query.

The directory layout matches that picture: screens, components, navigation, utils, jotai, assets, plugins and a servicies directory hold the application code, while App.tsx, index.js, types.tsx and app.json are the entry points and configuration.

Running the app locally on a Mac

The README documents the local iOS setup, and it starts with the tools you are missing. iOS development needs Xcode, the Command Line Tools and CocoaPods, and the recommended way to get CocoaPods is Homebrew:

bash
brew install cocoapods

After that, confirm that pod --version runs, then start the app:

bash
yarn ios

The dependency choice is yarn, and a yarn.lock file is committed at the root alongside an .nvmrc that pins the Node version. The package manager matters here because the postinstall script applies patches:

json
"postinstall": "patch-package --error-on-fail"

patch-package runs on every install and fails the install if a patch does not apply, and there is a patches directory in the tree. In practice this means a dependency upgrade can break the install until the patches are updated, so treat the lockfile and the patches directory as one unit when you pull.

On first run, if there is no ios directory, Expo performs the prebuild automatically. The README explains that when you change native configuration or add a plugin that needs native settings, you sync manually with:

bash
npx expo prebuild --platform ios

The Android script is more involved, because it wires the emulator through a local proxy on port 7897 before launching:

bash
"android": "adb -s emulator-5554 reverse tcp:7897 tcp:7897 && adb -s emulator-5554 shell settings put global http_proxy 127.0.0.1:7897 && REACT_NATIVE_PACKAGER_HOSTNAME=127.0.0.1 expo run:android"

That script assumes a proxy tool listening on 7897 on the host and a specific emulator serial, which is the first thing you will have to adjust for your own machine.

A URL scheme for search, topics, members and nodes

V2Fun registers its own URL scheme so other applications can open a specific screen in the app. The README gives a table of four routes with their patterns and examples.

Search is addressed as v2fun://search/:query? with an optional query parameter, and the example opens a search for the Chinese text for how this application is. A topic is addressed as v2fun://topic/:id with the example v2fun://topic/904226, a member as v2fun://member/iliaoliao, and a node as v2fun://node/apple.

This is a small feature with a real effect on how the app fits into a workflow. A link shared in a chat app can open directly in the thread rather than in a browser, and a node name can be turned into a subscription shortcut.

The route naming is inconsistent, though, and it matters if you write integrations. Two of the four rows in the table are written as member/:username and node/:name without the v2fun:// prefix that the other two carry, so the scheme prefix is missing in the documentation for those two. If you are automating deep links, treat the pattern as unverified for member and node until you check the app's own link handling.

The manifest also includes expo-linking and expo-constants, and the app has a plugins directory, so the scheme is registered through the native project rather than being hard-coded in one place.

Search and hot topics lean on two other community services

The acknowledgements section names the projects the two most visible features are built on. V2HOT is described as a site that shows the day's hottest posts on V2EX, and the README says the historical hot feature is implemented on that basis. SOV2EX is described as a convenient V2EX site search engine, and the search function is implemented on that basis.

That is a sensible engineering decision and it defines the project's real dependency surface. V2Fun does not have to solve full-text search across a forum it does not index; it queries a service that already does. The trade-off is that two features now depend on services the project does not control, and a change in either one's response format or availability shows up inside the app.

The dependency list supports that reading. cheerio is present, which is an HTML parser, and @native-html/render appears alongside axios for HTTP requests. Parsing HTML rather than consuming a clean JSON API is consistent with reading a site that was built to be read by people, and it also means the app's own request patterns are shaped by whatever markup those services return.

For anyone forking or vendoring this client, the practical consequence is that you inherit a scraper-shaped data layer and should check both upstream services before assuming a feature will keep working.

Patches, eas.json and a fast release cadence

The maintenance picture is unusually active for a community client. The release history shows 1.9.4 on 2026-09-13, 1.9.5 on 2026-09-18 and 1.9.6 on 2026-09-19, and the last push was on 2026-09-19. The repository is not archived and the default branch is main.

A release every few days is what you would expect from a single-maintainer app chasing a fast-moving forum API, and it also means the app in the store and the code in the repository can differ by days. For a user this means frequent fixes and no long support tail. For a developer considering a fork, it means the main branch is a moving target and you should pin to a tag rather than track it.

The build configuration reflects the same approach. eas.json sits at the root for EAS builds, store.config.json holds store metadata, and there is a separate Dockerfile-like-user file for the like-user variant of the app, along with plugins and assets directories. The repository also carries privacy policy and terms documents in English and Chinese, which is what the app stores require for review.

The licence is MIT, stated in the README's licence section and held in the LICENSE file at the root. MIT is permissive enough that a fork, a rebuild or a redistribution carries no obligation beyond keeping the notice, which is why community clients like this one are easy to fork and rebrand.

The project also asks for contributions through its issue tracker, pointing newcomers at issues labelled good first issue, with separate labels for bugs and feature requests.

Editorial conclusion

Adopt V2Fun if you use V2EX from a phone and want an unofficial client with a native feel, night mode and a URL scheme you can open from other apps. Do not build on it as if it were a stable public API, because the repository documents no API contract and the search and hot-topic features lean on two separate community services. Verify first that the current release still works with your V2EX account, that the iOS build can be produced on a Mac with Xcode and CocoaPods, and that the Android apk you install comes from the project release page. The last push was on 2026-09-19 and version 1.9.6 was released the same day.

Frequently asked questions

How do I install V2Fun on iOS and Android?

The README points iOS users to the App Store listing and Android users to the apk in the project's GitHub releases. There is no Google Play listing mentioned in the documentation.

How do I run the V2Fun project locally for iOS development?

iOS development needs Xcode, the Command Line Tools and CocoaPods, and the README recommends installing CocoaPods with brew install cocoapods. After confirming pod --version works, run yarn ios, and use npx expo prebuild --platform ios to sync native configuration after changing plugins.

What URL scheme does V2Fun register?

The README documents v2fun://search/:query? for search, v2fun://topic/:id for a topic, member/:username for a member and node/:name for a node. The member and node rows in the documentation omit the scheme prefix, so treat those two patterns as unverified.

Which projects does V2Fun's search and hot topic feature rely on?

The README credits V2HOT, a site showing the day's hottest V2EX posts, for the historical hot feature, and SOV2EX, a V2EX site search engine, for the search feature. Both are external community services rather than parts of this repository.

What licence is V2Fun released under?

MIT, with the terms in the LICENSE file at the repository root and the README's licence section stating the same. Version 1.9.6 was released on 2026-09-19 and the last push was on the same day.

Official sources

  1. Issues
  2. liaoliao666/v2ex on GitHub
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/liaoliao666-v2ex.svg)](https://hysenlabs.com/projects/liaoliao666-v2ex)

Was this useful?