Skip to content

Commit 13a7c66

Browse files
authored
fix: Allow publishing to staging with CMS on free plan (#5721)
Also Clarify staging vs custom-domain upgrade messaging
1 parent b4941aa commit 13a7c66

4 files changed

Lines changed: 54 additions & 19 deletions

File tree

apps/builder/app/builder/features/pages/page-settings.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,8 @@ const PathField = ({
340340
<br />
341341
<Text>
342342
To make the path dynamic and use it with CMS, you can use
343-
parameters and other features. CMS features are part of the
344-
Pro plan.
343+
parameters and other features. You can publish to staging
344+
for free; upgrade to Pro to publish to custom domains.
345345
</Text>
346346
<Link
347347
className={buttonStyle({ color: "gradient" })}
@@ -855,8 +855,9 @@ const FormFields = ({
855855
{allowDynamicData === false && (
856856
<PanelBanner>
857857
<Text>
858-
Dynamic routing and redirect are a part of the CMS
859-
functionality.
858+
Dynamic routing and redirect are part of the CMS functionality.
859+
You can publish to staging for free; upgrade to Pro to publish
860+
to custom domains.
860861
</Text>
861862
<Flex align="center" gap={1}>
862863
<UploadIcon />

apps/builder/app/builder/features/publish/collapsible-domain-section.stories.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,9 @@ export const UpgradeBanners = () => (
382382
<li>Redirect</li>
383383
<li>Custom contact email</li>
384384
</Text>
385-
<Text>You can delete these features or upgrade.</Text>
385+
<Text>
386+
You can delete these features or upgrade to publish to custom domains.
387+
</Text>
386388
<Flex align="center" gap={1}>
387389
<UpgradeIcon />
388390
<Link color="inherit" href="#">

apps/builder/app/builder/features/publish/publish.tsx

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -401,19 +401,28 @@ const Publish = ({
401401
timesLeft,
402402
disabled,
403403
refresh,
404+
restrictedFeatures,
404405
}: {
405406
project: Project;
406407
timesLeft: number;
407408
disabled: boolean;
408409
refresh: () => Promise<void>;
410+
restrictedFeatures: Map<
411+
string,
412+
| undefined
413+
| { awareness?: Awareness; view?: "pageSettings"; info?: ReactNode }
414+
>;
409415
}) => {
410416
const { maxDailyPublishesPerUser } = useStore($permissions);
417+
const { userPublishCount } = useUserPublishCount();
411418
const [publishError, setPublishError] = useState<
412419
undefined | JSX.Element | string
413420
>();
414421
const [isPublishing, setIsPublishing] = useOptimistic(false);
415422
const buttonRef = useRef<HTMLButtonElement>(null);
416423
const [hasSelectedDomains, setHasSelectedDomains] = useState(false);
424+
const [hasCustomDomainsSelected, setHasCustomDomainsSelected] =
425+
useState(false);
417426
const countdown = usePublishCountdown(isPublishing);
418427

419428
useEffect(() => {
@@ -425,8 +434,18 @@ const Publish = ({
425434

426435
const handleFormInput = () => {
427436
const formData = new FormData(form);
428-
const domainsSelected = formData.getAll(domainToPublishName).length;
429-
setHasSelectedDomains(domainsSelected > 0);
437+
const domainsSelected = formData
438+
.getAll(domainToPublishName)
439+
.map((domain) => domain.toString());
440+
441+
setHasSelectedDomains(domainsSelected.length > 0);
442+
443+
// Check if any custom domains are selected
444+
// Custom domains are those that are NOT the staging domain (project.domain)
445+
const hasCustom = domainsSelected.some(
446+
(domain) => domain !== project.domain
447+
);
448+
setHasCustomDomainsSelected(hasCustom);
430449
};
431450

432451
const observer = new MutationObserver(() => {
@@ -445,7 +464,7 @@ const Publish = ({
445464
return () => {
446465
observer.disconnect();
447466
};
448-
}, []);
467+
}, [project.domain]);
449468

450469
const handlePublish = async (formData: FormData) => {
451470
setPublishError(undefined);
@@ -582,7 +601,12 @@ const Publish = ({
582601
formAction={handlePublish}
583602
color="positive"
584603
state={showPendingState ? "pending" : undefined}
585-
disabled={hasSelectedDomains === false || disabled}
604+
disabled={
605+
hasSelectedDomains === false ||
606+
disabled ||
607+
(restrictedFeatures.size > 0 && hasCustomDomainsSelected) ||
608+
userPublishCount >= maxDailyPublishesPerUser
609+
}
586610
>
587611
{countdown !== undefined && countdown > 0
588612
? `Publishing (${countdown}s)`
@@ -789,7 +813,7 @@ const buttonLinkClass = css({
789813
...textVariants.link,
790814
}).toString();
791815

792-
const UpgradeBanner = () => {
816+
const UpgradeBanner = ({ hasCustomDomains }: { hasCustomDomains: boolean }) => {
793817
const restrictedFeatures = useStore($restrictedFeatures);
794818
const { canAddDomain } = useCanAddDomain();
795819
const { userPublishCount, maxDailyPublishesPerUser } = useUserPublishCount();
@@ -812,7 +836,9 @@ const UpgradeBanner = () => {
812836
);
813837
}
814838

815-
if (restrictedFeatures.size > 0) {
839+
// Only show Pro feature upgrade banner if custom domains are available
840+
// Free tier users can still publish to staging domain with Pro features
841+
if (restrictedFeatures.size > 0 && hasCustomDomains) {
816842
return (
817843
<PanelBanner>
818844
<img
@@ -854,7 +880,9 @@ const UpgradeBanner = () => {
854880
)
855881
)}
856882
</Text>
857-
<Text>You can delete these features or upgrade.</Text>
883+
<Text>
884+
You can delete these features or upgrade to publish to custom domains.
885+
</Text>
858886
<Flex align="center" gap={1}>
859887
<UpgradeIcon />
860888
<Link
@@ -915,6 +943,11 @@ const Content = (props: {
915943
domain.latestBuildVirtual == null
916944
);
917945

946+
// Check if any custom domains exist (active and verified)
947+
const hasCustomDomains = project.domainsVirtual.some(
948+
(domain) => domain.status === "ACTIVE" && domain.verified
949+
);
950+
918951
return (
919952
<form>
920953
<ScrollArea>
@@ -947,7 +980,7 @@ const Content = (props: {
947980
}}
948981
onExportClick={props.onExportClick}
949982
/>
950-
<UpgradeBanner />
983+
<UpgradeBanner hasCustomDomains={hasCustomDomains} />
951984
{hasUnpublishedDomains && (
952985
<PanelBanner>
953986
<Flex align="center" gap="1">
@@ -964,10 +997,8 @@ const Content = (props: {
964997
project={project}
965998
refresh={refreshProject}
966999
timesLeft={maxDailyPublishesPerUser - userPublishCount}
967-
disabled={
968-
restrictedFeatures.size > 0 ||
969-
userPublishCount >= maxDailyPublishesPerUser
970-
}
1000+
disabled={false}
1001+
restrictedFeatures={restrictedFeatures}
9711002
/>
9721003
</Flex>
9731004
</form>

apps/builder/app/builder/features/settings-panel/settings-panel.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ export const SettingsPanel = ({
4545
width={rawTheme.spacing[28]}
4646
style={{ aspectRatio: "4.1" }}
4747
/>
48-
<Text variant="regularBold">Upgrade for CMS</Text>
48+
<Text variant="regularBold">Upgrade for CMS on custom domains</Text>
4949
<Text>
5050
Integrate content from other tools to create blogs, directories, and
51-
any other structured content.
51+
any other structured content. You can preview CMS on staging without
52+
upgrading.
5253
</Text>
5354
<Flex align="center" gap={1}>
5455
<UpgradeIcon />

0 commit comments

Comments
 (0)