@meith/web 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +165 -0
- package/app/(auth)/layout.tsx +6 -0
- package/app/(auth)/login/page.tsx +106 -0
- package/app/(auth)/login/verify/page.tsx +55 -0
- package/app/(auth)/register/page.tsx +83 -0
- package/app/(auth)/reset/confirm/page.tsx +45 -0
- package/app/(auth)/reset/page.tsx +22 -0
- package/app/(auth)/verify/page.tsx +44 -0
- package/app/(auth)/verify/resend/page.tsx +51 -0
- package/app/(board)/[slug]/feed.xml/route.ts +48 -0
- package/app/(board)/[slug]/new/page.tsx +112 -0
- package/app/(board)/[slug]/page.tsx +403 -0
- package/app/(board)/discover/[view]/page.tsx +115 -0
- package/app/(board)/discover/page.tsx +5 -0
- package/app/(board)/layout.tsx +22 -0
- package/app/(board)/member/[id]/page.tsx +187 -0
- package/app/(board)/member/[id]/reputation/page.tsx +195 -0
- package/app/(board)/member/by-name/[name]/page.tsx +32 -0
- package/app/(board)/messages/[id]/page.tsx +103 -0
- package/app/(board)/messages/compose/page.tsx +60 -0
- package/app/(board)/messages/layout.tsx +5 -0
- package/app/(board)/messages/page.tsx +179 -0
- package/app/(board)/modcp/forums/page.tsx +59 -0
- package/app/(board)/modcp/ip/page.tsx +158 -0
- package/app/(board)/modcp/layout.tsx +5 -0
- package/app/(board)/modcp/log/page.tsx +98 -0
- package/app/(board)/modcp/page.tsx +112 -0
- package/app/(board)/moderation/layout.tsx +5 -0
- package/app/(board)/moderation/page.tsx +111 -0
- package/app/(board)/moderation/reports/page.tsx +193 -0
- package/app/(board)/moderation/warn/page.tsx +158 -0
- package/app/(board)/notifications/layout.tsx +5 -0
- package/app/(board)/notifications/page.tsx +144 -0
- package/app/(board)/notifications/preferences/page.tsx +65 -0
- package/app/(board)/online/page.tsx +119 -0
- package/app/(board)/page.tsx +195 -0
- package/app/(board)/plugins/[key]/[[...path]]/page.tsx +72 -0
- package/app/(board)/privacy/page.tsx +12 -0
- package/app/(board)/report/page.tsx +71 -0
- package/app/(board)/rules/page.tsx +12 -0
- package/app/(board)/search/[token]/page.tsx +130 -0
- package/app/(board)/search/page.tsx +289 -0
- package/app/(board)/stats/page.tsx +202 -0
- package/app/(board)/subscriptions/layout.tsx +5 -0
- package/app/(board)/subscriptions/page.tsx +142 -0
- package/app/(board)/terms/page.tsx +12 -0
- package/app/(board)/thread/[slug]/edit/page.tsx +107 -0
- package/app/(board)/thread/[slug]/feed.xml/route.ts +42 -0
- package/app/(board)/thread/[slug]/page.tsx +707 -0
- package/app/(board)/thread/[slug]/poll/page.tsx +41 -0
- package/app/(board)/thread/[slug]/post/[postId]/history/page.tsx +160 -0
- package/app/(board)/thread/[slug]/reply/page.tsx +136 -0
- package/app/(board)/unsubscribe/page.tsx +73 -0
- package/app/(board)/usercp/avatar/page.tsx +56 -0
- package/app/(board)/usercp/contacts/page.tsx +141 -0
- package/app/(board)/usercp/email/confirm/page.tsx +52 -0
- package/app/(board)/usercp/layout.tsx +23 -0
- package/app/(board)/usercp/options/page.tsx +56 -0
- package/app/(board)/usercp/page.tsx +71 -0
- package/app/(board)/usercp/profile/page.tsx +81 -0
- package/app/(board)/usercp/security/page.tsx +238 -0
- package/app/(board)/usercp/security/verify/page.tsx +92 -0
- package/app/(board)/usercp/signature/page.tsx +67 -0
- package/app/admin/antispam/page.tsx +155 -0
- package/app/admin/api/marketplace/screenshot/route.ts +68 -0
- package/app/admin/api/plugins/[key]/[...path]/route.ts +27 -0
- package/app/admin/api-tokens/page.tsx +129 -0
- package/app/admin/content/announcements/page.tsx +110 -0
- package/app/admin/content/attachments/page.tsx +199 -0
- package/app/admin/content/navigation/page.tsx +123 -0
- package/app/admin/content/page.tsx +170 -0
- package/app/admin/forums/[id]/page.tsx +96 -0
- package/app/admin/forums/[id]/permissions/page.tsx +108 -0
- package/app/admin/forums/page.tsx +45 -0
- package/app/admin/groups/[id]/page.tsx +133 -0
- package/app/admin/groups/memberships/page.tsx +56 -0
- package/app/admin/groups/page.tsx +104 -0
- package/app/admin/groups/promotions/page.tsx +143 -0
- package/app/admin/layout.tsx +86 -0
- package/app/admin/log/page.tsx +116 -0
- package/app/admin/page.tsx +206 -0
- package/app/admin/plugins/[key]/[[...path]]/page.tsx +276 -0
- package/app/admin/plugins/browse/page.tsx +70 -0
- package/app/admin/plugins/page.tsx +165 -0
- package/app/admin/security/page.tsx +124 -0
- package/app/admin/settings/page.tsx +190 -0
- package/app/admin/system/page.tsx +303 -0
- package/app/admin/themes/[key]/page.tsx +110 -0
- package/app/admin/themes/browse/page.tsx +70 -0
- package/app/admin/themes/page.tsx +163 -0
- package/app/admin/users/[id]/merge/page.tsx +136 -0
- package/app/admin/users/[id]/page.tsx +208 -0
- package/app/admin/users/mail/page.tsx +68 -0
- package/app/admin/users/page.tsx +260 -0
- package/app/admin/users/prune/page.tsx +186 -0
- package/app/api/health/route.ts +11 -0
- package/app/api/metrics/route.ts +66 -0
- package/app/api/plugins/[key]/[...path]/route.ts +27 -0
- package/app/api/read/all/route.ts +15 -0
- package/app/api/read/forum/[id]/route.ts +29 -0
- package/app/api/read/thread/[id]/route.ts +40 -0
- package/app/api/ready/route.ts +63 -0
- package/app/api/system/tick/route.ts +77 -0
- package/app/api/v1/[...path]/route.ts +208 -0
- package/app/api/v1/openapi.json/route.ts +12 -0
- package/app/apple-icon.ts +11 -0
- package/app/atom.xml/route.ts +7 -0
- package/app/attachment/[id]/route.ts +10 -0
- package/app/attachment/[id]/thumb/route.ts +10 -0
- package/app/auth/passkey/options/route.ts +145 -0
- package/app/auth/passkey/verify/route.ts +241 -0
- package/app/auth/resume/route.ts +55 -0
- package/app/auth/sso/[provider]/callback/route.ts +173 -0
- package/app/auth/sso/[provider]/go/route.ts +57 -0
- package/app/auth/sso/[provider]/route.ts +105 -0
- package/app/avatar/[id]/route.ts +31 -0
- package/app/brand/icon-192.png/route.ts +7 -0
- package/app/brand/icon-512.png/route.ts +7 -0
- package/app/brand/icon-maskable.png/route.ts +7 -0
- package/app/demo/stripe/[[...path]]/route.ts +27 -0
- package/app/error.tsx +15 -0
- package/app/feed.xml/route.ts +7 -0
- package/app/forumdisplay.php/page.tsx +11 -0
- package/app/group/[id]/badge/[scheme]/route.ts +26 -0
- package/app/icon.ts +13 -0
- package/app/install/page.tsx +221 -0
- package/app/jump/page.tsx +28 -0
- package/app/layout.tsx +124 -0
- package/app/logo/[scheme]/route.ts +24 -0
- package/app/manifest.ts +43 -0
- package/app/member.php/page.tsx +11 -0
- package/app/memberlist.php/page.tsx +11 -0
- package/app/not-found.tsx +14 -0
- package/app/opengraph-image.ts +11 -0
- package/app/redirect/page.tsx +44 -0
- package/app/robots.txt/route.ts +35 -0
- package/app/showthread.php/page.tsx +11 -0
- package/app/sitemap/[page]/route.ts +64 -0
- package/app/sitemap.xml/route.ts +31 -0
- package/app/twitter-image.ts +11 -0
- package/app/viewforum.php/page.tsx +11 -0
- package/app/viewtopic.php/page.tsx +11 -0
- package/bin/forum-web.mjs +241 -0
- package/components.json +21 -0
- package/instrumentation.ts +18 -0
- package/next.config.mjs +182 -0
- package/package.json +99 -0
- package/postcss.config.mjs +7 -0
- package/proxy.ts +160 -0
- package/src/components/account/active-sessions.tsx +87 -0
- package/src/components/account/avatar-form.tsx +119 -0
- package/src/components/account/credential-proof-form.tsx +76 -0
- package/src/components/account/logout-form.tsx +14 -0
- package/src/components/account/notification-forms.tsx +157 -0
- package/src/components/account/passkey-enrol.tsx +81 -0
- package/src/components/account/passkey-proof-button.tsx +47 -0
- package/src/components/account/push-device-form.tsx +193 -0
- package/src/components/account/relation-forms.tsx +69 -0
- package/src/components/account/reputation-forms.tsx +124 -0
- package/src/components/account/security-activity.tsx +46 -0
- package/src/components/account/sign-in-methods.tsx +166 -0
- package/src/components/account/subscription-forms.tsx +151 -0
- package/src/components/account/two-factor-forms.tsx +226 -0
- package/src/components/account/usercp-forms.tsx +387 -0
- package/src/components/account/usercp-nav.tsx +14 -0
- package/src/components/account/usercp-shell.tsx +34 -0
- package/src/components/admin/admin-forms.tsx +92 -0
- package/src/components/admin/admin-nav.tsx +52 -0
- package/src/components/admin/admin-undo.tsx +32 -0
- package/src/components/admin/api-token-forms.tsx +89 -0
- package/src/components/admin/badge-forms.tsx +97 -0
- package/src/components/admin/branding-forms.tsx +102 -0
- package/src/components/admin/content-forms.tsx +712 -0
- package/src/components/admin/form-bits.tsx +11 -0
- package/src/components/admin/forum-forms.tsx +524 -0
- package/src/components/admin/forum-tree.tsx +454 -0
- package/src/components/admin/group-forms.tsx +646 -0
- package/src/components/admin/mail-test-card.tsx +90 -0
- package/src/components/admin/marketplace-forms.tsx +30 -0
- package/src/components/admin/marketplace-listing.tsx +123 -0
- package/src/components/admin/navigation-forms.tsx +229 -0
- package/src/components/admin/navigation-tree.tsx +442 -0
- package/src/components/admin/oklch-picker.tsx +180 -0
- package/src/components/admin/plugin-forms.tsx +225 -0
- package/src/components/admin/settings-form.tsx +148 -0
- package/src/components/admin/system-forms.tsx +169 -0
- package/src/components/admin/theme-changes.tsx +354 -0
- package/src/components/admin/theme-forms.tsx +636 -0
- package/src/components/admin/theme-palette.tsx +119 -0
- package/src/components/admin/theme-preview.tsx +461 -0
- package/src/components/admin/user-bulk-toolbar.tsx +99 -0
- package/src/components/admin/user-forms.tsx +488 -0
- package/src/components/auth/auth-page.tsx +45 -0
- package/src/components/auth/form-controls.tsx +117 -0
- package/src/components/auth/login-form.tsx +47 -0
- package/src/components/auth/passkey-client.ts +171 -0
- package/src/components/auth/passkey-second-factor.tsx +69 -0
- package/src/components/auth/passkey-sign-in.tsx +61 -0
- package/src/components/auth/register-form.tsx +136 -0
- package/src/components/auth/resend-verification-form.tsx +34 -0
- package/src/components/auth/reset-confirm-form.tsx +43 -0
- package/src/components/auth/reset-request-form.tsx +35 -0
- package/src/components/auth/second-factor-form.tsx +51 -0
- package/src/components/auth/sso-buttons.tsx +47 -0
- package/src/components/board/live-region.tsx +74 -0
- package/src/components/board/search-off-notice.tsx +18 -0
- package/src/components/board/section-page.tsx +114 -0
- package/src/components/content/attachment-field.tsx +51 -0
- package/src/components/content/composer-field.ts +31 -0
- package/src/components/content/composer-ids.ts +6 -0
- package/src/components/content/composer-intents.tsx +27 -0
- package/src/components/content/composer-recovery.tsx +215 -0
- package/src/components/content/edit-post-form.tsx +121 -0
- package/src/components/content/markdown-editor.tsx +590 -0
- package/src/components/content/markdown-syntax.ts +53 -0
- package/src/components/content/mention-token.ts +23 -0
- package/src/components/content/multiquote-button.tsx +32 -0
- package/src/components/content/multiquote-selection.tsx +105 -0
- package/src/components/content/multiquote.ts +125 -0
- package/src/components/content/new-thread-form.tsx +169 -0
- package/src/components/content/poll-edit-form.tsx +96 -0
- package/src/components/content/poll.tsx +89 -0
- package/src/components/content/quote-in-place.tsx +51 -0
- package/src/components/content/reply-form.tsx +113 -0
- package/src/components/content/thanks-button.tsx +65 -0
- package/src/components/content/thread-rating.tsx +143 -0
- package/src/components/install/install-form.tsx +497 -0
- package/src/components/legal/legal-document.tsx +22 -0
- package/src/components/messages/message-forms.tsx +152 -0
- package/src/components/moderation/inline-moderation-form.tsx +158 -0
- package/src/components/moderation/modcp-nav.tsx +15 -0
- package/src/components/moderation/modcp-shell.tsx +41 -0
- package/src/components/moderation/queue-form.tsx +96 -0
- package/src/components/moderation/report-forms.tsx +120 -0
- package/src/components/moderation/signature-lock-form.tsx +83 -0
- package/src/components/moderation/thread-surgery-form.tsx +96 -0
- package/src/components/moderation/thread-tools-form.tsx +137 -0
- package/src/components/moderation/warning-forms.tsx +125 -0
- package/src/components/profile/custom-field.tsx +79 -0
- package/src/components/shell/appearance-icons.tsx +35 -0
- package/src/components/shell/board-notice.tsx +21 -0
- package/src/components/shell/copy-record.ts +20 -0
- package/src/components/shell/copy.tsx +17 -0
- package/src/components/shell/crash-notice.tsx +86 -0
- package/src/components/shell/demo-banner.tsx +49 -0
- package/src/components/shell/group-name-style.tsx +6 -0
- package/src/components/shell/measure.ts +1 -0
- package/src/components/shell/notification-menu.tsx +361 -0
- package/src/components/shell/offline-notice.tsx +29 -0
- package/src/components/shell/onboarding-banner.tsx +39 -0
- package/src/components/shell/page-shell.tsx +167 -0
- package/src/components/shell/panel-list.tsx +95 -0
- package/src/components/shell/panel-nav.tsx +40 -0
- package/src/components/shell/panel-overview.tsx +81 -0
- package/src/components/shell/panel-page.tsx +96 -0
- package/src/components/shell/panel-pagination.tsx +28 -0
- package/src/components/shell/panel-shell.tsx +31 -0
- package/src/components/shell/theme-runtime-style.tsx +6 -0
- package/src/components/shell/theme-switcher.tsx +97 -0
- package/src/components/shell/timezone-probe.tsx +45 -0
- package/src/components/shell/view-tabs.tsx +60 -0
- package/src/config.ts +13 -0
- package/src/server/absent-services.ts +29 -0
- package/src/server/admin-actions.ts +171 -0
- package/src/server/admin-settings-actions.ts +83 -0
- package/src/server/admin-undo-actions.ts +70 -0
- package/src/server/admin-undo.ts +75 -0
- package/src/server/admin.ts +112 -0
- package/src/server/announcements.ts +82 -0
- package/src/server/antispam.ts +310 -0
- package/src/server/api/content.ts +486 -0
- package/src/server/api/http.ts +119 -0
- package/src/server/api/members.ts +109 -0
- package/src/server/api/messages.ts +113 -0
- package/src/server/api/registry.ts +30 -0
- package/src/server/api/search.ts +98 -0
- package/src/server/api/subscriptions.ts +106 -0
- package/src/server/api-auth.ts +66 -0
- package/src/server/api-token-actions.ts +85 -0
- package/src/server/api-tokens-admin.ts +95 -0
- package/src/server/appearance-actions.ts +39 -0
- package/src/server/attachment-download.ts +43 -0
- package/src/server/attachment-embed.ts +63 -0
- package/src/server/attachment-upload-actions.ts +92 -0
- package/src/server/attachments.ts +257 -0
- package/src/server/auth-actions.ts +479 -0
- package/src/server/auth-config.ts +61 -0
- package/src/server/auth-events.ts +92 -0
- package/src/server/auth-form-state.ts +14 -0
- package/src/server/auth-mail.ts +104 -0
- package/src/server/avatars.ts +83 -0
- package/src/server/board-latest-actions.ts +7 -0
- package/src/server/board-latest.tsx +103 -0
- package/src/server/board-offline.ts +23 -0
- package/src/server/board-url.ts +14 -0
- package/src/server/brand-assets.ts +151 -0
- package/src/server/brand-mark.tsx +110 -0
- package/src/server/branding-actions.ts +53 -0
- package/src/server/branding.ts +101 -0
- package/src/server/cache-targets.ts +13 -0
- package/src/server/code-highlighting.ts +33 -0
- package/src/server/container.ts +402 -0
- package/src/server/content-actions.ts +459 -0
- package/src/server/content-admin-actions.ts +492 -0
- package/src/server/content-admin.ts +95 -0
- package/src/server/content-security-policy.ts +35 -0
- package/src/server/context.ts +32 -0
- package/src/server/cookies.ts +139 -0
- package/src/server/credential-proof-actions.ts +42 -0
- package/src/server/credential-proof.ts +35 -0
- package/src/server/current-location.ts +19 -0
- package/src/server/demo-stripe.ts +104 -0
- package/src/server/demo-uploads.ts +28 -0
- package/src/server/demo.ts +80 -0
- package/src/server/discovery.ts +104 -0
- package/src/server/embeds.ts +113 -0
- package/src/server/error-notice.tsx +41 -0
- package/src/server/federation-actions.ts +113 -0
- package/src/server/federation.ts +138 -0
- package/src/server/feed-builder.ts +72 -0
- package/src/server/feed-routes.ts +122 -0
- package/src/server/fixture-actor-source.ts +62 -0
- package/src/server/fixture-forum-repo.ts +59 -0
- package/src/server/fixture-member-profile-repo.ts +30 -0
- package/src/server/fixture-post-repo.ts +108 -0
- package/src/server/fixture-thread-repo.ts +98 -0
- package/src/server/form-state-reporter.ts +34 -0
- package/src/server/form-values.ts +23 -0
- package/src/server/forum-admin-actions.ts +353 -0
- package/src/server/forum-admin.ts +98 -0
- package/src/server/group-admin-actions.ts +341 -0
- package/src/server/group-admin.ts +98 -0
- package/src/server/group-badge-actions.ts +61 -0
- package/src/server/group-badge.ts +62 -0
- package/src/server/group-identity.ts +104 -0
- package/src/server/i18n-catalogs.ts +42 -0
- package/src/server/i18n.ts +69 -0
- package/src/server/image-upload.ts +109 -0
- package/src/server/inline-moderation-actions.ts +129 -0
- package/src/server/install-actions.ts +124 -0
- package/src/server/install.ts +281 -0
- package/src/server/legacy-redirect.ts +83 -0
- package/src/server/legal.ts +43 -0
- package/src/server/location-header.ts +37 -0
- package/src/server/mail-brand.ts +43 -0
- package/src/server/mail-health.ts +41 -0
- package/src/server/mail-send.ts +44 -0
- package/src/server/mail-test-actions.ts +67 -0
- package/src/server/mail-test.ts +56 -0
- package/src/server/markdown-pipeline.ts +31 -0
- package/src/server/marketplace-actions.ts +47 -0
- package/src/server/marketplace-admin.ts +260 -0
- package/src/server/mention-actions.ts +21 -0
- package/src/server/mention-search.ts +35 -0
- package/src/server/message-actions.ts +110 -0
- package/src/server/messages.ts +141 -0
- package/src/server/modcp.ts +125 -0
- package/src/server/moderation-actions.ts +165 -0
- package/src/server/navigation-admin-actions.ts +217 -0
- package/src/server/navigation.ts +112 -0
- package/src/server/nonce.ts +13 -0
- package/src/server/notification-actions.ts +84 -0
- package/src/server/notification-audience.ts +10 -0
- package/src/server/notification-menu-actions.ts +82 -0
- package/src/server/notification-menu.ts +96 -0
- package/src/server/notifications.ts +93 -0
- package/src/server/onboarding-actions.ts +27 -0
- package/src/server/onboarding.ts +89 -0
- package/src/server/page-metadata.ts +14 -0
- package/src/server/passkey-challenge.ts +42 -0
- package/src/server/plugin-admin-actions.ts +232 -0
- package/src/server/plugin-admin.ts +276 -0
- package/src/server/plugin-host.ts +143 -0
- package/src/server/plugin-pages.ts +192 -0
- package/src/server/plugin-panel.ts +49 -0
- package/src/server/plugin-routes.ts +298 -0
- package/src/server/plugin-view.tsx +58 -0
- package/src/server/poll-actions.ts +104 -0
- package/src/server/poll-scope.ts +52 -0
- package/src/server/post-notifications.ts +71 -0
- package/src/server/post-scope.ts +86 -0
- package/src/server/presence.ts +177 -0
- package/src/server/profile-fields.ts +112 -0
- package/src/server/push-actions.ts +113 -0
- package/src/server/push.ts +40 -0
- package/src/server/redirect-back.ts +15 -0
- package/src/server/registration.ts +7 -0
- package/src/server/relation-actions.ts +89 -0
- package/src/server/relations.ts +45 -0
- package/src/server/reply-core.ts +173 -0
- package/src/server/report-actions.ts +165 -0
- package/src/server/report-scope.ts +21 -0
- package/src/server/reputation-actions.ts +146 -0
- package/src/server/reputation-target.ts +49 -0
- package/src/server/reputation.ts +70 -0
- package/src/server/request-fingerprint.ts +65 -0
- package/src/server/safe-path.ts +16 -0
- package/src/server/same-origin.ts +45 -0
- package/src/server/search-page.ts +313 -0
- package/src/server/search.ts +45 -0
- package/src/server/secret-auth.ts +20 -0
- package/src/server/see-other.ts +11 -0
- package/src/server/seed-board.ts +417 -0
- package/src/server/session-actions.ts +78 -0
- package/src/server/session-cookies.ts +124 -0
- package/src/server/session-key.ts +17 -0
- package/src/server/settings.ts +47 -0
- package/src/server/signatures.ts +62 -0
- package/src/server/sso-handshake.ts +79 -0
- package/src/server/stats.ts +63 -0
- package/src/server/subscription-actions.ts +161 -0
- package/src/server/surgery-actions.ts +180 -0
- package/src/server/syndication.ts +77 -0
- package/src/server/system-admin-actions.ts +134 -0
- package/src/server/system-admin.ts +90 -0
- package/src/server/test-container.ts +114 -0
- package/src/server/theme-admin-actions.ts +242 -0
- package/src/server/theme-admin.ts +203 -0
- package/src/server/theme-runtime.ts +89 -0
- package/src/server/theme-style.ts +279 -0
- package/src/server/theme.ts +52 -0
- package/src/server/thread-core.ts +207 -0
- package/src/server/thread-rating-actions.ts +55 -0
- package/src/server/thread-tool-actions.ts +154 -0
- package/src/server/two-factor-actions.ts +178 -0
- package/src/server/two-factor.ts +86 -0
- package/src/server/upgrade-notice.ts +41 -0
- package/src/server/user-admin-actions.ts +572 -0
- package/src/server/user-admin.ts +165 -0
- package/src/server/usercp-actions.ts +263 -0
- package/src/server/usercp-mail.ts +120 -0
- package/src/server/viewer-preferences.ts +64 -0
- package/src/server/warning-actions.ts +122 -0
- package/src/styles/globals.css +969 -0
- package/src/theme/contract.fixture.ts +793 -0
- package/src/view/account-copy.ts +351 -0
- package/src/view/admin-content-copy.ts +66 -0
- package/src/view/admin-copy.ts +106 -0
- package/src/view/admin-forum-tree-copy.ts +40 -0
- package/src/view/admin-group-copy.ts +80 -0
- package/src/view/admin-log.ts +58 -0
- package/src/view/admin-nav.ts +164 -0
- package/src/view/admin-navigation-copy.ts +58 -0
- package/src/view/admin-panel-copy.ts +194 -0
- package/src/view/admin-settings.ts +173 -0
- package/src/view/admin-theme-copy.ts +229 -0
- package/src/view/admin-user-copy.ts +96 -0
- package/src/view/attachments.ts +51 -0
- package/src/view/auth-copy.ts +147 -0
- package/src/view/board-index.ts +167 -0
- package/src/view/board-latest.ts +101 -0
- package/src/view/breadcrumb.ts +50 -0
- package/src/view/contacts.ts +85 -0
- package/src/view/content-copy.ts +118 -0
- package/src/view/contrast.ts +286 -0
- package/src/view/copy.ts +101 -0
- package/src/view/count.ts +8 -0
- package/src/view/discovery-view.ts +74 -0
- package/src/view/editor-toolbar.ts +84 -0
- package/src/view/error-notice.ts +52 -0
- package/src/view/feed.ts +130 -0
- package/src/view/forum-cursor.ts +54 -0
- package/src/view/forum-display.ts +152 -0
- package/src/view/forum-jump.ts +60 -0
- package/src/view/forum-notice.ts +24 -0
- package/src/view/inline-moderation.ts +87 -0
- package/src/view/install-copy.ts +95 -0
- package/src/view/legal.ts +58 -0
- package/src/view/locale.ts +40 -0
- package/src/view/marketplace-panel.ts +51 -0
- package/src/view/member-identity.ts +23 -0
- package/src/view/member-profile.ts +65 -0
- package/src/view/messages.ts +222 -0
- package/src/view/metadata.ts +75 -0
- package/src/view/modcp-nav.ts +76 -0
- package/src/view/moderation-copy.ts +84 -0
- package/src/view/moderation-queue.ts +67 -0
- package/src/view/navigation-arrange.ts +188 -0
- package/src/view/navigation.ts +173 -0
- package/src/view/notification-menu.ts +202 -0
- package/src/view/notifications.ts +84 -0
- package/src/view/onboarding.ts +26 -0
- package/src/view/pager.ts +191 -0
- package/src/view/panel-nav.ts +203 -0
- package/src/view/plugin-panel.ts +42 -0
- package/src/view/post-form.ts +61 -0
- package/src/view/post-link.ts +29 -0
- package/src/view/presence.ts +99 -0
- package/src/view/promotion-rules.ts +52 -0
- package/src/view/redirect-notice.ts +21 -0
- package/src/view/reputation.ts +107 -0
- package/src/view/search-controls.ts +103 -0
- package/src/view/search-results.ts +291 -0
- package/src/view/security-activity.ts +73 -0
- package/src/view/setting-groups.ts +43 -0
- package/src/view/shell.ts +164 -0
- package/src/view/slug-id.ts +12 -0
- package/src/view/sso-hand-off.ts +44 -0
- package/src/view/sso-notices.ts +48 -0
- package/src/view/subscriptions.ts +76 -0
- package/src/view/theme-draft.ts +167 -0
- package/src/view/theme-preference.ts +30 -0
- package/src/view/theme-tokens.ts +333 -0
- package/src/view/thread-view.ts +280 -0
- package/src/view/time.ts +31 -0
- package/src/view/timezone.ts +35 -0
- package/src/view/two-factor.ts +6 -0
- package/src/view/usercp-nav.ts +103 -0
- package/src/view/usercp.ts +196 -0
- package/src/view/warnings.ts +128 -0
- package/src/view/word-filter.ts +5 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { renderBrandSocial } from '@/server/brand-mark'
|
|
2
|
+
|
|
3
|
+
export const dynamic = 'force-dynamic'
|
|
4
|
+
|
|
5
|
+
export const size = { width: 1200, height: 630 }
|
|
6
|
+
|
|
7
|
+
export const contentType = 'image/png'
|
|
8
|
+
|
|
9
|
+
export default function TwitterImage(): Promise<Response> {
|
|
10
|
+
return renderBrandSocial()
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { serveLegacyUrl } from '@/server/legacy-redirect'
|
|
2
|
+
|
|
3
|
+
export const dynamic = 'force-dynamic'
|
|
4
|
+
|
|
5
|
+
export default async function ViewforumPage({
|
|
6
|
+
searchParams,
|
|
7
|
+
}: {
|
|
8
|
+
searchParams: Promise<Record<string, string | string[] | undefined>>
|
|
9
|
+
}): Promise<never> {
|
|
10
|
+
return serveLegacyUrl('viewforum.php', await searchParams)
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { serveLegacyUrl } from '@/server/legacy-redirect'
|
|
2
|
+
|
|
3
|
+
export const dynamic = 'force-dynamic'
|
|
4
|
+
|
|
5
|
+
export default async function ViewtopicPage({
|
|
6
|
+
searchParams,
|
|
7
|
+
}: {
|
|
8
|
+
searchParams: Promise<Record<string, string | string[] | undefined>>
|
|
9
|
+
}): Promise<never> {
|
|
10
|
+
return serveLegacyUrl('viewtopic.php', await searchParams)
|
|
11
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `forum-web` — the bin that makes `@meith/web` runnable as a plain
|
|
4
|
+
* dependency of an external board workspace (see docs/development.md,
|
|
5
|
+
* "Consuming the board from a workspace").
|
|
6
|
+
*
|
|
7
|
+
* A Next.js app is not consumable as a bare dependency: `next dev|build|start`
|
|
8
|
+
* need to run with the app's own directory as the project root, and the
|
|
9
|
+
* board-config seam (`@board/config` / `@board/plugins`, see
|
|
10
|
+
* docs/architecture.md) is a pair of tsconfig path aliases that inside this
|
|
11
|
+
* monorepo point at `apps/community`'s own files. Neither survives npm
|
|
12
|
+
* installing this package into somebody else's workspace unchanged.
|
|
13
|
+
*
|
|
14
|
+
* So on every invocation this bin:
|
|
15
|
+
*
|
|
16
|
+
* 1. Copies this package's own Next app sources into `.meith/app/` inside
|
|
17
|
+
* the invoking workspace (the current working directory) — gitignored,
|
|
18
|
+
* regenerated every time, never a merge target.
|
|
19
|
+
* 2. Writes `.meith/app/tsconfig.json`, a fresh tsconfig whose `paths`
|
|
20
|
+
* point `@board/config` and `@board/plugins` at *this workspace's own*
|
|
21
|
+
* `community.config.ts` / `community.plugins.ts` — the same seam, wired
|
|
22
|
+
* to a different pair of files. tsconfig `paths` are a compiler/bundler
|
|
23
|
+
* alias, not a package boundary, so nothing stops one from naming a
|
|
24
|
+
* path two directories up; that is the whole trick.
|
|
25
|
+
* 3. Runs `next dev|build|start` with `.meith/app/` as the project root.
|
|
26
|
+
*
|
|
27
|
+
* `.meith/app/` sits exactly two directories below the workspace root
|
|
28
|
+
* (`<root>/.meith/app`) on purpose: `next.config.mjs` (copied verbatim, see
|
|
29
|
+
* below) computes its own workspace root as two directories up from itself,
|
|
30
|
+
* so materializing at that exact depth keeps that computation correct
|
|
31
|
+
* without touching the file.
|
|
32
|
+
*
|
|
33
|
+
* This assumes a *hoisted* `node_modules` (npm, yarn classic, or pnpm with
|
|
34
|
+
* `node-linker=hoisted`) — see docs/development.md for why.
|
|
35
|
+
*
|
|
36
|
+
* `boards/stock` (docker/Dockerfile) is this bin's one *in-repo* consumer,
|
|
37
|
+
* and it has neither a hoisted `node_modules` nor a two-directories-up
|
|
38
|
+
* workspace root — it is a workspace member of this monorepo's own
|
|
39
|
+
* (non-hoisted) pnpm install, nested two directories deeper again. Two
|
|
40
|
+
* environment variables, set only by that workspace's own `build`/`dev`
|
|
41
|
+
* scripts, cover the difference without changing anything for a real
|
|
42
|
+
* external board, which never sets either: `FORUM_WORKSPACE_ROOT`
|
|
43
|
+
* (apps/community/next.config.mjs) points tracing at this repository's real
|
|
44
|
+
* root, and `FORUM_ALIASES_FROM` (`monorepoAliases()` below) carries this
|
|
45
|
+
* repository's own `@meith/*` tsconfig aliases into the generated tsconfig,
|
|
46
|
+
* since packages here resolve each other through those aliases rather than
|
|
47
|
+
* through real `dependencies` entries a hoisted `node_modules` would need.
|
|
48
|
+
*/
|
|
49
|
+
import { spawn } from 'node:child_process'
|
|
50
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
51
|
+
import { createRequire } from 'node:module'
|
|
52
|
+
import { dirname, join, relative, resolve, sep } from 'node:path'
|
|
53
|
+
import { fileURLToPath } from 'node:url'
|
|
54
|
+
|
|
55
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
56
|
+
const packageRoot = join(here, '..')
|
|
57
|
+
const workspaceRoot = process.cwd()
|
|
58
|
+
const appDir = join(workspaceRoot, '.meith', 'app')
|
|
59
|
+
|
|
60
|
+
// `next dev|build` runs with `.meith/app` as its own cwd (see `run()` below),
|
|
61
|
+
// so a relative FORUM_WORKSPACE_ROOT / FORUM_ALIASES_FROM — the shape
|
|
62
|
+
// boards/stock/package.json's scripts write, relative to *this* process's
|
|
63
|
+
// own cwd (the board's own directory) — would resolve against the wrong
|
|
64
|
+
// directory if left for next.config.mjs to resolve itself. Rewriting them to
|
|
65
|
+
// absolute paths here, before spawning, means both env vars mean the same
|
|
66
|
+
// thing regardless of which process reads them.
|
|
67
|
+
for (const name of ['FORUM_WORKSPACE_ROOT', 'FORUM_ALIASES_FROM']) {
|
|
68
|
+
if (process.env[name]) process.env[name] = resolve(workspaceRoot, process.env[name])
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Files this package ships (see its `files` allowlist) that belong inside
|
|
72
|
+
// the materialized app. Board files (community.config.ts, board.plugins.json,
|
|
73
|
+
// community.plugins.ts) are never copied — they are read in place, from the
|
|
74
|
+
// workspace, through the generated tsconfig instead.
|
|
75
|
+
const APP_ENTRIES = [
|
|
76
|
+
'app',
|
|
77
|
+
'src',
|
|
78
|
+
'next.config.mjs',
|
|
79
|
+
'postcss.config.mjs',
|
|
80
|
+
'components.json',
|
|
81
|
+
'instrumentation.ts',
|
|
82
|
+
'proxy.ts',
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
function fail(message) {
|
|
86
|
+
console.error(`forum-web: ${message}`)
|
|
87
|
+
process.exit(1)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function toPosixRelative(from, to) {
|
|
91
|
+
const rel = relative(from, to).split(sep).join('/')
|
|
92
|
+
return rel.startsWith('.') ? rel : `./${rel}`
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* A board outside this monorepo has a hoisted `node_modules` (see the module
|
|
97
|
+
* comment), so plain bare-specifier resolution reaches every `@meith/*`
|
|
98
|
+
* package this app's dependency graph needs, and `transpilePackages`
|
|
99
|
+
* (apps/community/next.config.mjs) is what lets Next compile the `.ts`
|
|
100
|
+
* source that resolution lands on. A board built *inside* this monorepo's
|
|
101
|
+
* own pnpm install has no such hoisting — packages here resolve each other
|
|
102
|
+
* through tsconfig path aliases straight to source (docs/architecture.md,
|
|
103
|
+
* "The board-config seam"; docs/development.md, "The workspace") rather than
|
|
104
|
+
* through real `dependencies` entries, so plain node_modules resolution
|
|
105
|
+
* finds nothing for most of them.
|
|
106
|
+
*
|
|
107
|
+
* `FORUM_ALIASES_FROM`, set only by docker/Dockerfile for `boards/stock`,
|
|
108
|
+
* names that other tsconfig (this repository's own `tsconfig.base.json`).
|
|
109
|
+
* When set, every `@meith/*` alias it declares is copied into the
|
|
110
|
+
* materialized app's own generated tsconfig, rebased to be relative to
|
|
111
|
+
* `.meith/app` — the same aliases apps/community's own tsconfig.json
|
|
112
|
+
* hand-maintains for exactly this reason. Unset (the default, and the only
|
|
113
|
+
* path a real external board ever takes), this is a no-op.
|
|
114
|
+
*/
|
|
115
|
+
function monorepoAliases() {
|
|
116
|
+
const configFile = process.env.FORUM_ALIASES_FROM
|
|
117
|
+
if (!configFile) return {}
|
|
118
|
+
|
|
119
|
+
const sourceDir = dirname(resolve(configFile))
|
|
120
|
+
const source = JSON.parse(readFileSync(configFile, 'utf8'))
|
|
121
|
+
const paths = source.compilerOptions?.paths ?? {}
|
|
122
|
+
|
|
123
|
+
const aliases = {}
|
|
124
|
+
for (const [alias, targets] of Object.entries(paths)) {
|
|
125
|
+
// `@board/config`/`@board/plugins` are this workspace's own seam, wired
|
|
126
|
+
// below to *this* board's files — never to whatever apps/community's own
|
|
127
|
+
// tsconfig happens to alias them to.
|
|
128
|
+
if (alias === '@board/config' || alias === '@board/plugins') continue
|
|
129
|
+
aliases[alias] = targets.map((target) => toPosixRelative(appDir, join(sourceDir, target)))
|
|
130
|
+
}
|
|
131
|
+
return aliases
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function materialize() {
|
|
135
|
+
const boardConfig = join(workspaceRoot, 'community.config.ts')
|
|
136
|
+
const boardPlugins = join(workspaceRoot, 'community.plugins.ts')
|
|
137
|
+
|
|
138
|
+
if (!existsSync(boardConfig)) {
|
|
139
|
+
fail(
|
|
140
|
+
`no community.config.ts in ${workspaceRoot}. Run forum-web from a board's own ` +
|
|
141
|
+
'directory — the one create-meith scaffolded, or one shaped like it.',
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Replace each shipped entry, but never `rm -rf` the whole directory:
|
|
146
|
+
// `.next` lives here too once a build has run, and `forum-web start` needs
|
|
147
|
+
// that build still on disk after this same function re-materializes the
|
|
148
|
+
// sources ahead of launching the standalone server.
|
|
149
|
+
mkdirSync(appDir, { recursive: true })
|
|
150
|
+
|
|
151
|
+
for (const entry of APP_ENTRIES) {
|
|
152
|
+
const source = join(packageRoot, entry)
|
|
153
|
+
const target = join(appDir, entry)
|
|
154
|
+
rmSync(target, { recursive: true, force: true })
|
|
155
|
+
if (!existsSync(source)) continue
|
|
156
|
+
cpSync(source, target, { recursive: true })
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const tsconfig = {
|
|
160
|
+
compilerOptions: {
|
|
161
|
+
target: 'ES2022',
|
|
162
|
+
lib: ['dom', 'dom.iterable', 'esnext'],
|
|
163
|
+
module: 'esnext',
|
|
164
|
+
moduleResolution: 'bundler',
|
|
165
|
+
jsx: 'preserve',
|
|
166
|
+
allowJs: false,
|
|
167
|
+
resolveJsonModule: true,
|
|
168
|
+
esModuleInterop: true,
|
|
169
|
+
isolatedModules: true,
|
|
170
|
+
skipLibCheck: true,
|
|
171
|
+
noEmit: true,
|
|
172
|
+
incremental: true,
|
|
173
|
+
strict: true,
|
|
174
|
+
plugins: [{ name: 'next' }],
|
|
175
|
+
paths: {
|
|
176
|
+
...monorepoAliases(),
|
|
177
|
+
'@/*': ['./src/*'],
|
|
178
|
+
'@board/config': [toPosixRelative(appDir, boardConfig)],
|
|
179
|
+
'@board/plugins': [toPosixRelative(appDir, boardPlugins)],
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
include: ['next-env.d.ts', '**/*.ts', '**/*.tsx', '.next/types/**/*.ts'],
|
|
183
|
+
exclude: ['node_modules'],
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
writeFileSync(join(appDir, 'tsconfig.json'), `${JSON.stringify(tsconfig, null, 2)}\n`)
|
|
187
|
+
|
|
188
|
+
// next dev/build reads its own next-env.d.ts if present; an empty one is
|
|
189
|
+
// enough, and next regenerates it with the right content on first run.
|
|
190
|
+
writeFileSync(
|
|
191
|
+
join(appDir, 'next-env.d.ts'),
|
|
192
|
+
'/// <reference types="next" />\n/// <reference types="next/image-types/global" />\n',
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function resolveNextBin() {
|
|
197
|
+
// Resolved from this package's own directory rather than the workspace
|
|
198
|
+
// root: `next` is @meith/web's dependency, not necessarily the workspace
|
|
199
|
+
// manifest's, and resolving from here finds it either way — hoisted to
|
|
200
|
+
// the workspace root (npm, yarn classic) or nested under this package's
|
|
201
|
+
// own node_modules (pnpm's default, non-hoisted layout).
|
|
202
|
+
const require = createRequire(join(packageRoot, 'package.json'))
|
|
203
|
+
try {
|
|
204
|
+
return require.resolve('next/dist/bin/next')
|
|
205
|
+
} catch {
|
|
206
|
+
fail("could not find next's own CLI from @meith/web — is next installed in this workspace?")
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function run(executable, args, cwd) {
|
|
211
|
+
const child = spawn(executable, args, { cwd, stdio: 'inherit' })
|
|
212
|
+
child.on('exit', (code, signal) => process.exit(code ?? (signal ? 1 : 0)))
|
|
213
|
+
child.on('error', (error) => fail(error.message))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const [, , command, ...rest] = process.argv
|
|
217
|
+
|
|
218
|
+
if (!['dev', 'build', 'start'].includes(command ?? '')) {
|
|
219
|
+
console.error('Usage: forum-web <dev|build|start> [next arguments]')
|
|
220
|
+
process.exit(1)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
materialize()
|
|
224
|
+
|
|
225
|
+
if (command === 'start') {
|
|
226
|
+
// `next.config.mjs` sets `output: 'standalone'`, and a standalone build is
|
|
227
|
+
// run from its own traced server.js, not `next start` (see docker/Dockerfile
|
|
228
|
+
// and docker/entrypoint.sh, which run the image's board the same way). The
|
|
229
|
+
// tracing root is the workspace root (see the module comment on why
|
|
230
|
+
// `.meith/app` sits exactly two levels below it), so the standalone bundle
|
|
231
|
+
// preserves that same relative path down to the app directory.
|
|
232
|
+
const standaloneRoot = join(appDir, '.next', 'standalone')
|
|
233
|
+
const serverScript = join(standaloneRoot, relative(workspaceRoot, appDir), 'server.js')
|
|
234
|
+
if (!existsSync(serverScript)) {
|
|
235
|
+
fail(`no standalone build at ${serverScript} — run "forum-web build" first.`)
|
|
236
|
+
}
|
|
237
|
+
run(process.execPath, [serverScript, ...rest], standaloneRoot)
|
|
238
|
+
} else {
|
|
239
|
+
const nextBin = resolveNextBin()
|
|
240
|
+
run(process.execPath, [nextBin, command, ...rest], appDir)
|
|
241
|
+
}
|
package/components.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "base-nova",
|
|
4
|
+
"rsc": true,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "app/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@/components",
|
|
15
|
+
"utils": "@/lib/utils",
|
|
16
|
+
"ui": "@/components/ui",
|
|
17
|
+
"lib": "@/lib",
|
|
18
|
+
"hooks": "@/hooks"
|
|
19
|
+
},
|
|
20
|
+
"iconLibrary": "lucide"
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export async function register(): Promise<void> {
|
|
2
|
+
// biome-ignore lint/style/noProcessEnv: build-time runtime token, not config; see above
|
|
3
|
+
if (process.env.NEXT_RUNTIME !== 'nodejs') return
|
|
4
|
+
|
|
5
|
+
const { assertRuntimeEnv, initTracing } = await import('@meith/core')
|
|
6
|
+
|
|
7
|
+
const env = assertRuntimeEnv()
|
|
8
|
+
|
|
9
|
+
if (env.DATA_SOURCE === 'fixture') {
|
|
10
|
+
// biome-ignore lint/suspicious/noConsole: pre-logger boot diagnostic
|
|
11
|
+
console.info(
|
|
12
|
+
'[forum] DATA_SOURCE=fixture — running against in-memory sample data. ' +
|
|
13
|
+
'Set DATABASE_URL to use Postgres.',
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
await initTracing('meith-web')
|
|
18
|
+
}
|
package/next.config.mjs
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
const here = path.dirname(fileURLToPath(import.meta.url))
|
|
6
|
+
|
|
7
|
+
// Two directories up from this file's own location — correct whenever this
|
|
8
|
+
// file sits at that fixed depth below the real workspace root: in place at
|
|
9
|
+
// `apps/community` inside this monorepo, or materialized to `.meith/app`
|
|
10
|
+
// inside a *board whose own directory sits two levels below its own
|
|
11
|
+
// `node_modules`* (a create-meith scaffold with hoisted node_modules, per
|
|
12
|
+
// docs/development.md, "Consuming the board from a workspace").
|
|
13
|
+
//
|
|
14
|
+
// `boards/stock` (docker/Dockerfile) is neither: it is a workspace member of
|
|
15
|
+
// *this* monorepo's own pnpm install, which does not hoist, so its real
|
|
16
|
+
// dependencies (including `next` itself) resolve through this repository's
|
|
17
|
+
// root `node_modules`, two directories further up again — a fixed offset
|
|
18
|
+
// this file cannot compute from its own path alone, because pnpm resolves
|
|
19
|
+
// its dependencies through symlinks into a central store rather than by
|
|
20
|
+
// nesting a workspace member two directories below everything it needs.
|
|
21
|
+
// FORUM_WORKSPACE_ROOT lets the Dockerfile say so explicitly, without
|
|
22
|
+
// changing the default for every other consumer this computation already
|
|
23
|
+
// serves correctly.
|
|
24
|
+
const workspaceRoot = process.env.FORUM_WORKSPACE_ROOT
|
|
25
|
+
? path.resolve(process.env.FORUM_WORKSPACE_ROOT)
|
|
26
|
+
: path.join(here, '../../')
|
|
27
|
+
|
|
28
|
+
// How many `../` this file's own directory is below workspaceRoot — 2 by
|
|
29
|
+
// construction in the default case (see above), more when
|
|
30
|
+
// FORUM_WORKSPACE_ROOT points further up. Used below instead of a literal
|
|
31
|
+
// `'../../'` wherever a *relative* climb has to reach the same root, because
|
|
32
|
+
// `outputFileTracingIncludes` (unlike `outputFileTracingRoot` and
|
|
33
|
+
// `turbopack.root`) resolves its globs relative to this directory itself,
|
|
34
|
+
// not against `workspaceRoot` — an absolute glob there silently matches
|
|
35
|
+
// nothing useful once it is rejoined onto this directory downstream.
|
|
36
|
+
const upToWorkspaceRoot = path.relative(here, workspaceRoot).split(path.sep).join('/')
|
|
37
|
+
|
|
38
|
+
const loadedEnvFiles = []
|
|
39
|
+
for (const name of ['.env.local', '.env']) {
|
|
40
|
+
const file = path.join(workspaceRoot, name)
|
|
41
|
+
if (!existsSync(file)) continue
|
|
42
|
+
process.loadEnvFile(file)
|
|
43
|
+
loadedEnvFiles.push(name)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (process.env.NODE_ENV !== 'production' && loadedEnvFiles.length > 0) {
|
|
47
|
+
console.log(`- Environments: ${loadedEnvFiles.join(', ')} (${workspaceRoot})`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const nextConfig = {
|
|
51
|
+
output: 'standalone',
|
|
52
|
+
poweredByHeader: false,
|
|
53
|
+
distDir: process.env.FORUM_DIST_DIR ?? '.next',
|
|
54
|
+
|
|
55
|
+
serverExternalPackages: [
|
|
56
|
+
'@aws-sdk/client-s3',
|
|
57
|
+
'@aws-sdk/s3-request-presigner',
|
|
58
|
+
'postgres',
|
|
59
|
+
'@jsquash/jpeg',
|
|
60
|
+
'@jsquash/png',
|
|
61
|
+
'@jsquash/resize',
|
|
62
|
+
'nodemailer',
|
|
63
|
+
],
|
|
64
|
+
outputFileTracingRoot: workspaceRoot,
|
|
65
|
+
// Turbopack infers a project root by walking up for a lockfile, and
|
|
66
|
+
// otherwise stops at this app's own directory — which for a materialized
|
|
67
|
+
// app (apps/community/bin/forum-web.mjs) is two directories below the
|
|
68
|
+
// real one. Left unset, Turbopack's own Node.js transform pool (postcss,
|
|
69
|
+
// for instance) cannot see the invoking workspace's node_modules at all,
|
|
70
|
+
// and fails with "Cannot find module" for a dependency that plain Node
|
|
71
|
+
// resolution finds without trouble.
|
|
72
|
+
turbopack: {
|
|
73
|
+
root: workspaceRoot,
|
|
74
|
+
},
|
|
75
|
+
// The output-file tracer only follows the CJS half of @swc/helpers' dual
|
|
76
|
+
// package and misses the `esm/` variant next's own require-hook resolves at
|
|
77
|
+
// runtime, so the standalone build ships a `@swc/helpers` directory missing
|
|
78
|
+
// its esm/ half. next resolves the package from its own nested pnpm store
|
|
79
|
+
// entry (node_modules/.pnpm/next@…/node_modules/@swc/helpers), which is a
|
|
80
|
+
// symlink into node_modules/.pnpm/@swc+helpers@0.5.23/node_modules/@swc/helpers
|
|
81
|
+
// — so that is the path that has to be complete, not the app's own copy.
|
|
82
|
+
outputFileTracingIncludes: {
|
|
83
|
+
'/**': [
|
|
84
|
+
`${upToWorkspaceRoot}/node_modules/.pnpm/@swc+helpers@0.5.23/node_modules/@swc/helpers/**/*`,
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
images: {
|
|
88
|
+
unoptimized: true,
|
|
89
|
+
},
|
|
90
|
+
// Every `@meith/*` package this app's dependency graph reaches — not just
|
|
91
|
+
// the ones apps/community imports directly. All of them ship TypeScript
|
|
92
|
+
// source with no build step (see docs/release.md, "They ship TypeScript
|
|
93
|
+
// source, deliberately"), and inside this monorepo every one of them is
|
|
94
|
+
// resolved through a tsconfig path alias straight to its source file,
|
|
95
|
+
// bypassing node_modules — which is why this list used to be a small,
|
|
96
|
+
// seemingly arbitrary subset: only the packages some other resolution path
|
|
97
|
+
// happened to touch via node_modules ever needed it here.
|
|
98
|
+
//
|
|
99
|
+
// A materialized workspace's own generated tsconfig carries no such alias
|
|
100
|
+
// map (see apps/community/bin/forum-web.mjs) — only `@board/config` and
|
|
101
|
+
// `@board/plugins`, the seam itself. Every other `@meith/*` specifier
|
|
102
|
+
// resolves the ordinary way once this package is npm-installed, which
|
|
103
|
+
// means every one of them needs this same source-compilation treatment,
|
|
104
|
+
// or the build fails with "Unknown module type" on its `src/index.ts`.
|
|
105
|
+
// Computed by walking this app's own imports plus every `@meith/*`
|
|
106
|
+
// package's own "dependencies" transitively — see docs/development.md,
|
|
107
|
+
// "Consuming the board from a workspace".
|
|
108
|
+
transpilePackages: [
|
|
109
|
+
'@meith/accounts',
|
|
110
|
+
'@meith/admin',
|
|
111
|
+
'@meith/antispam',
|
|
112
|
+
'@meith/api',
|
|
113
|
+
'@meith/attachments',
|
|
114
|
+
'@meith/authorization',
|
|
115
|
+
'@meith/avatars',
|
|
116
|
+
'@meith/core',
|
|
117
|
+
'@meith/db',
|
|
118
|
+
'@meith/demo',
|
|
119
|
+
'@meith/drafts',
|
|
120
|
+
'@meith/drivers',
|
|
121
|
+
'@meith/events',
|
|
122
|
+
'@meith/forums',
|
|
123
|
+
'@meith/groups',
|
|
124
|
+
'@meith/i18n',
|
|
125
|
+
'@meith/import',
|
|
126
|
+
'@meith/install',
|
|
127
|
+
'@meith/mail',
|
|
128
|
+
'@meith/markdown',
|
|
129
|
+
'@meith/marketplace',
|
|
130
|
+
'@meith/messages',
|
|
131
|
+
'@meith/moderation',
|
|
132
|
+
'@meith/notifications',
|
|
133
|
+
'@meith/plugin-dues',
|
|
134
|
+
'@meith/plugin-kit',
|
|
135
|
+
'@meith/polls',
|
|
136
|
+
'@meith/posts',
|
|
137
|
+
'@meith/profile-fields',
|
|
138
|
+
'@meith/relations',
|
|
139
|
+
'@meith/reputation',
|
|
140
|
+
'@meith/runtime',
|
|
141
|
+
'@meith/search',
|
|
142
|
+
'@meith/settings',
|
|
143
|
+
'@meith/signatures',
|
|
144
|
+
'@meith/subscriptions',
|
|
145
|
+
'@meith/tasks',
|
|
146
|
+
'@meith/theme-clubhouse',
|
|
147
|
+
'@meith/theme-default',
|
|
148
|
+
'@meith/theme-kit',
|
|
149
|
+
'@meith/theme-midnight',
|
|
150
|
+
'@meith/theme-phasebook',
|
|
151
|
+
'@meith/theme-raidframe',
|
|
152
|
+
'@meith/threads',
|
|
153
|
+
'@meith/ui',
|
|
154
|
+
'@meith/upgrade',
|
|
155
|
+
// Only reached through the `@meith/web/config` subpath, and only from a
|
|
156
|
+
// materialized workspace's own community.config.ts — inside this
|
|
157
|
+
// monorepo apps/community never imports itself by package name. Real
|
|
158
|
+
// once npm resolves this package into another workspace's node_modules,
|
|
159
|
+
// so it needs the same source-compilation treatment as everything else
|
|
160
|
+
// in this list.
|
|
161
|
+
'@meith/web',
|
|
162
|
+
],
|
|
163
|
+
async headers() {
|
|
164
|
+
return [
|
|
165
|
+
{
|
|
166
|
+
source: '/:path*',
|
|
167
|
+
headers: [
|
|
168
|
+
{ key: 'X-Content-Type-Options', value: 'nosniff' },
|
|
169
|
+
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
|
|
170
|
+
{ key: 'Strict-Transport-Security', value: 'max-age=63072000' },
|
|
171
|
+
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
|
|
172
|
+
{
|
|
173
|
+
key: 'Permissions-Policy',
|
|
174
|
+
value: 'camera=(), microphone=(), geolocation=()',
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export default nextConfig
|
package/package.json
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meith/web",
|
|
3
|
+
"version": "0.16.0",
|
|
4
|
+
"description": "The board itself: the Next.js app, and the forum-web bin that materializes it into an external board workspace.",
|
|
5
|
+
"license": "LGPL-3.0-or-later",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/meith-dev/meith.git",
|
|
9
|
+
"directory": "apps/community"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"forum-web": "./bin/forum-web.mjs"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
"./config": "./src/config.ts"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"bin",
|
|
19
|
+
"app",
|
|
20
|
+
"src",
|
|
21
|
+
"next.config.mjs",
|
|
22
|
+
"postcss.config.mjs",
|
|
23
|
+
"components.json",
|
|
24
|
+
"instrumentation.ts",
|
|
25
|
+
"proxy.ts",
|
|
26
|
+
"!src/**/*.test.*",
|
|
27
|
+
"!src/**/*.type-test.*",
|
|
28
|
+
"!app/**/*.test.*",
|
|
29
|
+
"!app/**/*.type-test.*"
|
|
30
|
+
],
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@swc/helpers": "0.5.23",
|
|
36
|
+
"@tailwindcss/postcss": "^4.3.3",
|
|
37
|
+
"next": "16.3.1",
|
|
38
|
+
"postcss": "^8.5",
|
|
39
|
+
"react": "19.2.8",
|
|
40
|
+
"react-dom": "19.2.8",
|
|
41
|
+
"tailwindcss": "^4.3.3",
|
|
42
|
+
"typescript": "7.0.2",
|
|
43
|
+
"@types/react": "^19",
|
|
44
|
+
"@types/react-dom": "^19",
|
|
45
|
+
"@meith/accounts": "0.16.0",
|
|
46
|
+
"@meith/antispam": "0.16.0",
|
|
47
|
+
"@meith/authorization": "0.16.0",
|
|
48
|
+
"@meith/attachments": "0.16.0",
|
|
49
|
+
"@meith/api": "0.16.0",
|
|
50
|
+
"@meith/admin": "0.16.0",
|
|
51
|
+
"@meith/avatars": "0.16.0",
|
|
52
|
+
"@meith/db": "0.16.0",
|
|
53
|
+
"@meith/drivers": "0.16.0",
|
|
54
|
+
"@meith/events": "0.16.0",
|
|
55
|
+
"@meith/drafts": "0.16.0",
|
|
56
|
+
"@meith/forums": "0.16.0",
|
|
57
|
+
"@meith/groups": "0.16.0",
|
|
58
|
+
"@meith/core": "0.16.0",
|
|
59
|
+
"@meith/demo": "0.16.0",
|
|
60
|
+
"@meith/mail": "0.16.0",
|
|
61
|
+
"@meith/install": "0.16.0",
|
|
62
|
+
"@meith/import": "0.16.0",
|
|
63
|
+
"@meith/markdown": "0.16.0",
|
|
64
|
+
"@meith/marketplace": "0.16.0",
|
|
65
|
+
"@meith/moderation": "0.16.0",
|
|
66
|
+
"@meith/notifications": "0.16.0",
|
|
67
|
+
"@meith/profile-fields": "0.16.0",
|
|
68
|
+
"@meith/plugin-kit": "0.16.0",
|
|
69
|
+
"@meith/posts": "0.16.0",
|
|
70
|
+
"@meith/polls": "0.16.0",
|
|
71
|
+
"@meith/i18n": "0.16.0",
|
|
72
|
+
"@meith/reputation": "0.16.0",
|
|
73
|
+
"@meith/search": "0.16.0",
|
|
74
|
+
"@meith/signatures": "0.16.0",
|
|
75
|
+
"@meith/settings": "0.16.0",
|
|
76
|
+
"@meith/subscriptions": "0.16.0",
|
|
77
|
+
"@meith/theme-clubhouse": "0.16.0",
|
|
78
|
+
"@meith/relations": "0.16.0",
|
|
79
|
+
"@meith/messages": "0.16.0",
|
|
80
|
+
"@meith/runtime": "0.16.0",
|
|
81
|
+
"@meith/plugin-dues": "0.16.0",
|
|
82
|
+
"@meith/theme-kit": "0.16.0",
|
|
83
|
+
"@meith/tasks": "0.16.0",
|
|
84
|
+
"@meith/theme-midnight": "0.16.0",
|
|
85
|
+
"@meith/theme-default": "0.16.0",
|
|
86
|
+
"@meith/theme-phasebook": "0.16.0",
|
|
87
|
+
"@meith/theme-raidframe": "0.16.0",
|
|
88
|
+
"@meith/threads": "0.16.0",
|
|
89
|
+
"@meith/upgrade": "0.16.0",
|
|
90
|
+
"@meith/ui": "0.16.0"
|
|
91
|
+
},
|
|
92
|
+
"scripts": {
|
|
93
|
+
"dev": "next dev",
|
|
94
|
+
"build": "next build",
|
|
95
|
+
"start": "next start",
|
|
96
|
+
"lint": "biome check .",
|
|
97
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
98
|
+
}
|
|
99
|
+
}
|