diff --git a/packages/shared/src/components/PlusUserBadge.tsx b/packages/shared/src/components/PlusUserBadge.tsx index 0c2d8ec339e..d9210b0a7df 100644 --- a/packages/shared/src/components/PlusUserBadge.tsx +++ b/packages/shared/src/components/PlusUserBadge.tsx @@ -3,7 +3,7 @@ import React from 'react'; import type { PublicProfile } from '../lib/user'; import { SimpleTooltip } from './tooltips'; import { PlusUser } from './PlusUser'; -import { plusUrl } from '../lib/constants'; +import { plusApiCta, plusUrl } from '../lib/constants'; import Link from './utilities/Link'; import { Typography, @@ -29,7 +29,7 @@ export const PlusUserBadge = ({ size = IconSize.Size16, }: Props): ReactElement | null => { const { isPlus, logSubscriptionEvent } = usePlusSubscription(); - const plusCta = 'Get API Access'; + const plusCta = plusApiCta; if (!user.isPlus) { return null; @@ -60,7 +60,7 @@ export const PlusUserBadge = ({ }); }} > - {plusCta}! + {plusCta} )} diff --git a/packages/shared/src/components/UpgradeToPlus.tsx b/packages/shared/src/components/UpgradeToPlus.tsx index 9e2e09019ef..be2932327cd 100644 --- a/packages/shared/src/components/UpgradeToPlus.tsx +++ b/packages/shared/src/components/UpgradeToPlus.tsx @@ -5,7 +5,7 @@ import type { ButtonSize } from './buttons/Button'; import { ButtonColor, Button, ButtonVariant } from './buttons/Button'; import { DevPlusIcon } from './icons'; import Link from './utilities/Link'; -import { plusUrl } from '../lib/constants'; +import { plusApiCta, plusApiCtaShort, plusUrl } from '../lib/constants'; import { useViewSize, ViewSize } from '../hooks'; import { usePlusSubscription } from '../hooks/usePlusSubscription'; import { usePlusSale } from '../hooks/usePlusSale'; @@ -39,7 +39,7 @@ export const UpgradeToPlus = ({ const isFullCTAText = !isLaptop || isLaptopXL; const { isPlus, logSubscriptionEvent } = usePlusSubscription(); const { isActive: isSaleActive } = usePlusSale(); - const ctaCopy = { full: 'Get API Access', short: 'API access' }; + const ctaCopy = { full: plusApiCta, short: plusApiCtaShort }; const content = isFullCTAText ? ctaCopy.full : ctaCopy.short; const showSaleLabel = isSaleActive && !iconOnly; const defaultColor = ButtonColor.Bacon; diff --git a/packages/shared/src/components/modals/IntroQuestModal.tsx b/packages/shared/src/components/modals/IntroQuestModal.tsx index afc3dd3a4dd..023633b63c4 100644 --- a/packages/shared/src/components/modals/IntroQuestModal.tsx +++ b/packages/shared/src/components/modals/IntroQuestModal.tsx @@ -53,6 +53,14 @@ const introDestinationByEventType: Record = { label: 'Profile', path: '/settings/profile', }, + api_token_create: { + label: 'API settings', + path: '/settings/api', + }, + api_profile_fetch: { + label: 'API settings', + path: '/settings/api', + }, }; const getExtensionIntroDestination = ( diff --git a/packages/shared/src/components/plus/PlusList.tsx b/packages/shared/src/components/plus/PlusList.tsx index a329223b034..639a1df29d3 100644 --- a/packages/shared/src/components/plus/PlusList.tsx +++ b/packages/shared/src/components/plus/PlusList.tsx @@ -66,9 +66,9 @@ export const defaultFeatureList: Array = [ export const plusFeatureListControl: Array = [ { id: 'public-api', - label: 'Public API access', + label: 'Full public API access and higher rate limits', status: PlusItemStatus.Ready, - tooltip: `Build custom integrations and access your personalized feed programmatically. Full API access to feeds, bookmarks, search, and more.`, + tooltip: `Build custom integrations and access your personalized feed programmatically. Full API access to feeds, bookmarks, search, and more with higher rate limits.`, }, { id: 'presidential-briefing', @@ -242,10 +242,10 @@ const reframeControlItem = ( export const plusFeatureListApiFirst: Array = [ { id: 'public-api', - label: 'Public API access', + label: 'Full public API access and higher rate limits', status: PlusItemStatus.Ready, highlight: true, - tooltip: `Endpoints for your feed, search, posts, and bookmarks. Plus pre-built integrations for Claude Code, Cursor, and Codex.`, + tooltip: `Full API access across your feed, search, posts, and bookmarks, with higher rate limits. Plus pre-built integrations for Claude Code, Cursor, and Codex.`, }, reframeControlItem( 'custom feeds', diff --git a/packages/shared/src/components/quest/questDestinations.ts b/packages/shared/src/components/quest/questDestinations.ts index 85cf622dc68..e7af07ad183 100644 --- a/packages/shared/src/components/quest/questDestinations.ts +++ b/packages/shared/src/components/quest/questDestinations.ts @@ -68,6 +68,12 @@ export const getQuestDestination = ( return { label: 'Feedback', path: '/settings/feedback' }; case 'squad_join': return { label: 'Squads', path: '/squads/discover' }; + case 'api_token_create': + case 'api_profile_fetch': + case 'api_feed_fetch': + case 'api_bookmark': + case 'api_search': + return { label: 'API settings', path: '/settings/api' }; default: return null; } diff --git a/packages/shared/src/components/sidebar/sections/MainSection.tsx b/packages/shared/src/components/sidebar/sections/MainSection.tsx index c1fa88f8b4d..15ace6a9096 100644 --- a/packages/shared/src/components/sidebar/sections/MainSection.tsx +++ b/packages/shared/src/components/sidebar/sections/MainSection.tsx @@ -21,6 +21,8 @@ import { OtherFeedPage } from '../../../lib/query'; import type { SidebarSectionProps } from './common'; import { gameCenterMilestoneSectionId, + plusApiCta, + plusApiCtaShort, plusUrl, webappUrl, } from '../../../lib/constants'; @@ -48,7 +50,7 @@ export const MainSection = ({ const { isV2 } = useLayoutVariant(); const isPlus = user?.isPlus; const { isActive: isSaleActive } = usePlusSale(); - const ctaCopy = { full: 'Get API Access', short: 'API access' }; + const ctaCopy = { full: plusApiCta, short: plusApiCtaShort }; const { value: showYearInReview } = useConditionalFeature({ feature: featureYearInReview, shouldEvaluate: isLoggedIn, diff --git a/packages/shared/src/components/sidebar/sections/ProfilePanelSection.tsx b/packages/shared/src/components/sidebar/sections/ProfilePanelSection.tsx index 2d7eeb8469f..6fd1fe0fda0 100644 --- a/packages/shared/src/components/sidebar/sections/ProfilePanelSection.tsx +++ b/packages/shared/src/components/sidebar/sections/ProfilePanelSection.tsx @@ -15,7 +15,12 @@ import { } from '../../icons'; import type { SidebarSectionProps } from './common'; import { OtherFeedPage } from '../../../lib/query'; -import { plusUrl, settingsUrl, webappUrl } from '../../../lib/constants'; +import { + plusApiCta, + plusUrl, + settingsUrl, + webappUrl, +} from '../../../lib/constants'; import { LogEvent, TargetId } from '../../../lib/log'; import { useAuthContext } from '../../../contexts/AuthContext'; import { usePlusSubscription } from '../../../hooks'; @@ -90,10 +95,10 @@ export const ProfilePanelSection = ({ } /> ), }, - // Non-Plus only: a purple "Get API Access" upgrade CTA (API access is a - // Plus perk). Plus users already have it, so it's hidden for them. + // Non-Plus only: a purple upgrade CTA for the higher API rate limits + // Plus carries. Plus users already have them, so it's hidden for them. !isPlus && { - title: 'Get API Access', + title: plusApiCta, path: plusUrl, isForcedLink: true, requiresLogin: true, diff --git a/packages/shared/src/features/ask/components/AskFAQ.tsx b/packages/shared/src/features/ask/components/AskFAQ.tsx index 90095c8ed84..a17fc330e91 100644 --- a/packages/shared/src/features/ask/components/AskFAQ.tsx +++ b/packages/shared/src/features/ask/components/AskFAQ.tsx @@ -24,7 +24,7 @@ const faq = [ { title: 'Is this free?', description: - 'daily-dev-ask requires a Plus subscription and an API token. You can get Plus at daily.dev/plus and create a token in your API settings.', + 'Yes. Any daily.dev account can create an API token in API settings and use daily-dev-ask. Plus adds full API access and higher rate limits, check it out at daily.dev/plus.', }, { title: 'What tools does it work with?', diff --git a/packages/shared/src/features/ask/components/AskInstall.tsx b/packages/shared/src/features/ask/components/AskInstall.tsx index af3954ee351..c89f28e7425 100644 --- a/packages/shared/src/features/ask/components/AskInstall.tsx +++ b/packages/shared/src/features/ask/components/AskInstall.tsx @@ -80,7 +80,7 @@ const methods: InstallMethod[] = [ export const AskInstall = (): ReactElement => { const { displayToast } = useToastNotification(); - const { isPlus } = usePlusSubscription(); + const { isPlus, logSubscriptionEvent } = usePlusSubscription(); const { isLoggedIn, showLogin } = useAuthContext(); const { logEvent } = useLogContext(); const [expandedTool, setExpandedTool] = useState(null); @@ -116,17 +116,14 @@ export const AskInstall = (): ReactElement => { color={TypographyColor.Secondary} center > - {isPlus ? ( + You'll need an{' '} + + API token + + . Pick your tool and install in seconds. + {!isPlus && ( <> - You'll need an{' '} - - API token - - . Pick your tool and install in seconds. - - ) : ( - <> - Requires a{' '} + {' '} { if (!isLoggedIn) { e.preventDefault(); showLogin({ trigger: AuthTriggers.Plus }); + return; } + logSubscriptionEvent({ + event_name: LogEvent.UpgradeSubscription, + target_id: TargetId.ApiAccess, + }); }} onKeyDown={(e) => { if (e.key === 'Enter' && !isLoggedIn) { @@ -145,14 +147,10 @@ export const AskInstall = (): ReactElement => { } }} > - Plus subscription + Upgrade to Plus {' '} - and an{' '} - - API token - - . Pick your tool and install in seconds. + for full API access and higher rate limits. )} diff --git a/packages/shared/src/lib/constants.ts b/packages/shared/src/lib/constants.ts index 8e962b8f031..3d37a9ac243 100644 --- a/packages/shared/src/lib/constants.ts +++ b/packages/shared/src/lib/constants.ts @@ -63,6 +63,8 @@ export const webappUrl = process.env.NEXT_PUBLIC_WEBAPP_URL as string; export const gameCenterMilestoneSectionId = 'milestone-quests'; export const onboardingUrl = `${webappUrl}onboarding`; export const plusUrl = `${webappUrl}plus`; +export const plusApiCta = 'Full API access and higher rate limits'; +export const plusApiCtaShort = 'Full API access'; export const managePlusUrl = 'https://r.daily.dev/billing'; export const plusDetailsUrl = 'https://r.daily.dev/plus-onboarding'; export const plusSuccessUrl = `${plusUrl}/success`; diff --git a/packages/shared/src/lib/log.ts b/packages/shared/src/lib/log.ts index aa2f72ad92c..a7890a1a4b8 100644 --- a/packages/shared/src/lib/log.ts +++ b/packages/shared/src/lib/log.ts @@ -648,6 +648,7 @@ export enum TargetId { MyProfile = 'my profile', PlusBadge = 'plus badge', PlusPage = 'plus page', + ApiAccess = 'api access', Onboarding = 'onboarding', BlockedWords = 'block words', CustomFeed = 'custom feed', diff --git a/packages/webapp/pages/agents/ask/index.tsx b/packages/webapp/pages/agents/ask/index.tsx index ca09cfd1c52..dc52a5e72f3 100644 --- a/packages/webapp/pages/agents/ask/index.tsx +++ b/packages/webapp/pages/agents/ask/index.tsx @@ -16,7 +16,7 @@ import { ButtonVariant, } from '@dailydotdev/shared/src/components/buttons/Button'; import { DevPlusIcon } from '@dailydotdev/shared/src/components/icons'; -import { plusUrl } from '@dailydotdev/shared/src/lib/constants'; +import { plusApiCta, plusUrl } from '@dailydotdev/shared/src/lib/constants'; import { useLogContext } from '@dailydotdev/shared/src/contexts/LogContext'; import { LogEvent, TargetId } from '@dailydotdev/shared/src/lib/log'; import { useAuthContext } from '@dailydotdev/shared/src/contexts/AuthContext'; @@ -153,15 +153,15 @@ const AskPage = (): ReactElement => { {!isPlus && (
- Unlock daily-dev-ask with Plus + {plusApiCta} - daily-dev-ask requires a Plus subscription. Upgrade to get API - access and connect your AI tools. + daily-dev-ask works on any account. Plus raises your request + limits and unlocks the Plus-only endpoints. - ) : undefined + } >
@@ -516,11 +513,41 @@ const ApiAccessPage = (): ReactElement => { type={TypographyType.Callout} color={TypographyColor.Tertiary} > - Use tokens to authenticate with the daily.dev API. Tokens provide - read-only access to your personalized feed and posts. + Use tokens to authenticate with the daily.dev API from agents, + scripts, and integrations.
+ {!isPlus && ( +
+ + {plusApiCta} + + + Plus raises your request limits and unlocks the Plus-only + endpoints, including bookmark folders and clickbait-shielded + titles. + + +
+ )} + {isLoading && ( { type={TypographyType.Callout} color={TypographyColor.Tertiary} > - {tokenEmptyStateText} + No tokens yet. Create one to get started. - {isPlus ? ( - - ) : ( - - )} +
)}