This guide is for contributors who need to find code or documentation, decide where a new file belongs or prepare the development toolchain. For the selected stack and version pins, see technology choices
| Path | Contents |
|---|---|
| Repository root | The license, the AGENTS.md navigation file and the Git attribute settings |
docs/ |
All repository documentation, including the public README. The README is a regular file, with no root copy or symlink |
| projects/ | The pnpm development workspace |
| projects/bot/ | The Fluxer bot package @neonflux/bot |
| projects/backend/ | The Convex backend package @neonflux/backend |
| projects/contracts/ | The shared contracts package @neonflux/contracts |
| projects/web/ | The dashboard and web verification package @neonflux/web |
| projects/scripts/ | The heavy-task gate that limits concurrent machine-heavy package scripts, and the Effect typecheck runner |
The workspace manifest, workspace configuration and generated lockfile own shared dependency management. The Node version file owns the exact development runtime
src/holds the bot source. main.ts starts the process, config.ts reads the environment and bot.ts builds the SDK lifecycle, gateway routing, the hold on a starting server's events and the serial message pipeline- server-scope.ts routes commands to a server of the scope, and server-runtime.ts adopts the backend's scope and website origin at startup, binds one runtime and its backend adapters to each server and calls the backend's installation functions
- backend-http.ts sends every backend request through the Convex client in convex-client.ts, and backend-routes.ts maps each request path to its backend function, whose name and kind the service contract owns. work-dispatcher.ts runs the one work dispatcher, and signalled-worker.ts is the wake-driven loop most workers share with contained.ts, which logs a failed background effect without stopping its worker
- costs.ts counts the process's Fluxer requests, backend requests and events. usage.ts reports the backend calls to the bill guard and keeps its state, and optional-work.ts holds the per-server limits on optional per-message work
- channel-parents.ts is the one source of thread parents, including the forum a command in a forum post counts as in, from Fluxerly's channel cache and one read for a channel it does not hold. thread-memory.ts keeps the last seen state of threads for metadata logs. Ticket transcripts list a ticket channel's threads in ticket-transcripts.ts, and message cleanup picks the next active thread of a policy channel in cleanup-evidence.ts, each with its own Fluxer read
- suggestion-forum.ts adds and applies the status tags of suggestion posts in a forum destination, and events.ts starts and closes event discussion threads
- protections.ts sends messages and joins to automod and security, including webhook and other bots' messages for a server that checks them, and remembers whether each server does, so their messages cost nothing while it is off
- reply-style.ts builds every status, detail and list reply once, from a title, labelled fields, an optional closing note that may hold commands, mentions and times and an optional plain footer, and renders it as an embed or as plain text in the style the server chose with its prefix in general-settings.ts
- help.ts holds the one table of built-in commands that help pages and typo hints read,
setup-check.ts owns
!setup,!healthwith its safety audit,!recoveryand the dashboard's permission check, and permission-fix.ts turns a missing permission or role position into the sentence that names its fix, and private-data.ts answers the website's access checks for private cases with the bot's own reads tests/holds the bot tests, which use the SDK's in-memory transport and the in-memory backend in backend-fake.ts. cost.test.ts records how many Fluxer and backend requests one ordinary event costs with every feature configured, on a server's first message and on a warm serverscripts/holds the opt-in live smoke script. The test compiler checks it and Node runs it directly. smoke-live.example.json shows its configuration, and the private local copy stays ignored- tsconfig.json compiles
src/intodist/, and tsconfig.test.json checks source, tests and scripts without emitting
convex/holds the Convex functions. schema.ts owns every table, botService.ts owns the bot's key-checked public entry points, serviceKey.ts checks the key, crons.ts starts scheduled jobs and retention.ts runs every feature's bounded retention cleanup as one chain- protection.ts evaluates messages and joins for automod and security and checks text that NeonFlux posts for members against the content rules, and moderationLinks.ts judges deceptive links from the message text alone
convex/_generated/is created by the Convex CLI and kept in version control- dashboard-contracts.d.ts and verification-contracts.d.ts are types-only exports of the website's own contracts. They re-export the shared types the website also uses and the generated types of the public functions it calls, and contain no runtime code or credentials
tests/holdsconvex-testtests and*-contract.test.tsfiles that run the bot's backend adapters against an isolated backend fixturescripts/holds the motion challenge screenshot evaluation, described in the challenge evaluation guide
src/holds one module per feature with an Effect Schema, and a type of the same name, for every request and answer between the bot and the backend. The bot imports them as@neonflux/contracts/<module>- common.ts holds IDs, limits and other building blocks, shared.ts the member and actor reads that many features send, and publishing-base.ts message content and the publishing grants, attempts and posts every posting feature shares
- motion-captcha.ts holds the motion challenge's public frame format, palette, particle geometry and spark path bounds, which the backend and the website share. Seeds and route geometry stay in the backend
- permission-names.ts holds Fluxer's titles for each permission bit, which the backend and the website show because they cannot load the SDK. A bot test compares every entry with the SDK
- A module imports only these base modules and the modules of the features it builds on, never in a cycle
- The backend decodes requests with
decodefrom validation.ts, and each bot-store.tsdecodes the answers
src/routes/holds TanStack Router file routes for the dashboard, verification page, session and verification APIs and Fluxer OAuth sign-in and sign-outsrc/server/holds OAuth, session and verification server handlers that run only on the web server- dashboard.tsx owns sign-in state, the server picker and the section layout. dashboard-sections.tsx lists the sections and loads each one's code on first use, and every section subscribes to its own live data. drafts.ts keeps unsaved drafts in session storage, and catalog.tsx loads and refreshes a server's channels and roles
- Other
src/files hold dashboard settings sections, the overview, the audit log, the recovery inbox, the backup restore, private cases, the member role picker, the search picker, the message builder, the verification page, the motion canvas and the Turnstile widget - onboarding-checklist.tsx holds the newcomer checklist section, while onboarding-settings.tsx holds the greetings and tickets sections
- server-export.tsx holds the owner's server export download, and dashboard-tour.tsx holds the first-visit dashboard tour
- showcase-settings.tsx holds the showcase and profile sections, and showcase-member.tsx and profile-member.tsx hold their member pages
- structure-editor.tsx holds the server structure editor, whose live diff structure-diff.ts builds from the change functions in the structure contracts that the backend's structureDomain.ts merge also uses
src/routeTree.gen.tsis generated by TanStack Router and kept in version control. Nitro builds.output/, which stays ignoredtests/holds component and server handler tests
Each feature uses the same file prefix in both packages.
In the bot, <prefix>-command.ts owns command grammar, -management.ts owns management replies, -permissions.ts owns native permission checks, which actions read fresh, -store.ts decodes backend answers with the feature's shared schemas and -worker.ts runs scoped background work.
In the backend, <prefix>.ts owns queries and mutations, Domain.ts owns domain rules, Store.ts owns state helpers and Validators.ts owns persisted shapes.
The requests and answers between them live in the feature's module of the contracts package
| Feature | Bot src/ prefix |
Backend convex/ prefix |
Contracts src/ module |
|---|---|---|---|
| Bot foundation, AFK and responses | bot, main, config, reply-style, backend-http, backend-routes, convex-client, costs, message-revisions, protections, member-evidence, channel-parents, thread-memory, afk, response, responses |
schema, botService, serviceKey, crons, retention, validation, protection, afk, response, responses |
common, shared, afk, responses |
| Moderation, automod, security and appeals | moderation, safety-permissions, action-executor |
moderation, appeals |
moderation, appeal |
| Private cases on the website | private-data |
privateData |
private-data |
| Publishing and scheduled publishing | publishing, schedule, civil-calendar |
publishing, schedules, civilDomain |
publishing-base, publishing, schedules, civil |
| Role panels, rules and autorole | role, roles |
role, roles |
roles |
| Role picker and member access | rolepicker |
rolePicker, memberAccess |
role-picker |
| Temporary roles | temprole |
temporaryRoles |
temporary-roles |
| Newcomer checklist | onboarding |
onboarding |
onboarding |
| Setup presets | preset |
presets |
presets |
| Welcome and goodbye | welcome |
greeting, greetings |
greetings |
| Tickets | ticket, tickets |
ticket, tickets |
tickets |
| Forum help desk, saved answers and thread budget guard | helpdesk |
helpDesk |
helpdesk |
| Showcases and profiles | showcase, profile |
showcases, profiles, memberContent |
showcases, profiles, member-content |
| Message leveling | level, leveling |
leveling |
leveling |
| Events, birthdays and suggestions | event, events, milestone, suggestion |
events, milestones, suggestions |
events, milestones, suggestions |
| Message cleanup and metadata logs | cleanup, metadata-log |
cleanup, metadataLogs |
cleanup, metadata-logs |
| Security alerts and invites | alerts |
alerts |
alerts |
| Selective backup | backup |
backup |
backup, permission-names |
| Readable server export | server-export |
serverExport |
server-export |
| Server structure editor on the website | structure |
structure |
structure |
| Server analytics | analytics |
analytics |
analytics |
| Temporary voice rooms | voice |
voice |
voice |
| Looking for group | lfg |
lfg |
lfg |
| Help, setup, health, recovery inbox and permission fixes | help, setup-check, permission-fix |
setupCheck, recovery |
setup |
| YouTube upload alerts and the WebSub callback | youtube |
youtube, http |
youtube |
| Sticky messages, dashboard link and member list order | sticky, sidebar, memberlist |
sticky, sidebar, memberList |
sticky, sidebar, member-list |
| Multi-server scope and installations | server-scope, server-runtime, install-note |
serverScope, installations |
service |
| Background work dispatch | work-dispatcher |
workDispatch, workSignal |
service |
| Optional work limits and the bill guard | optional-work, usage |
usage |
service |
| Dashboard | dashboard, general-settings |
dashboard, configuration, generalSettings |
dashboard, general |
| Web verification | verification |
verification, motionCaptcha, captchaDomain, turnstile |
verification |
| Audit log and member data rights | member-data |
auditLog, configurationChange, memberData |
member-data |
Keep one-consumer code in its owning package, and introduce a shared package only for a demonstrated shared responsibility. Update this guide when ownership or navigation changes
Install the Node version in projects/.node-version and a pnpm 12 bootstrap, then run the following from projects/
pnpm install --frozen-lockfile
pnpm run checkpnpm selects the exact version pinned in the workspace manifest.
The aggregate check checks formatting with Prettier, then runs the contracts typecheck, then the backend checks, then the bot typecheck, build and tests, then the web build, which regenerates the route tree, and the web typecheck and tests.
Tests need no live credentials.
The opt-in live smoke runs separately through pnpm run smoke:live and is not part of the aggregate check
Use pnpm run build to compile the bot and website and pnpm run start to run the bot's last build.
During development, pnpm run dev:bot runs the bot from its source and restarts it on changes, pnpm run dev:web runs the website and pnpm run deploy:dev publishes the backend once to the development deployment.
The bot and website read a private .env described by their .env.example, and the backend's .env.example is a template for the Convex CLI's .env.local with only the deploy key.
See the bot guide, the backend guide and the dashboard guide for environment setup.
There are no production deployment or container commands yet
- Regenerate the lockfile through pnpm when dependency inputs change, review it and verify a frozen install
- Regenerate
convex/_generated/against a configured deployment after changing the backend schema or function interfaces, as described in the backend guide - Dependency installs, compiler output, build caches and private
.envfiles stay ignored through the workspace ignore rules and each package's own.gitignore - Keep ignore rules at workspace or package scope, not in a root
.gitignore. Use Git's local.git/info/excludefor repository-root machine files - The workspace configuration allows build scripts only for the reviewed
esbuildversions that Convex and the web build tools need, and exempts the pinned SDK release from the minimum release age. Review a changed script or version before updating these entries