diff --git a/apps/web/src/components/flows/FlowHeader.tsx b/apps/web/src/components/flows/FlowHeader.tsx index f7e510fcd..750b35671 100644 --- a/apps/web/src/components/flows/FlowHeader.tsx +++ b/apps/web/src/components/flows/FlowHeader.tsx @@ -259,7 +259,7 @@ function PublishToCommunityModal({ flow, onClose }: { flow: Flow; onClose: () => headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tags }), }); - if (res.status === 400) { setErr('Publishing to the community hub is not configured on this instance.'); return; } + if (res.status === 400) { setErr('No community key configured. Get one in Settings → Community, then set COMMUNITY_HUB_KEY.'); return; } if (res.status === 409) { setErr('Publish a version of this flow first, then publish it to the community.'); return; } if (res.status === 403) { setErr('Only workspace owners, admins, and editors can publish.'); return; } if (!res.ok) { setErr('Publish failed. Try again.'); return; } diff --git a/apps/web/src/components/settings/CommunitySettings.tsx b/apps/web/src/components/settings/CommunitySettings.tsx new file mode 100644 index 000000000..5af6fac7f --- /dev/null +++ b/apps/web/src/components/settings/CommunitySettings.tsx @@ -0,0 +1,143 @@ +/** + * Community settings (Community Flows — Phase 3, P3-6). Self-host surface. + * + * Shows this instance's community-hub status. The publish credential + * (COMMUNITY_HUB_KEY) is an instance env var, so setting it stays out-of-band + * (env + restart) — there is no browser-writable secret here by design. But we + * DO surface a "get a free key" action: it emails a signed community-license key + * (via our hosted licensing service) that the operator then sets as + * COMMUNITY_HUB_KEY. This is the self-hoster's setup path for publishing. + */ +import { type JSX, useEffect, useState } from 'react'; + +const ink = 'var(--ink, #e7e7e9)'; +const soft = 'var(--ink-soft, #a1a1aa)'; +const muted = 'var(--ink-muted, #71717a)'; +const line = 'var(--line, rgba(255,255,255,0.1))'; +const surface = 'var(--surface, rgba(255,255,255,0.02))'; +const mono = { fontFamily: 'var(--mono, monospace)', fontSize: 12 } as const; + +// OUR hosted licensing service — the only outbound call, by explicit user action. +const LICENSE_SERVICE_URL = + (import.meta.env.PUBLIC_COMMUNITY_LICENSE_URL as string | undefined) ?? 'https://mnema.app/community-license'; + +interface Config { + enabled: boolean; + hub_url: string; + can_publish: boolean; +} + +function Row({ label, children }: { label: string; children: React.ReactNode }): JSX.Element { + return ( +
+ Browsing and importing community flows works out of the box. To publish your own flows,
+ this instance needs a community-license key set as the COMMUNITY_HUB_KEY environment
+ variable. To point at a different hub or disable the feature entirely, set{' '}
+ COMMUNITY_HUB_URL / COMMUNITY_HUB_ENABLED.
+
+ Looking to unlock version history and document export? That's a separate, + per-workspace step — redeem a community-license key under{' '} + Settings → Billing. +
+ + {!cfg.can_publish && ( +
+ Check your inbox for the signed key, then set it as COMMUNITY_HUB_KEY in this
+ instance's environment and restart the API. Publishing turns on once it's set.
+
+ We'll email you a free signed community-license key. Set it as COMMUNITY_HUB_KEY to
+ enable publishing from this instance.
+
{keyErr}
} + > + )} +