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
149 changes: 149 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# Contributing to opx77_doc

Thanks for helping. This file is how the documentation site is built and how its
pages are written. The reviewer rules for the framework itself are on the site:
[Contributing](content/docs/guides/contributing.mdx). The organization-wide guide is
[here](https://github.com/opx77-framework/.github/blob/main/CONTRIBUTING.md).

Questions go to [Discord](https://discord.gg/xpSuYgEYsU). A page that is wrong can be
reported with the *Documentation issue* form.

## Workflow

- Nothing is pushed to `main` directly: `main` is deployed to GitHub Pages on every
push. Branch (`docs/<thing>`, `fix/<thing>`), push, open a pull request.
- A pull request runs the same build as a deployment, without deploying.
- **Nothing is documented that was not read in the code.** Link the framework commit
or pull request a page change follows (for example "sync opx_infinity #88–#95").
- Commit messages: `docs: <what the pages say now>`, and a body naming the framework
changes it follows.

## Before you push

```bash
npm ci
node scripts/check-content.mjs # MDX compiles, front matter, links, anchors
npm run types:check
npm run build
npm run check:api # with opx_infinity and opx_lib checked out next to this repo
```

## Stack

A [Fumadocs](https://fumadocs.dev) site on Next.js, exported as static HTML and
modelled on the [overextended docs](https://github.com/overextended/overextended.github.io):
fumadocs-core / fumadocs-ui 16, fumadocs-mdx 15, Next 16, React 19, Tailwind v4,
Orama static search. Node 24 and npm (`package-lock.json` is committed).

```text
content/docs/ the pages (.mdx) and the sidebar order (meta.json per folder)
├── index.mdx introduction: where to start
├── getting-started/ install, configure, troubleshooting
├── opx_infinity/ overview, concepts/, core/ (OPX.*, config, events, lib/, error codes),
│ then one folder per module: index (commands, config, codes),
│ server, client, events
├── opx_lib/ one page per Lib module
├── creators/ server/ and client/: one page per export; events
├── guides/ write a module, write a resource, convert, contribute
└── migration/ from opx77_* to opx_infinity, release notes

app/ Next routes: home, /docs, search index, llms.txt,
anchors.json and the old-URL redirect pages
lib/legacy.ts every URL the old MkDocs site served -> its new page
scripts/
├── check-content.mjs MDX compiles, front matter, internal links and anchors
├── anchors.mjs what counts as an anchor (shared by both checks)
├── check-api-coverage.sh fails on a published name the docs do not document
└── dump-surface.lua boots opx_infinity on its stub host and prints that surface
```

## How the pages are written

The overextended style: snippets explain, prose stays short.

- Front matter: `title` and a one-sentence `description` (shown under the title).
- A function, export or event is one heading with its anchor, a one-line
description, the call as a `lua` snippet, a **Parameters** list and a
**Returns** list with types, then a tiny `Example`:

````mdx
## SetWeather [#server-weather-setweather]

Crosses to a weather and reschedules the next roll.

```lua
weather.SetWeather(name, transitionSeconds, reason)
```

**Parameters**
- name: `string`
- transitionSeconds?: `number`

**Returns**
- `Result` — errors `no_presets`, `unknown_preset`, `invalid_transition`
````

- Commands, config keys and refusal codes are tables on the module's index
page, with `<a id="…" />` in the first cell.
- Every published name has an anchor; the rule is in
[Contributing](content/docs/guides/contributing.mdx).
- Nothing is documented that was not read in the code. The code is the source
of truth, not the framework manual (`docs/MANUAL.md`).
- Outside code, `{`, `}` and `<` are JSX in MDX: keep them in backticks.

## Adding a module

1. Create `content/docs/opx_infinity/<id>/` with `index.mdx`, `server.mdx`,
`client.mdx`, `events.mdx` (only those it has) and a `meta.json`, copying
an existing module (`weather` is the smallest complete one).
2. Add `<id>` to `content/docs/opx_infinity/meta.json` (alphabetical) and a row
to the module list in `content/docs/opx_infinity/index.mdx`.
3. Run the checks below.

## Building locally

```bash
npm ci
npm run dev # http://localhost:3000/opx77_doc/
npm run build # static export to out/
npm run types:check
node scripts/check-content.mjs
```

`npm start` serves `out/` (open `/opx77_doc/`).

## Checking API coverage

The framework lives in other repositories, so the check needs checkouts of
`opx_infinity` and `opx_lib`, desktop **Lua 5.4** (`lua5.4` or `lua`) and Node:

```bash
npm run check:api # finds ../opx_infinity, ../../opx_infinity or ../../../opx_infinity
./scripts/check-api-coverage.sh /path/to/opx_infinity
OPX_INFINITY=/path/to/opx_infinity OPX_LIB_PATH=/path/to/opx_lib ./scripts/check-api-coverage.sh
```

It does not grep the framework. `scripts/dump-surface.lua` boots the real
manifest on the framework's own stub host (`opx_infinity/tests/host.lua`) and
prints every module, contract member, command, alias, Open77 export, network
event, module event, page channel, config key and `OPX.*` function that is
actually registered; `opx_lib`'s functions are read from its source. The check
then fails on any name without its anchor in the right folder of
`content/docs`. With no framework checkout in reach it prints a note and exits
0, which is what happens on the CI runner.

## Old URLs

The MkDocs site served pages such as `/opx77_doc/modules/weather/`. Each of
those paths (and every path the MkDocs `redirects` plugin already forwarded)
is exported as a small page that forwards to its new home, keeping the
`#fragment` when a page still defines that anchor (looked up in
`/opx77_doc/anchors.json`). The list is `lib/legacy.ts`.

## Deployment

Pushing to `main` runs `.github/workflows/deploy.yml`: `npm ci`, content check,
coverage check (a skip on CI), type check, `npm run build`, then the `out/`
directory is deployed to GitHub Pages. Pull requests run the same build
without deploying. The repository's Pages source must be **GitHub Actions**.

176 changes: 71 additions & 105 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,136 +1,102 @@
# opx77_doc

Documentation for **OPX//77**, a roleplay framework for
[OPEN//77](https://open2077.net), the multiplayer platform for Cyberpunk 2077.

Published at <https://opx77-framework.github.io/opx77_doc/>.

The framework is **one resource, `opx_infinity`**, plus the client library
**`opx_lib`**. This site documents both, and the exports other resources may
call.

## Stack

A [Fumadocs](https://fumadocs.dev) site on Next.js, exported as static HTML and
modelled on the [overextended docs](https://github.com/overextended/overextended.github.io):
fumadocs-core / fumadocs-ui 16, fumadocs-mdx 15, Next 16, React 19, Tailwind v4,
Orama static search. Node 24 and npm (`package-lock.json` is committed).

```text
content/docs/ the pages (.mdx) and the sidebar order (meta.json per folder)
├── index.mdx introduction: where to start
├── getting-started/ install, configure, troubleshooting
├── opx_infinity/ overview, concepts/, core/ (OPX.*, config, events, lib/, error codes),
│ then one folder per module: index (commands, config, codes),
│ server, client, events
├── opx_lib/ one page per Lib module
├── creators/ server/ and client/: one page per export; events
├── guides/ write a module, write a resource, convert, contribute
└── migration/ from opx77_* to opx_infinity, release notes

app/ Next routes: home, /docs, search index, llms.txt,
anchors.json and the old-URL redirect pages
lib/legacy.ts every URL the old MkDocs site served -> its new page
scripts/
├── check-content.mjs MDX compiles, front matter, internal links and anchors
├── anchors.mjs what counts as an anchor (shared by both checks)
├── check-api-coverage.sh fails on a published name the docs do not document
└── dump-surface.lua boots opx_infinity on its stub host and prints that surface
```
<h1 align="center">OPX//77 · Documentation</h1>

## How the pages are written
<p align="center">
<strong>The documentation site for OPX//77, the serious-roleplay framework for <a href="https://open2077.net">Open77</a>, the Cyberpunk 2077 multiplayer platform.</strong>
</p>

The overextended style: snippets explain, prose stays short.
<p align="center">
<a href="https://github.com/opx77-framework/opx77_doc/actions/workflows/deploy.yml"><img alt="Deploy documentation" src="https://github.com/opx77-framework/opx77_doc/actions/workflows/deploy.yml/badge.svg?branch=main"></a>
<a href="https://opx77-framework.github.io/opx77_doc/"><img alt="Read the docs" src="https://img.shields.io/badge/docs-online-c5003c"></a>
<a href="https://discord.gg/xpSuYgEYsU"><img alt="Discord" src="https://img.shields.io/badge/discord-join-5865F2?logo=discord&logoColor=white"></a>
</p>

- Front matter: `title` and a one-sentence `description` (shown under the title).
- A function, export or event is one heading with its anchor, a one-line
description, the call as a `lua` snippet, a **Parameters** list and a
**Returns** list with types, then a tiny `Example`:
<p align="center">
<strong><a href="https://opx77-framework.github.io/opx77_doc/">opx77-framework.github.io/opx77_doc</a></strong>
</p>

````mdx
## SetWeather [#server-weather-setweather]
---

Crosses to a weather and reschedules the next roll.
## What it covers

```lua
weather.SetWeather(name, transitionSeconds, reason)
```
OPX//77 is **one resource, [`opx_infinity`](https://github.com/opx77-framework/opx_infinity)**,
plus the client library **[`opx_lib`](https://github.com/opx77-framework/opx_lib)**. This
site documents both, and the exports other resources may call.

**Parameters**
- name: `string`
- transitionSeconds?: `number`
| Section | What is in it |
|---|---|
| [Getting started](https://opx77-framework.github.io/opx77_doc/docs/getting-started/install) | Install on an Open77 server, configure, troubleshoot. |
| [opx_infinity](https://opx77-framework.github.io/opx77_doc/docs/opx_infinity) | How it works (concepts, core), then every module: commands, configuration, refusal codes, server and client contracts, events. |
| [opx_lib](https://opx77-framework.github.io/opx77_doc/docs/opx_lib) | One page per library module. |
| [For creators](https://opx77-framework.github.io/opx77_doc/docs/creators) | Every server and client export, and the public events. |
| [Guides](https://opx77-framework.github.io/opx77_doc/docs/guides/writing-a-module) | Write a module, write a separate resource, convert from FiveM, contribute. |
| [Migration](https://opx77-framework.github.io/opx77_doc/docs/migration/from-opx77) | From the old `opx77_*` resources, and the release notes. |

**Returns**
- `Result` — errors `no_presets`, `unknown_preset`, `invalid_transition`
````
The site is also served as plain text for tools and assistants: `/opx77_doc/llms.txt`.

- Commands, config keys and refusal codes are tables on the module's index
page, with `<a id="…" />` in the first cell.
- Every published name has an anchor; the rule is in
[Contributing](content/docs/guides/contributing.mdx).
- Nothing is documented that was not read in the code. The code is the source
of truth, not the framework README.
- Outside code, `{`, `}` and `<` are JSX in MDX: keep them in backticks.
## Built with

## Adding a module
[Fumadocs](https://fumadocs.dev) on Next.js, exported as static HTML and deployed to
GitHub Pages: fumadocs-core / fumadocs-ui 16, fumadocs-mdx 15, Next 16, React 19,
Tailwind v4, Orama static search. Modelled on the
[overextended docs](https://github.com/overextended/overextended.github.io).

1. Create `content/docs/opx_infinity/<id>/` with `index.mdx`, `server.mdx`,
`client.mdx`, `events.mdx` (only those it has) and a `meta.json`, copying
an existing module (`weather` is the smallest complete one).
2. Add `<id>` to `content/docs/opx_infinity/meta.json` (alphabetical) and a row
to the module list in `content/docs/opx_infinity/index.mdx`.
3. Run the checks below.
## Run it locally

## Building locally
Requirements: **Node.js 24** and npm.

```bash
npm ci
npm run dev # http://localhost:3000/opx77_doc/
npm run build # static export to out/
npm run types:check
node scripts/check-content.mjs
npm start # serve out/ (open /opx77_doc/)
```

`npm start` serves `out/` (open `/opx77_doc/`).

## Checking API coverage

The framework lives in other repositories, so the check needs checkouts of
`opx_infinity` and `opx_lib`, desktop **Lua 5.4** (`lua5.4` or `lua`) and Node:
## Checks

```bash
npm run check:api # finds ../opx_infinity, ../../opx_infinity or ../../../opx_infinity
./scripts/check-api-coverage.sh /path/to/opx_infinity
OPX_INFINITY=/path/to/opx_infinity OPX_LIB_PATH=/path/to/opx_lib ./scripts/check-api-coverage.sh
node scripts/check-content.mjs # MDX compiles, front matter, internal links and anchors
npm run types:check
npm run check:api # every published name of the framework has its page anchor
```

It does not grep the framework. `scripts/dump-surface.lua` boots the real
manifest on the framework's own stub host (`opx_infinity/tests/host.lua`) and
prints every module, contract member, command, alias, Open77 export, network
event, module event, page channel, config key and `OPX.*` function that is
actually registered; `opx_lib`'s functions are read from its source. The check
then fails on any name without its anchor in the right folder of
`content/docs`. With no framework checkout in reach it prints a note and exits
0, which is what happens on the CI runner.
`check:api` boots the real `opx_infinity` manifest on its stub host and fails on any
module, command, export, event, config key or `OPX.*` function the docs do not
document. It needs `opx_infinity` and `opx_lib` checked out next to this repository and
desktop **Lua 5.4**; on CI, with no framework checkout, it reports a skip.

## Old URLs
Pushing to `main` runs [`deploy.yml`](.github/workflows/deploy.yml): install, content
check, coverage check, type check, build, deploy to GitHub Pages. Pull requests run the
same build without deploying.

The MkDocs site served pages such as `/opx77_doc/modules/weather/`. Each of
those paths (and every path the MkDocs `redirects` plugin already forwarded)
is exported as a small page that forwards to its new home, keeping the
`#fragment` when a page still defines that anchor (looked up in
`/opx77_doc/anchors.json`). The list is `lib/legacy.ts`.
## Contributing

## Deployment
Corrections are very welcome: a wrong sentence on this site costs every operator who
reads it. Read [`CONTRIBUTING.md`](CONTRIBUTING.md) for how the pages are written
(snippets explain, prose stays short; every published name has an anchor; nothing is
documented that was not read in the code), how to add a module, and how old URLs are
kept working. Report a problem with the *Documentation issue* form, or ask on
[Discord](https://discord.gg/xpSuYgEYsU).

Pushing to `main` runs `.github/workflows/deploy.yml`: `npm ci`, content check,
coverage check (a skip on CI), type check, `npm run build`, then the `out/`
directory is deployed to GitHub Pages. Pull requests run the same build
without deploying. The repository's Pages source must be **GitHub Actions**.
Everyone taking part follows the
[Code of Conduct](https://github.com/opx77-framework/.github/blob/main/CODE_OF_CONDUCT.md).

## Security

A vulnerability in the framework goes through a
[private security advisory](https://github.com/opx77-framework/opx_infinity/security/advisories/new),
never a public issue or pull request here; see the
[security policy](https://github.com/opx77-framework/.github/blob/main/SECURITY.md).

## License

The documented resources are MIT licensed. Copyright © 2026 Luís MOUTA.
The documented resources (`opx_infinity`, `opx_lib`) are MIT licensed. Copyright © 2026
Luís MOUTA.

## Credits

Written by **dop42** and the OPX//77 contributors. Built with
[Fumadocs](https://fumadocs.dev); structure and style after the
[overextended docs](https://github.com/overextended/overextended.github.io).
Support the project on [Tipeee](https://fr.tipeee.com/dop42/).

OPX//77 is an independent community project and is not affiliated with or
endorsed by CD PROJEKT RED.
<sub>OPX//77 is an independent community project and is not affiliated with or endorsed by CD PROJEKT RED.</sub>
4 changes: 2 additions & 2 deletions content/docs/guides/contributing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Contributing
description: How to change opx_infinity, opx_lib or this site — branches, checks before pushing, code conventions, text, and the documentation to update in the same change.
---

The rules reviewers apply. The framework's own `README.md` and `ui/README.md` are the authority when they disagree with this page.
The rules reviewers apply. In the framework, `CONTRIBUTING.md` (workflow and house style), `docs/MANUAL.md` (the design record) and `ui/README.md` are the authority when they disagree with this page.

## Branches and pull requests [#branches]

Expand Down Expand Up @@ -167,7 +167,7 @@ npm run build # static export to out/
- Front matter on every page: `title` and a one-sentence `description` (shown under the title, so do not repeat it).
- Snippets first, little prose. Short, direct sentences; tables for anything a reader looks up.
- British spelling.
- Never document something you have not read in the code. If the code and the framework README disagree, the code wins; say so to the maintainers.
- Never document something you have not read in the code. If the code and the framework manual (`docs/MANUAL.md`) disagree, the code wins; say so to the maintainers.
- Callouts are rare: `<Callout type="warn">` for a surprising or irreversible effect, `type="error"` for lost money or data.

## Licence [#licence]
Expand Down