# Website — Project Tree > **Auto-generated.** This file is maintained by the `sync-project-tree` CI workflow in > the [`RunicGateway/website`](https://gitea.whitlocktech.com/RunicGateway/website) repository, which > opens a pull request here whenever the tracked file layout on `main` changes. Do not edit > by hand — changes will be overwritten by the next sync. A snapshot of the tracked files in the repository (build output, dependencies, and other git-ignored paths are excluded). ```text website/ ├── .claude/ │ └── launch.json ├── .gitea/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── config.yaml │ │ └── feature_request.md │ ├── scripts/ │ │ └── gen_tree.py │ ├── workflows/ │ │ ├── build-images.yml │ │ ├── pr-checks.yml │ │ ├── sonarqube.yml │ │ └── sync-project-tree.yml │ └── PULL_REQUEST_TEMPLATE.md ├── bot/ │ ├── src/ │ │ ├── discord/ │ │ │ ├── commands/ │ │ │ │ ├── announce.command.js │ │ │ │ ├── autorole.command.js │ │ │ │ ├── ban.command.js │ │ │ │ ├── filter.command.js │ │ │ │ ├── filterallow.command.js │ │ │ │ ├── index.js │ │ │ │ ├── invite.command.js │ │ │ │ ├── kick.command.js │ │ │ │ ├── modlog.command.js │ │ │ │ ├── mute.command.js │ │ │ │ ├── news.command.js │ │ │ │ ├── ping.command.js │ │ │ │ ├── role.command.js │ │ │ │ ├── rolemenu.command.js │ │ │ │ ├── roles.command.js │ │ │ │ ├── schedule.command.js │ │ │ │ ├── warn.command.js │ │ │ │ ├── warnings.command.js │ │ │ │ └── wiki.command.js │ │ │ ├── discordManager.js │ │ │ ├── guildMemberAdd.js │ │ │ ├── guildMemberRemove.js │ │ │ ├── inviteTracker.js │ │ │ ├── messageFilter.js │ │ │ ├── modLog.js │ │ │ ├── newsAnnounce.js │ │ │ └── roleMenuHandler.js │ │ ├── filter/ │ │ │ ├── filterCache.js │ │ │ ├── inviteFilter.js │ │ │ ├── normalize.js │ │ │ └── spamFilter.js │ │ ├── internal/ │ │ │ ├── internal.controller.js │ │ │ ├── internal.routes.js │ │ │ └── requireInternalKey.js │ │ ├── invites/ │ │ │ ├── inviteRotator.js │ │ │ └── inviteScheduler.js │ │ ├── model/ │ │ │ ├── filterAllowlist.js │ │ │ ├── filterHits.js │ │ │ ├── filterWords.js │ │ │ ├── guildConfig.js │ │ │ ├── inviteLog.js │ │ │ ├── memberEvents.js │ │ │ ├── roleMenus.js │ │ │ ├── scheduledMessages.js │ │ │ ├── spamHits.js │ │ │ ├── tempRoles.js │ │ │ └── warnings.js │ │ ├── roles/ │ │ │ └── tempRoleSweeper.js │ │ ├── scheduler/ │ │ │ └── scheduler.js │ │ ├── site/ │ │ │ └── siteApiClient.js │ │ ├── utils/ │ │ │ ├── duration.js │ │ │ └── logger.js │ │ ├── app.js │ │ ├── bootstrap.js │ │ ├── brand.js │ │ ├── db.js │ │ └── server.js │ ├── .env.example │ ├── .gitignore │ ├── Dockerfile │ ├── package-lock.json │ └── package.json ├── brand/ │ └── README.md ├── client/ │ ├── public/ │ │ ├── assets/ │ │ │ └── img/ │ │ │ ├── favicon.ico │ │ │ ├── hero-moon.png │ │ │ ├── runic-emblem.png │ │ │ └── uomysticmoon-main-hero.png │ │ └── robots.txt │ ├── src/ │ │ ├── api/ │ │ │ └── client.js │ │ ├── blocks/ │ │ │ ├── types/ │ │ │ │ ├── cta.jsx │ │ │ │ ├── divider.jsx │ │ │ │ ├── heading.jsx │ │ │ │ ├── image.jsx │ │ │ │ ├── quote.jsx │ │ │ │ ├── richText.jsx │ │ │ │ └── twoColumn.jsx │ │ │ ├── BlockRenderer.jsx │ │ │ ├── editorKit.jsx │ │ │ ├── index.js │ │ │ └── registry.js │ │ ├── components/ │ │ │ ├── security/ │ │ │ │ ├── RecoveryCodesDisplay.jsx │ │ │ │ ├── RecoveryCodesPanel.jsx │ │ │ │ ├── TrustedDevicesPanel.jsx │ │ │ │ └── TrustLimitModal.jsx │ │ │ ├── CharacterSheet.jsx │ │ │ ├── CharacterStats.jsx │ │ │ ├── CreateGameAccountForm.jsx │ │ │ ├── GameAccounts.jsx │ │ │ ├── HeroElement.jsx │ │ │ ├── MaintenanceGate.jsx │ │ │ ├── Modal.jsx │ │ │ ├── MoonDot.jsx │ │ │ ├── PageHeader.jsx │ │ │ ├── PageState.jsx │ │ │ ├── PlayersOnline.jsx │ │ │ ├── ProviderIcon.jsx │ │ │ ├── PublicLayout.jsx │ │ │ ├── RequireAuth.jsx │ │ │ ├── RequirePlayer.jsx │ │ │ ├── RichTextEditor.jsx │ │ │ ├── RoleGate.jsx │ │ │ ├── ShardAccountActions.jsx │ │ │ ├── SiteFooter.jsx │ │ │ ├── SiteHeader.jsx │ │ │ └── VendorSales.jsx │ │ ├── contexts/ │ │ │ ├── AuthContext.jsx │ │ │ └── SiteContext.jsx │ │ ├── data/ │ │ │ ├── cityCrests.js │ │ │ └── regionBuckets.js │ │ ├── lib/ │ │ │ ├── format.js │ │ │ ├── heroLayout.js │ │ │ ├── shardEvents.js │ │ │ ├── useAsync.js │ │ │ └── useShardFeed.js │ │ ├── routes/ │ │ │ ├── admin/ │ │ │ │ ├── views/ │ │ │ │ │ ├── AccountAdmin.jsx │ │ │ │ │ ├── ActivityAdmin.jsx │ │ │ │ │ ├── AdminCharacter.jsx │ │ │ │ │ ├── AdminCharacters.jsx │ │ │ │ │ ├── Appeals.jsx │ │ │ │ │ ├── AuthProvidersAdmin.jsx │ │ │ │ │ ├── BotActivityAdmin.jsx │ │ │ │ │ ├── Dashboard.jsx │ │ │ │ │ ├── DiscordBotAdmin.jsx │ │ │ │ │ ├── EmailDelivery.jsx │ │ │ │ │ ├── HeroEditor.jsx │ │ │ │ │ ├── HousesAdmin.jsx │ │ │ │ │ ├── InvitesAdmin.jsx │ │ │ │ │ ├── Moderation.jsx │ │ │ │ │ ├── ModerationUser.jsx │ │ │ │ │ ├── PageBuilder.jsx │ │ │ │ │ ├── PagesAdmin.jsx │ │ │ │ │ ├── PostEditor.jsx │ │ │ │ │ ├── PostsAdmin.jsx │ │ │ │ │ ├── SettingsAdmin.jsx │ │ │ │ │ ├── ShardAdmin.jsx │ │ │ │ │ ├── ShardOps.jsx │ │ │ │ │ ├── UserDetail.jsx │ │ │ │ │ ├── UserEditor.jsx │ │ │ │ │ ├── UsersAdmin.jsx │ │ │ │ │ ├── WikiAdmin.jsx │ │ │ │ │ ├── WikiCategories.jsx │ │ │ │ │ ├── WikiEditor.jsx │ │ │ │ │ └── WikiHistory.jsx │ │ │ │ ├── AdminLayout.jsx │ │ │ │ └── AdminLogin.jsx │ │ │ ├── player/ │ │ │ │ ├── AcceptInvite.jsx │ │ │ │ ├── ForgotPassword.jsx │ │ │ │ ├── PlayerAccount.jsx │ │ │ │ ├── PlayerAppeals.jsx │ │ │ │ ├── PlayerCharacter.jsx │ │ │ │ ├── PlayerCharacters.jsx │ │ │ │ ├── PlayerLogin.jsx │ │ │ │ ├── PlayerPortalLayout.jsx │ │ │ │ ├── PlayerRegister.jsx │ │ │ │ ├── PlayerShell.jsx │ │ │ │ └── ResetPassword.jsx │ │ │ ├── public/ │ │ │ │ ├── About.jsx │ │ │ │ ├── ChampSpawns.jsx │ │ │ │ ├── CmsPage.jsx │ │ │ │ ├── FiveOnFriday.jsx │ │ │ │ ├── Governors.jsx │ │ │ │ ├── Guilds.jsx │ │ │ │ ├── Houses.jsx │ │ │ │ ├── Maintenance.jsx │ │ │ │ ├── News.jsx │ │ │ │ ├── Newsletter.jsx │ │ │ │ ├── NewsletterIssue.jsx │ │ │ │ ├── Portal.jsx │ │ │ │ ├── Screenshots.jsx │ │ │ │ ├── Shard.jsx │ │ │ │ ├── ShardActivity.jsx │ │ │ │ ├── Status.jsx │ │ │ │ └── Website.jsx │ │ │ └── wiki/ │ │ │ ├── Wiki.jsx │ │ │ └── WikiArticle.jsx │ │ ├── styles/ │ │ │ └── theme.css │ │ ├── App.jsx │ │ └── main.jsx │ ├── test/ │ │ ├── apiClient.test.js │ │ ├── format.test.js │ │ ├── heroLayout.test.js │ │ ├── regionBuckets.test.js │ │ └── shardEvents.test.js │ ├── index.html │ ├── package-lock.json │ ├── package.json │ └── vite.config.js ├── ntfy/ │ └── server.yml ├── scripts/ │ ├── dev/ │ │ ├── README.md │ │ ├── seed-sso-provider.js │ │ ├── sso-bridge-smoketest.js │ │ └── stub-idp.js │ └── sonar-test-reporter.mjs ├── server/ │ ├── db/ │ │ ├── schema.sql │ │ └── seed.js │ ├── scripts/ │ │ └── routeManifest.js │ ├── src/ │ │ ├── auth/ │ │ │ ├── providers/ │ │ │ │ ├── base.provider.js │ │ │ │ ├── discord.provider.js │ │ │ │ ├── genericOidc.provider.js │ │ │ │ ├── google.provider.js │ │ │ │ ├── local.provider.js │ │ │ │ ├── oauth2.provider.js │ │ │ │ └── registry.js │ │ │ ├── session.middleware.js │ │ │ ├── session.service.js │ │ │ ├── ssoState.js │ │ │ ├── token.js │ │ │ └── usernamePolicy.js │ │ ├── blocks/ │ │ │ ├── types/ │ │ │ │ ├── cta.js │ │ │ │ ├── divider.js │ │ │ │ ├── heading.js │ │ │ │ ├── image.js │ │ │ │ ├── quote.js │ │ │ │ ├── richText.js │ │ │ │ └── twoColumn.js │ │ │ ├── index.js │ │ │ ├── propHelpers.js │ │ │ ├── registry.js │ │ │ ├── sanitizeBlocks.js │ │ │ └── validateBlocks.js │ │ ├── config/ │ │ │ ├── brand.js │ │ │ ├── csp.js │ │ │ ├── notificationStreams.js │ │ │ └── version.js │ │ ├── middleware/ │ │ │ ├── botScore.js │ │ │ ├── loginProtection.js │ │ │ ├── noindex.js │ │ │ ├── rateLimit.js │ │ │ ├── requireInternalKey.js │ │ │ ├── siteMode.js │ │ │ └── validate.js │ │ ├── model/ │ │ │ ├── activity/ │ │ │ │ ├── activity.db.js │ │ │ │ └── activity.model.js │ │ │ ├── announceJobs/ │ │ │ │ ├── announceJobs.db.js │ │ │ │ ├── announceJobs.logic.js │ │ │ │ └── announceJobs.model.js │ │ │ ├── appeals/ │ │ │ │ ├── appeals.db.js │ │ │ │ ├── appeals.model.js │ │ │ │ └── appeals.pure.js │ │ │ ├── authProviders/ │ │ │ │ ├── authProviders.db.js │ │ │ │ └── authProviders.model.js │ │ │ ├── botConfig/ │ │ │ │ ├── botConfig.db.js │ │ │ │ └── botConfig.model.js │ │ │ ├── emailConfig/ │ │ │ │ ├── emailConfig.db.js │ │ │ │ └── emailConfig.model.js │ │ │ ├── invites/ │ │ │ │ ├── invites.db.js │ │ │ │ └── invites.model.js │ │ │ ├── mobileAuthBridge/ │ │ │ │ ├── mobileAuthBridge.db.js │ │ │ │ └── mobileAuthBridge.model.js │ │ │ ├── mobileSessions/ │ │ │ │ ├── mobileSessions.db.js │ │ │ │ └── mobileSessions.model.js │ │ │ ├── moderation/ │ │ │ │ ├── moderation.db.js │ │ │ │ ├── moderation.model.js │ │ │ │ └── moderation.pure.js │ │ │ ├── modNotes/ │ │ │ │ ├── modNotes.db.js │ │ │ │ └── modNotes.model.js │ │ │ ├── notificationSubs/ │ │ │ │ ├── notificationSubs.db.js │ │ │ │ └── notificationSubs.model.js │ │ │ ├── pages/ │ │ │ │ ├── pages.db.js │ │ │ │ ├── pages.model.js │ │ │ │ └── reservedSlugs.js │ │ │ ├── passwordResets/ │ │ │ │ ├── passwordResets.db.js │ │ │ │ └── passwordResets.model.js │ │ │ ├── posts/ │ │ │ │ ├── posts.db.js │ │ │ │ └── posts.model.js │ │ │ ├── pushDevices/ │ │ │ │ ├── pushDevices.db.js │ │ │ │ └── pushDevices.model.js │ │ │ ├── recoveryCodes/ │ │ │ │ ├── recoveryCodes.db.js │ │ │ │ └── recoveryCodes.model.js │ │ │ ├── revokedSessions/ │ │ │ │ ├── revokedSessions.db.js │ │ │ │ └── revokedSessions.model.js │ │ │ ├── settings/ │ │ │ │ ├── settings.db.js │ │ │ │ └── settings.model.js │ │ │ ├── shardEvents/ │ │ │ │ ├── shardEvents.db.js │ │ │ │ └── shardEvents.model.js │ │ │ ├── shardLinks/ │ │ │ │ ├── shardLinks.db.js │ │ │ │ └── shardLinks.model.js │ │ │ ├── shardState/ │ │ │ │ ├── shardState.db.js │ │ │ │ └── shardState.model.js │ │ │ ├── trustedDevices/ │ │ │ │ ├── trustedDevices.db.js │ │ │ │ └── trustedDevices.model.js │ │ │ ├── uoLinkConfig/ │ │ │ │ ├── uoLinkConfig.db.js │ │ │ │ └── uoLinkConfig.model.js │ │ │ ├── userIdentities/ │ │ │ │ ├── userIdentities.db.js │ │ │ │ └── userIdentities.model.js │ │ │ ├── users/ │ │ │ │ ├── users.db.js │ │ │ │ └── users.model.js │ │ │ ├── wiki/ │ │ │ │ ├── wiki.db.js │ │ │ │ ├── wiki.links.js │ │ │ │ └── wiki.model.js │ │ │ └── singletonConfigDb.js │ │ ├── router/ │ │ │ ├── v1/ │ │ │ │ ├── admin/ │ │ │ │ │ ├── account.controller.js │ │ │ │ │ ├── account.router.js │ │ │ │ │ ├── activity.router.js │ │ │ │ │ ├── admin.controller.js │ │ │ │ │ ├── admin.routes.js │ │ │ │ │ ├── authProviders.controller.js │ │ │ │ │ ├── authProviders.router.js │ │ │ │ │ ├── botActivity.controller.js │ │ │ │ │ ├── botActivity.router.js │ │ │ │ │ ├── discordBot.controller.js │ │ │ │ │ ├── emailConfig.controller.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── invites.controller.js │ │ │ │ │ ├── invites.router.js │ │ │ │ │ ├── moderation.controller.js │ │ │ │ │ ├── moderation.router.js │ │ │ │ │ ├── pages.controller.js │ │ │ │ │ ├── shardOps.controller.js │ │ │ │ │ ├── uoLink.controller.js │ │ │ │ │ ├── users.router.js │ │ │ │ │ └── usersShard.controller.js │ │ │ │ ├── auth/ │ │ │ │ │ ├── auth.controller.js │ │ │ │ │ ├── auth.routes.js │ │ │ │ │ ├── invite.controller.js │ │ │ │ │ ├── me.routes.js │ │ │ │ │ ├── mobile.controller.js │ │ │ │ │ ├── mobile.routes.js │ │ │ │ │ ├── mobileSso.controller.js │ │ │ │ │ ├── mobileSso.routes.js │ │ │ │ │ ├── notifications.controller.js │ │ │ │ │ ├── notifications.routes.js │ │ │ │ │ ├── passwordReset.controller.js │ │ │ │ │ ├── sso.controller.js │ │ │ │ │ ├── sso.routes.js │ │ │ │ │ └── trustDevice.helper.js │ │ │ │ ├── internal/ │ │ │ │ │ ├── internal.controller.js │ │ │ │ │ └── internal.routes.js │ │ │ │ ├── player/ │ │ │ │ │ ├── appeals.controller.js │ │ │ │ │ ├── player.routes.js │ │ │ │ │ └── shard.controller.js │ │ │ │ ├── public/ │ │ │ │ │ ├── public.controller.js │ │ │ │ │ ├── public.routes.js │ │ │ │ │ └── shard.controller.js │ │ │ │ └── v1.router.js │ │ │ ├── api.router.js │ │ │ ├── cspReport.controller.js │ │ │ └── wellKnown.controller.js │ │ ├── utils/ │ │ │ ├── announceWorker.js │ │ │ ├── auth.js │ │ │ ├── botInternalClient.js │ │ │ ├── botInternalKey.js │ │ │ ├── db.js │ │ │ ├── logger.js │ │ │ ├── mailer.js │ │ │ ├── newsGump.js │ │ │ ├── pushDispatch.js │ │ │ ├── sanitizeHtml.js │ │ │ ├── secretBox.js │ │ │ ├── shardBroadcast.js │ │ │ ├── shardIngest.js │ │ │ ├── shardSales.js │ │ │ ├── totp.js │ │ │ ├── trustProxy.js │ │ │ ├── uoLinkClient.js │ │ │ └── uoLinkSocket.js │ │ ├── app.js │ │ ├── internalApp.js │ │ └── server.js │ ├── swagger/ │ │ ├── swagger-output.json │ │ └── swagger.js │ ├── test/ │ │ ├── _helper.js │ │ ├── adminTrustedDevices.test.js │ │ ├── adminUserShard.test.js │ │ ├── announceJobs.test.js │ │ ├── appeals.pure.test.js │ │ ├── appeals.test.js │ │ ├── appLinks.test.js │ │ ├── authController.test.js │ │ ├── authMe.test.js │ │ ├── authTrustedDevice.test.js │ │ ├── botInternalKey.test.js │ │ ├── botScore.test.js │ │ ├── csp.test.js │ │ ├── emailConfig.model.test.js │ │ ├── honeypot.test.js │ │ ├── inviteController.test.js │ │ ├── invites.test.js │ │ ├── loginProtection.test.js │ │ ├── mailer.test.js │ │ ├── mobileAuthBridge.model.test.js │ │ ├── mobileDeviceSessions.test.js │ │ ├── mobileSession.test.js │ │ ├── mobileSsoBridge.test.js │ │ ├── moderation.model.test.js │ │ ├── moderation.test.js │ │ ├── newsGump.test.js │ │ ├── notificationsRoutes.test.js │ │ ├── pages.model.test.js │ │ ├── passwordResetController.test.js │ │ ├── passwordResets.test.js │ │ ├── playerAccounts.test.js │ │ ├── playerRouteAccess.test.js │ │ ├── providers.test.js │ │ ├── publicBrand.test.js │ │ ├── publicController.test.js │ │ ├── publicShardOnline.test.js │ │ ├── publicVersion.test.js │ │ ├── pushDispatch.test.js │ │ ├── recoveryCodes.test.js │ │ ├── registry.test.js │ │ ├── requireInternalKey.test.js │ │ ├── routeManifest.test.js │ │ ├── secretBox.test.js │ │ ├── selfTrustedDevices.test.js │ │ ├── session.test.js │ │ ├── shardControllerPublic.test.js │ │ ├── shardIngest.champsPages.test.js │ │ ├── shardIngest.protocol2.test.js │ │ ├── shardState.governorTerms.test.js │ │ ├── shardState.model.test.js │ │ ├── ssoCallback.test.js │ │ ├── ssoState.test.js │ │ ├── totp.test.js │ │ ├── trustedDevices.test.js │ │ ├── trustProxy.test.js │ │ └── usernamePolicy.test.js │ ├── .env.example │ ├── package-lock.json │ ├── package.json │ ├── routes.guards.json │ └── routes.manifest.json ├── .dockerignore ├── .env.example ├── .env.uomysticmoon.example ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── docker-compose.dev.yml ├── docker-compose.yml ├── Dockerfile ├── LICENSE.md ├── package.json ├── README.md ├── SECURITY.md └── sonar-project.properties ```