# vue-realworld-example-app: a Vue 3 codebase that passes the RealWorld e2e suite

> The repository is a Vue 3, Pinia and Vite implementation of the RealWorld spec, tested with the official Playwright suite. It is a reference codebase for reading, not a starter kit, and its README says so indirectly by keeping the spec in a submodule.

**realworld-apps/vue-realworld-example-app** — An exemplary real-world application built with Vue.js, Vuex, axios and different other technologies. This is a good example to discover Vue for beginners.

- Repository: https://github.com/realworld-apps/vue-realworld-example-app
- Website: https://vue-vuex-realworld.netlify.com
- Stars: 4,072 · Forks: 1,312
- Language: Vue
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/realworld-apps-vue-realworld-example-app

## What vue-realworld-example-app is, and who it is written for

RealWorld is a specification for a Medium-style blogging frontend: register, log in, write articles, comment, follow authors, favourite posts, paginate feeds. Implementations in different frameworks are expected to behave identically against the same API, so the value of any one of them is that you can compare it with the others on equal terms. This repository is the Vue entry. The README describes it as a "Vue 3 codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API", and the package description calls it "TodoMVC for the RealWorld".

The audience is narrower than the phrase "real world" suggests. This is a reading exercise for developers who already know some Vue and want to see a full application assembled: Composition API with `<script setup>`, Pinia stores, Vue Router, a fetch wrapper, markdown rendering, date formatting, pagination. It is not a scaffold. There is no CLI generator, no plugin system, no documented way to strip the demo content and keep the plumbing. If you want a starting point for a product, you are expected to copy patterns out of it, not to fork it.

## How the Vue 3 app is wired: Pinia stores, a fetch wrapper and a submodule

The architecture is deliberately thin. Pages and components live under `src/`, state lives in Pinia stores, and every network call goes through one module, `src/common/api.service.js`, which the README describes as "a thin `fetch` wrapper instead of axios". That single choke point is the most instructive part of the codebase: authentication headers, error handling and JSON parsing are handled once rather than in each component, and swapping backends means changing one base URL rather than auditing every view.

Two dependencies are worth noting because they show up in the data flow. Article bodies are markdown, rendered with `marked` and then sanitised with `DOMPurify` before insertion, which is the correct order and a detail many example apps get wrong. Timestamps go through `date-fns`. The visual theme is not in the repository at all: it is imported in `src/main.js` from `realworld/assets/theme/styles.css`, a path inside the vendored `realworld` git submodule, so the CSS that ships with the app is the same file the spec's templates and e2e selectors are written against. That keeps the app visually in sync with the test contract, and it also means the repository cannot be cloned shallowly and still work.

The stack list in the README is specific: Vue 3 with Pinia and Vue Router 5, Vite via `@vitejs/plugin-vue`, Bun as package manager and script runner, and Playwright running the official RealWorld e2e suite. The `package.json` confirms the dependency versions and the script names.

## Installing vue-realworld-example-app and running it locally

The README is explicit that the submodule is not optional, because the app imports its theme from there. Clone with submodules, or initialise them afterwards in an existing clone:

```bash
git clone --recurse-submodules https://github.com/realworld-apps/vue-realworld-example-app
# or, in an existing clone:
git submodule update --init
```

Install dependencies with Bun and start the dev server. The README states the server listens on port 8080:

```bash
bun install
bun run serve
```

You should see Vite report a local URL at `http://localhost:8080`. The backend defaults to `https://api.realworld.show/api`, so the app works against a hosted API without further setup. To point it at your own spec-compliant backend, set `VITE_API_URL`, either in the shell or in an `.env.local` file:

```bash
VITE_API_URL=http://localhost:8000/api bun run serve
```

For a production build, the README gives two commands, `bun run build` followed by `bun run preview`. To run the official end-to-end suite, install the Playwright browser first, then run the test script. The README notes that Playwright starts the Vite dev server itself, configured in `playwright.config.ts`:

```bash
bunx playwright install --with-deps chromium
bun run test
```

Linting and formatting are separate scripts, `bun run lint` for ESLint with `eslint-plugin-vue` and `bun run format` for Prettier. The README makes the division of labour clear: Prettier only formats, while `eslint-plugin-vue` is described as the only linter that understands Vue single-file component templates, and `eslint-config-prettier` turns off the stylistic ESLint rules so the two tools do not conflict.

## Where the codebase stops short

The most obvious limitation is the one the README itself flags: there is no upgrade path documented for the Vue 2 line. The original implementation is kept as a "frozen reference" at `realworld-apps/vue-2-realworld-example-app`, and the README notes that Vue 2 reached end of life on December 31, 2023. If you are maintaining a Vue 2 application, this repository shows you where the framework went, but it does not describe a migration route, and the README points to a commercial support offering for teams that cannot move. That is a statement about the Vue 2 repository, not a migration guide for yours.

Second, the submodule coupling is a real operational cost. The theme, the spec and the e2e tests all arrive through one git submodule. Anyone who clones without `--recurse-submodules`, or who works in an environment that strips submodules, gets an app with no stylesheet and a test suite that cannot run. CI configuration for that is on you; the repository layout shows a `.github/` directory but the README does not describe the workflows.

Third, the test strategy is end-to-end only. The scripts in `package.json` are `test`, `test:e2e`, `test:e2e:security` and `format:check`; there is no unit test runner listed. That is a defensible choice for a spec-conformance demo, where the contract is behavioural, but it means the repository is not a good model for how to structure fast unit tests in a Vue 3 application, and it gives you no example of component-level testing with a mocking library.

Finally, this is the wrong tool if you need a production template. There is no authentication token refresh strategy documented, no error boundary pattern, no i18n, no deployment configuration beyond a Netlify demo URL. Treat it as a specimen.

## The Vue 2 repository as the alternative, and what actually differs

The natural comparison is the sibling repository the README names, `realworld-apps/vue-2-realworld-example-app`. Both implement the same specification against the same API, so the difference is not in features but in the framework generation and the tooling around it. The Vue 2 codebase uses the Options API and the Vuex store pattern, and it is kept frozen: the README describes it as a place "for studying patterns and comparing frameworks", not as a base for new work.

This repository replaces Vuex with Pinia, uses the Composition API with `<script setup>`, and builds with Vite rather than the older toolchain. The README also notes that the original was created by Emmanuel Vilsbol and the `gothinkster/vue-realworld-example-app` contributors, so the lineage is direct rather than a parallel reimplementation. If your goal is to compare state management approaches in Vue, reading both side by side is the point of having two repositories. If your goal is to build something new, the Vue 2 version is out on lifecycle grounds alone and the choice is not close.

## Maintenance, licence and what an upgrade would cost you

The repository is not archived, and the last push was on 2026-06-10. There is one release in the record, tagged `build-1`, dated the same day. That is recent enough that the code is not abandoned, but the release history gives no signal about cadence, and the README documents no versioning or upgrade policy. Dependency versions in `package.json` are caret ranges, so a fresh `bun install` will pull newer minor and patch releases than the author last ran; `bun.lock` is committed, which is what keeps a clean install reproducible if you use it.

The licence is MIT, which is permissive and places few obligations on reuse beyond preserving the copyright notice and licence text. That is a statement about the licence file, not legal advice; if you plan to ship derived code, read `LICENSE` and the licences of the dependencies yourself. One dependency detail matters here: the theme and the spec test suite come from the `realworld` submodule, which is a separate project with its own licence, and the README does not discuss what that means for redistribution. That is the question to resolve before copying the CSS into a commercial product.

The upgrade cost is mostly the submodule. Keeping the app in step with the spec means updating the submodule pointer, and because the stylesheet is imported from inside it, a spec update can change your visuals and your test selectors in the same commit.

## Conclusion

Read this repository if you want a complete Vue 3 application whose auth, routing and pagination behaviour is checked by a shared spec suite, and if you are comfortable running Bun and a Playwright browser install. Do not adopt it as the base of a product: it is a demonstration app with no documented upgrade path, and its theme and tests are imported from a git submodule rather than owned by the repository. Verify first that `git submodule update --init` has populated `realworld/assets/theme/styles.css`, because the app imports its CSS from there in `src/main.js` and will not render correctly without it.

## FAQ

### Can you provide some examples of Vue code from vue-realworld-example-app?

The repository is a full Vue 3 application rather than a snippet collection. The README points to `src/common/api.service.js` as a thin fetch wrapper, and the app uses the Composition API with `<script setup>` alongside Pinia stores and Vue Router.

### Is there a Vue app in the RealWorld project?

Yes. The README describes this repository as a Vue 3 codebase adhering to the RealWorld spec and API, and it is tested with the official RealWorld Playwright e2e suite vendored as a git submodule.

### What are some realworld apps available?

The README links to CodebaseShow for the same application built with other stacks, and to the RealWorld project itself for the spec. Within this repository's own material, the named sibling is the frozen Vue 2 implementation at `realworld-apps/vue-2-realworld-example-app`.

## Sources

- [License: MIT](https://github.com/realworld-apps/vue-realworld-example-app/blob/master/LICENSE)
- [Project website](https://vue-vuex-realworld.netlify.com)
- [README](https://github.com/realworld-apps/vue-realworld-example-app/blob/master/README.md)
- [realworld-apps/vue-realworld-example-app on GitHub](https://github.com/realworld-apps/vue-realworld-example-app)
- [Releases](https://github.com/realworld-apps/vue-realworld-example-app/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/realworld-apps-vue-realworld-example-app
