diff --git a/README.md b/README.md index 610c9a2cdab..e9707107735 100644 --- a/README.md +++ b/README.md @@ -1,126 +1,170 @@ +

+ + We're live on Product Hunt — Support us + +

+

Twenty logo

-

The #1 Open-Source CRM

- -

🌐 Website · 📚 Documentation · Roadmap · Discord · Figma

-
+

The #1 Open-Source CRM

+

Website · Documentation · Roadmap · Discord · Figma

- - - Cover + + + Twenty banner


-# Installation - -See: -🚀 [Self-hosting](https://docs.twenty.com/developers/self-host/capabilities/docker-compose) -🖥️ [Local Setup](https://docs.twenty.com/developers/contribute/capabilities/local-setup) - # Why Twenty -We built Twenty for three reasons: +Twenty gives technical teams the building blocks for a custom CRM that meets complex business needs and quickly adapts as the business evolves. Twenty is the CRM you build, ship, and version like the rest of your stack. -**CRMs are too expensive, and users are trapped.** Companies use locked-in customer data to hike prices. It shouldn't be that way. - -**A fresh start is required to build a better experience.** We can learn from past mistakes and craft a cohesive experience inspired by new UX patterns from tools like Notion, Airtable or Linear. - -**We believe in open-source and community.** Hundreds of developers are already building Twenty together. Once we have plugin capabilities, a whole ecosystem will grow around it. + Learn more about why we built Twenty
-# What You Can Do With Twenty +# Installation -Please feel free to flag any specific needs you have by creating an issue. +### Cloud -Below are a few features we have implemented to date: +The fastest way to get started. Sign up at [twenty.com](https://twenty.com) and spin up a workspace in under a minute, with no infrastructure to manage and always up to date. -+ [Personalize layouts with filters, sort, group by, kanban and table views](#personalize-layouts-with-filters-sort-group-by-kanban-and-table-views) -+ [Customize your objects and fields](#customize-your-objects-and-fields) -+ [Create and manage permissions with custom roles](#create-and-manage-permissions-with-custom-roles) -+ [Automate workflow with triggers and actions](#automate-workflow-with-triggers-and-actions) -+ [Emails, calendar events, files, and more](#emails-calendar-events-files-and-more) +### Build an app +Scaffold a new app with the Twenty CLI: -## Personalize layouts with filters, sort, group by, kanban and table views +```bash +npx create-twenty-app my-app +``` -

- - - - Companies Kanban Views - -

+Define objects, fields, and views as code: -## Customize your objects and fields +```ts +import { defineObject, FieldType } from 'twenty-sdk/define'; -

- - - - Setting Custom Objects - -

+export default defineObject({ + nameSingular: 'deal', + namePlural: 'deals', + labelSingular: 'Deal', + labelPlural: 'Deals', + fields: [ + { name: 'name', label: 'Name', type: FieldType.TEXT }, + { name: 'amount', label: 'Amount', type: FieldType.CURRENCY }, + { name: 'closeDate', label: 'Close Date', type: FieldType.DATE_TIME }, + ], +}); +``` -## Create and manage permissions with custom roles +Then ship it to your workspace: -

- - - - Permissions - -

+```bash +npx twenty deploy +``` -## Automate workflow with triggers and actions +See the [app development guide](https://docs.twenty.com/developers/extend/apps/getting-started) for objects, views, agents, and logic functions. -

- - - - Workflows - -

+### Self-hosting -## Emails, calendar events, files, and more +Run Twenty on your own infrastructure with [Docker Compose](https://docs.twenty.com/developers/self-host/capabilities/docker-compose), or contribute locally via the [local setup guide](https://docs.twenty.com/developers/contribute/capabilities/local-setup). -

- - - - Other Features - -

+
+
+ +# Everything you need + +Twenty gives you the building blocks of a modern CRM (objects, views, workflows, and agents) and lets you extend them as code. Here's a tour of what's in the box. + +Want to go deeper? Read the User Guide for product walkthroughs, or the Documentation for developer reference. + + + + + + + + + + + + + + +
+ + + + Create your apps + +

Learn more about apps in doc

+
+ + + + Stay on top with version control + +

Learn more about version control in doc

+
+ + + + All the tools you need to build anything + +

Learn more about primitives in doc

+
+ + + + Customize your layouts + +

Learn more about layouts in doc

+
+ + + + AI agents and chats + +

Learn more about AI in doc

+
+ + + + Plus all the tools of a good CRM + +

Learn more about CRM features in doc

+

# Stack -- [TypeScript](https://www.typescriptlang.org/) -- [Nx](https://nx.dev/) -- [NestJS](https://nestjs.com/), with [BullMQ](https://bullmq.io/), [PostgreSQL](https://www.postgresql.org/), [Redis](https://redis.io/) -- [React](https://reactjs.org/), with [Jotai](https://jotai.org/), [Linaria](https://linaria.dev/) and [Lingui](https://lingui.dev/) + +- TypeScript +- Nx +- NestJS, with BullMQ, PostgreSQL, Redis +- React, with Jotai, Linaria and Lingui # Thanks

- Chromatic - Greptile - Sentry - Crowdin - E2B + Chromatic +      + Greptile +      + Sentry +      + Crowdin

Thanks to these amazing services that we use and recommend for UI testing (Chromatic), code review (Greptile), catching bugs (Sentry) and translating (Crowdin). @@ -128,9 +172,4 @@ Below are a few features we have implemented to date: # Join the Community -- Star the repo -- Subscribe to releases (watch -> custom -> releases) -- Follow us on [Twitter](https://twitter.com/twentycrm) or [LinkedIn](https://www.linkedin.com/company/twenty/) -- Join our [Discord](https://discord.gg/cx5n4Jzs57) -- Improve translations on [Crowdin](https://twenty.crowdin.com/twenty) -- [Contributions](https://github.com/twentyhq/twenty/contribute) are, of course, most welcome! +

Star the repo · Discord · Feature requests · Releases · X · LinkedIn · Crowdin · Contribute

diff --git a/packages/twenty-website-new/output/playwright/customers-reference.png b/packages/twenty-website-new/output/playwright/customers-reference.png new file mode 100644 index 00000000000..7e0706b19de Binary files /dev/null and b/packages/twenty-website-new/output/playwright/customers-reference.png differ diff --git a/packages/twenty-website-new/output/playwright/partners-full-after.png b/packages/twenty-website-new/output/playwright/partners-full-after.png new file mode 100644 index 00000000000..32671e79f90 Binary files /dev/null and b/packages/twenty-website-new/output/playwright/partners-full-after.png differ diff --git a/packages/twenty-website-new/output/playwright/partners-seam-after.png b/packages/twenty-website-new/output/playwright/partners-seam-after.png new file mode 100644 index 00000000000..e03549ae2c8 Binary files /dev/null and b/packages/twenty-website-new/output/playwright/partners-seam-after.png differ diff --git a/packages/twenty-website-new/src/app/(home)/page.tsx b/packages/twenty-website-new/src/app/(home)/page.tsx index b725a1a39c0..61a6bf829d4 100644 --- a/packages/twenty-website-new/src/app/(home)/page.tsx +++ b/packages/twenty-website-new/src/app/(home)/page.tsx @@ -11,6 +11,7 @@ import { TalkToUsButton } from '@/app/components/ContactCalModal'; import { FAQ_DATA, MENU_DATA, TRUSTED_BY_DATA } from '@/app/_constants'; import { Body, Eyebrow, Heading, LinkButton } from '@/design-system/components'; import { Pages } from '@/enums/pages'; +import { ArrowRightUpIcon } from '@/icons'; import { fetchCommunityStats } from '@/lib/community/fetch-community-stats'; import { mergeSocialLinkLabels } from '@/lib/community/merge-social-link-labels'; import { Faq } from '@/sections/Faq/components'; @@ -28,11 +29,15 @@ import { styled } from '@linaria/react'; import type { Metadata } from 'next'; export const metadata: Metadata = { - title: 'Twenty | Open Source CRM', - description: 'Modular, scalable open source CRM for modern teams.', + title: 'Twenty | #1 open source CRM', + description: + 'The #1 open source CRM for modern teams. Modular, scalable, and built to fit your business.', }; const HOME_TOP_BACKGROUND_COLOR = '#F4F4F4'; +const PRODUCT_HUNT_LAUNCH_URL = + 'https://www.producthunt.com/products/twenty-crm?launch=twenty-2-0'; +const PRODUCT_HUNT_BRAND_COLOR = '#DA552F'; const HeroHeadingGroup = styled.div` align-items: center; @@ -41,11 +46,63 @@ const HeroHeadingGroup = styled.div` gap: ${theme.spacing(3)}; width: 100%; - > *:nth-child(2) { + > *:last-child { margin-top: 0; } `; +const HeroLaunchChip = styled.a` + align-items: center; + background: ${theme.colors.primary.background[100]}; + border: 1px solid ${theme.colors.primary.border[10]}; + border-radius: 999px; + color: ${theme.colors.primary.text[100]}; + display: inline-flex; + font-family: ${theme.font.family.mono}; + font-size: ${theme.font.size(2.5)}; + font-weight: ${theme.font.weight.medium}; + gap: ${theme.spacing(2)}; + line-height: ${theme.lineHeight(3)}; + padding: ${theme.spacing(2)} ${theme.spacing(3)}; + text-decoration: none; + text-transform: uppercase; + transition: + border-color 180ms ease, + color 180ms ease, + transform 180ms ease; + white-space: nowrap; + + &:is(:hover, :focus-visible) { + border-color: ${PRODUCT_HUNT_BRAND_COLOR}; + color: ${PRODUCT_HUNT_BRAND_COLOR}; + transform: translateY(-1px); + } + + &:focus-visible { + outline: 1px solid ${theme.colors.highlight[100]}; + outline-offset: 2px; + } + + @media (prefers-reduced-motion: reduce) { + transition: none; + } +`; + +const HeroLaunchChipDot = styled.span` + background: ${PRODUCT_HUNT_BRAND_COLOR}; + border-radius: 999px; + display: block; + flex-shrink: 0; + height: ${theme.spacing(2)}; + width: ${theme.spacing(2)}; +`; + +const HeroLaunchChipLabel = styled.span` + align-items: center; + display: inline-flex; + gap: ${theme.spacing(1.5)}; +`; + const HeroIntroGroup = styled.div` align-items: center; display: flex; @@ -109,6 +166,17 @@ export default async function HomePage() { + + + + Live on Product Hunt + + + diff --git a/packages/twenty-website-new/src/app/_constants/faq.ts b/packages/twenty-website-new/src/app/_constants/faq.ts index b8085964de1..e582373e8f3 100644 --- a/packages/twenty-website-new/src/app/_constants/faq.ts +++ b/packages/twenty-website-new/src/app/_constants/faq.ts @@ -25,7 +25,7 @@ export const FAQ_DATA: FaqDataType = { fontFamily: 'sans', }, answer: { - text: "Yes. Twenty is the #1 open-source CRM on GitHub. Most teams run it on our managed cloud for zero-ops setup; self-hosting is always available if you'd rather own the infrastructure.", + text: "Yes. Twenty is the #1 open source CRM on GitHub. Most teams run it on our managed cloud for zero-ops setup; self-hosting is always available if you'd rather own the infrastructure.", }, }, { diff --git a/packages/twenty-website-new/src/app/_constants/menu.ts b/packages/twenty-website-new/src/app/_constants/menu.ts index d1a9207ac38..feb706d4d87 100644 --- a/packages/twenty-website-new/src/app/_constants/menu.ts +++ b/packages/twenty-website-new/src/app/_constants/menu.ts @@ -40,7 +40,7 @@ export const MENU_DATA: MenuDataType = { image: '/images/shared/menu/developers-preview.png', imageAlt: 'Blue developer illustration with branching arrows', imagePosition: 'center', - imageScale: 1.4, + imageScale: 1.6, title: 'Build on an open platform', description: 'APIs, SDKs and webhooks to extend Twenty and ship apps on top of your CRM data.', diff --git a/packages/twenty-website-new/src/app/customers/_constants/case-study-catalog.ts b/packages/twenty-website-new/src/app/customers/_constants/case-study-catalog.ts index 8a944494038..7a70314dd3a 100644 --- a/packages/twenty-website-new/src/app/customers/_constants/case-study-catalog.ts +++ b/packages/twenty-website-new/src/app/customers/_constants/case-study-catalog.ts @@ -120,7 +120,7 @@ export const CASE_STUDY_CATALOG_ENTRIES: CaseStudyCatalogEntry[] = [ 'NetZero uses Twenty as a modular CRM across product lines and countries, with a roadmap into AI-assisted workflows.', date: '2025', coverImageSrc: - 'https://images.unsplash.com/photo-1510524474345-1c4bac68d1d0?w=1600&q=80', + 'https://images.unsplash.com/photo-1744830343976-ce690ba2a67c?w=1600&q=80', }, }, { diff --git a/packages/twenty-website-new/src/app/customers/netzero/page.tsx b/packages/twenty-website-new/src/app/customers/netzero/page.tsx index 377d3c246a7..c50831f1cf5 100644 --- a/packages/twenty-website-new/src/app/customers/netzero/page.tsx +++ b/packages/twenty-website-new/src/app/customers/netzero/page.tsx @@ -10,7 +10,7 @@ import { theme } from '@/theme'; import type { Metadata } from 'next'; const PLACEHOLDER_HERO = - 'https://images.unsplash.com/photo-1510524474345-1c4bac68d1d0?w=1600&q=80'; + 'https://images.unsplash.com/photo-1744830343976-ce690ba2a67c?w=1600&q=80'; const CASE_STUDY: CaseStudyData = { meta: { diff --git a/packages/twenty-website-new/src/app/layout.tsx b/packages/twenty-website-new/src/app/layout.tsx index 0a3f78d70fa..4668c60cc7c 100644 --- a/packages/twenty-website-new/src/app/layout.tsx +++ b/packages/twenty-website-new/src/app/layout.tsx @@ -66,8 +66,9 @@ const StyledMain = styled.main` `; export const metadata: Metadata = { - title: 'Twenty | Open Source CRM', - description: 'Modular, scalable open source CRM for modern teams.', + title: 'Twenty | #1 open source CRM', + description: + 'The #1 open source CRM for modern teams. Modular, scalable, and built to fit your business.', }; export default function RootLayout({ diff --git a/packages/twenty-website-new/src/app/partners/_constants/hero.ts b/packages/twenty-website-new/src/app/partners/_constants/hero.ts index 1136bad9e72..0d82b9f3177 100644 --- a/packages/twenty-website-new/src/app/partners/_constants/hero.ts +++ b/packages/twenty-website-new/src/app/partners/_constants/hero.ts @@ -6,6 +6,6 @@ export const HERO_DATA = { { text: 'our partner', fontFamily: 'sans', newLine: true }, ], body: { - text: "We're building the #1 open-source CRM, but we can't do it alone. Join our partner ecosystem and grow with us.", + text: "We're building the #1 open source CRM, but we can't do it alone. Join our partner ecosystem and grow with us.", }, } satisfies HeroBaseDataType; diff --git a/packages/twenty-website-new/src/app/partners/_constants/three-cards-illustration.ts b/packages/twenty-website-new/src/app/partners/_constants/three-cards-illustration.ts index 8f6709f7c5d..5a1c23b9d2c 100644 --- a/packages/twenty-website-new/src/app/partners/_constants/three-cards-illustration.ts +++ b/packages/twenty-website-new/src/app/partners/_constants/three-cards-illustration.ts @@ -34,7 +34,7 @@ export const THREE_CARDS_ILLUSTRATION_DATA: ThreeCardsIllustrationDataType = { { heading: { text: 'Content & Community Partners', fontFamily: 'sans' }, body: { - text: "Share Twenty with your audience and help shape the future of open-source CRM. We're looking for creators, educators, and community builders who want to showcase great software.", + text: "Share Twenty with your audience and help shape the future of the #1 open source CRM. We're looking for creators, educators, and community builders who want to showcase great software.", }, benefits: [ { text: 'Revenue share for referred customers', icon: 'tag' }, diff --git a/packages/twenty-website-new/src/app/partners/page.tsx b/packages/twenty-website-new/src/app/partners/page.tsx index 4a9f02cc558..74c41103c65 100644 --- a/packages/twenty-website-new/src/app/partners/page.tsx +++ b/packages/twenty-website-new/src/app/partners/page.tsx @@ -26,6 +26,7 @@ import { ThreeCards } from '@/sections/ThreeCards/components'; import { TrustedBy } from '@/sections/TrustedBy/components'; import type { ThreeCardsScrollLayoutOptions } from '@/sections/ThreeCards/utils/three-cards-scroll-layout'; import { theme } from '@/theme'; +import { styled } from '@linaria/react'; import type { Metadata } from 'next'; const PARTNER_ILLUSTRATION_CARDS_SCROLL_LAYOUT_OPTIONS: ThreeCardsScrollLayoutOptions = @@ -37,10 +38,18 @@ const PARTNER_ILLUSTRATION_CARDS_SCROLL_LAYOUT_OPTIONS: ThreeCardsScrollLayoutOp stagger: 0.16, }; +const PromoSpacing = styled.div` + margin-bottom: ${theme.spacing(8)}; + + @media (min-width: ${theme.breakpoints.md}px) { + margin-bottom: ${theme.spacing(12)}; + } +`; + export const metadata: Metadata = { title: 'Partners | Twenty', description: - 'Join our partner ecosystem and grow with us as we build the #1 open-source CRM.', + 'Join our partner ecosystem and grow with us as we build the #1 open source CRM.', }; export default async function PartnerPage() { @@ -72,13 +81,16 @@ export default async function PartnerPage() { - + + + diff --git a/packages/twenty-website-new/src/app/pricing/page.tsx b/packages/twenty-website-new/src/app/pricing/page.tsx index c13f84068b4..1ef10047478 100644 --- a/packages/twenty-website-new/src/app/pricing/page.tsx +++ b/packages/twenty-website-new/src/app/pricing/page.tsx @@ -37,7 +37,7 @@ const PricingBannerContainer = styled.div` export const metadata: Metadata = { title: 'Pricing | Twenty', description: - 'Plans that scale with your team. Compare tiers of the #1 open-source CRM.', + 'Plans that scale with your team. Compare tiers of the #1 open source CRM.', }; export default async function PricingPage() { diff --git a/packages/twenty-website-new/src/app/releases/_constants/hero.ts b/packages/twenty-website-new/src/app/releases/_constants/hero.ts index ff73a36dcf2..bc97891a82c 100644 --- a/packages/twenty-website-new/src/app/releases/_constants/hero.ts +++ b/packages/twenty-website-new/src/app/releases/_constants/hero.ts @@ -7,5 +7,5 @@ export const RELEASE_NOTES_HERO_HEADING: HeadingType[] = [ ]; export const RELEASE_NOTES_HERO_BODY: BodyType = { - text: 'Discover the newest features and improvements in Twenty,\nthe #1 open-source CRM.', + text: 'Discover the newest features and improvements in Twenty,\nthe #1 open source CRM.', }; diff --git a/packages/twenty-website-new/src/app/releases/page.tsx b/packages/twenty-website-new/src/app/releases/page.tsx index 4fdeb4a3348..01a480333ff 100644 --- a/packages/twenty-website-new/src/app/releases/page.tsx +++ b/packages/twenty-website-new/src/app/releases/page.tsx @@ -21,7 +21,7 @@ import { Fragment } from 'react'; export const metadata: Metadata = { title: 'Releases | Twenty', description: - 'Discover the newest features and improvements in Twenty, the open-source CRM.', + 'Discover the newest features and improvements in Twenty, the #1 open source CRM.', }; export default async function ReleasesPage() { diff --git a/packages/twenty-website-new/src/app/why-twenty/page.tsx b/packages/twenty-website-new/src/app/why-twenty/page.tsx index be967d7c12f..e95221850dc 100644 --- a/packages/twenty-website-new/src/app/why-twenty/page.tsx +++ b/packages/twenty-website-new/src/app/why-twenty/page.tsx @@ -11,7 +11,6 @@ import { LinkButton } from '@/design-system/components'; import { Pages } from '@/enums/pages'; import { fetchCommunityStats } from '@/lib/community/fetch-community-stats'; import { mergeSocialLinkLabels } from '@/lib/community/merge-social-link-labels'; -import { OverflowProbe } from '@/lib/debug/overflow-probe'; import { Editorial } from '@/sections/Editorial/components'; import { Hero } from '@/sections/Hero/components'; import { Marquee } from '@/sections/Marquee/components'; @@ -72,7 +71,6 @@ export default async function WhyTwentyPage() { return ( <> - ` } `; -const CORNER_OFFSET = '-6px'; +const CORNER_SIZE = 14; +const CORNER_OFFSET = '-7px'; const FramedGrid = styled.div` position: relative; @@ -89,11 +90,12 @@ const FrameRailBottom = styled.span` const FrameCorner = styled.span` align-items: center; display: none; - height: 12px; + height: ${CORNER_SIZE}px; justify-content: center; + line-height: 0; pointer-events: none; position: absolute; - width: 12px; + width: ${CORNER_SIZE}px; @media (min-width: ${theme.breakpoints.md}px) { display: flex; @@ -157,18 +159,30 @@ export function Grid({ {!compactTop && ( <> - + - + )} - + - + {entries.map((entry, index) => { diff --git a/packages/twenty-website-new/src/sections/CaseStudyCatalog/components/Promo/Promo.tsx b/packages/twenty-website-new/src/sections/CaseStudyCatalog/components/Promo/Promo.tsx index c113a707fda..c01bc65e331 100644 --- a/packages/twenty-website-new/src/sections/CaseStudyCatalog/components/Promo/Promo.tsx +++ b/packages/twenty-website-new/src/sections/CaseStudyCatalog/components/Promo/Promo.tsx @@ -11,7 +11,9 @@ import { PromoMic } from '@/illustrations/CaseStudyCatalog/PromoMic'; import { theme } from '@/theme'; import { styled } from '@linaria/react'; -const CORNER_OFFSET = '-6px'; +const CORNER_SIZE = 14; +const CORNER_OFFSET = '-7px'; +const CONNECTED_TOP_OFFSET = '6px'; const LINE_INSET = '20px'; const TRUSTED_BY_BOTTOM_PADDING = 12; const TRUSTED_BY_BOTTOM_PADDING_DESKTOP = 16; @@ -59,12 +61,13 @@ const FrameBoard = styled.div` } `; -const Frame = styled.div` +const Frame = styled.div<{ compactTop: boolean }>` bottom: ${theme.spacing(12)}; left: ${theme.spacing(10)}; position: absolute; right: ${theme.spacing(10)}; - top: ${theme.spacing(12)}; + top: ${({ compactTop }) => + compactTop ? CONNECTED_TOP_OFFSET : theme.spacing(12)}; `; const FrameLine = styled.span` @@ -86,28 +89,29 @@ const FrameLineBottom = styled(FrameLine)` right: ${LINE_INSET}; `; -const FrameLineLeft = styled(FrameLine)` +const FrameLineLeft = styled(FrameLine)<{ compactTop: boolean }>` bottom: ${LINE_INSET}; left: 0; - top: ${LINE_INSET}; + top: ${({ compactTop }) => (compactTop ? '0' : LINE_INSET)}; width: 1px; `; -const FrameLineRight = styled(FrameLine)` +const FrameLineRight = styled(FrameLine)<{ compactTop: boolean }>` bottom: ${LINE_INSET}; right: 0; - top: ${LINE_INSET}; + top: ${({ compactTop }) => (compactTop ? '0' : LINE_INSET)}; width: 1px; `; const FrameCorner = styled.span` align-items: center; display: flex; - height: 12px; + height: ${CORNER_SIZE}px; justify-content: center; + line-height: 0; pointer-events: none; position: absolute; - width: 12px; + width: ${CORNER_SIZE}px; `; const FrameCornerTopLeft = styled(FrameCorner)` @@ -130,16 +134,20 @@ const FrameCornerBottomRight = styled(FrameCorner)` right: ${CORNER_OFFSET}; `; -const StyledContainer = styled(Container)` +const StyledContainer = styled(Container)<{ compactTop: boolean }>` align-items: center; display: grid; gap: ${theme.spacing(10)}; grid-template-columns: 1fr; min-height: 520px; - padding-bottom: ${theme.spacing(24 + TRUSTED_BY_BOTTOM_PADDING)}; + padding-bottom: ${({ compactTop }) => + compactTop + ? theme.spacing(16) + : theme.spacing(24 + TRUSTED_BY_BOTTOM_PADDING)}; padding-left: ${theme.spacing(4)}; padding-right: ${theme.spacing(4)}; - padding-top: ${theme.spacing(20)}; + padding-top: ${({ compactTop }) => + compactTop ? theme.spacing(16) : theme.spacing(20)}; position: relative; z-index: 1; @@ -147,12 +155,14 @@ const StyledContainer = styled(Container)` column-gap: ${theme.spacing(16)}; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); min-height: 500px; - padding-bottom: ${theme.spacing( - 40 + TRUSTED_BY_BOTTOM_PADDING_DESKTOP, - )}; + padding-bottom: ${({ compactTop }) => + compactTop + ? `calc(${theme.spacing(24)} + ${theme.spacing(12)} - ${CONNECTED_TOP_OFFSET})` + : theme.spacing(40 + TRUSTED_BY_BOTTOM_PADDING_DESKTOP)}; padding-left: ${theme.spacing(10)}; padding-right: ${theme.spacing(10)}; - padding-top: ${theme.spacing(32)}; + padding-top: ${({ compactTop }) => + compactTop ? theme.spacing(24) : theme.spacing(32)}; } `; @@ -250,41 +260,57 @@ type PromoProps = { entries: readonly CaseStudyCatalogEntry[]; ctaHref?: string; ctaLabel?: string; + compactTop?: boolean; }; export function Promo({ entries, ctaHref = '/customers', ctaLabel = 'Explore customer stories', + compactTop = false, }: PromoProps) { - const featured = entries[0]; - return (
- - + + {!compactTop && } - - - - - - - - + + + {!compactTop && ( + <> + + + + + + + + )} - + - + - + diff --git a/packages/twenty-website-new/src/sections/Faq/components/Item/Item.tsx b/packages/twenty-website-new/src/sections/Faq/components/Item/Item.tsx index 833df68ee35..2410cddcc90 100644 --- a/packages/twenty-website-new/src/sections/Faq/components/Item/Item.tsx +++ b/packages/twenty-website-new/src/sections/Faq/components/Item/Item.tsx @@ -8,10 +8,7 @@ import { } from '@/icons'; import type { FaqQuestionType } from '@/sections/Faq/types/FaqQuestion'; import { theme } from '@/theme'; -import { - Accordion as BaseAccordion, - type AccordionTriggerState, -} from '@base-ui/react/accordion'; +import { Accordion as BaseAccordion } from '@base-ui/react/accordion'; import { styled } from '@linaria/react'; const QuestionText = styled.span` @@ -55,12 +52,29 @@ const ToggleVisual = styled.span` display: inline-flex; height: 36px; justify-content: center; + position: relative; transition: border-color 0.2s ease, transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1); width: 36px; `; +const ToggleIconLayer = styled.span` + align-items: center; + display: inline-flex; + inset: 0; + justify-content: center; + position: absolute; + transition: + opacity 0.2s ease, + transform 0.2s ease; + + &[data-icon='minus'] { + opacity: 0; + transform: scale(0.9); + } +`; + const RowTrigger = styled.button` background: transparent; border: none; @@ -123,6 +137,16 @@ export const ItemRow = styled.div` opacity: 1; } + &[data-open] ${ToggleIconLayer}[data-icon='plus'] { + opacity: 0; + transform: scale(0.9); + } + + &[data-open] ${ToggleIconLayer}[data-icon='minus'] { + opacity: 1; + transform: scale(1); + } + @media (min-width: ${theme.breakpoints.md}px) { grid-template-columns: 14px 60px 1fr 80px 36px; row-gap: ${theme.spacing(4)}; @@ -186,42 +210,41 @@ export function Item({ question, value }: ItemProps) { return ( }> }> - { - const isOpen = state.open; - const ToggleIcon = isOpen ? MinusIcon : PlusIcon; - return ( - // oxlint-disable-next-line react/jsx-props-no-spreading -- Accordion.Trigger host props - - - - - - - - - + }> + + + + + + + + - {question.question.text} + {question.question.text} - - - - - - - ); - }} - /> + + + + + + + + + + + } keepMounted> diff --git a/packages/twenty-website-new/src/sections/TrustedBy/components/Root/Root.tsx b/packages/twenty-website-new/src/sections/TrustedBy/components/Root/Root.tsx index cd6626ce0b6..00e9464d050 100644 --- a/packages/twenty-website-new/src/sections/TrustedBy/components/Root/Root.tsx +++ b/packages/twenty-website-new/src/sections/TrustedBy/components/Root/Root.tsx @@ -4,7 +4,8 @@ import { theme } from '@/theme'; import { styled } from '@linaria/react'; import { Children, type ReactNode } from 'react'; -const CORNER_OFFSET = '-6px'; +const CORNER_SIZE = 14; +const CORNER_OFFSET = '-7px'; const StyledSection = styled.section<{ compactTop: boolean; @@ -18,6 +19,7 @@ const StyledSection = styled.section<{ compactTop ? theme.spacing(4) : theme.spacing(12)}; position: relative; width: 100%; + z-index: ${({ compactBottom }) => (compactBottom ? 2 : 'auto')}; @media (min-width: ${theme.breakpoints.md}px) { padding-bottom: ${({ compactBottom }) => @@ -97,11 +99,12 @@ const StyledCountCell = styled(StyledCell)` const CornerMarker = styled.span` align-items: center; display: flex; - height: 12px; + height: ${CORNER_SIZE}px; justify-content: center; + line-height: 0; pointer-events: none; position: absolute; - width: 12px; + width: ${CORNER_SIZE}px; `; const CornerTopLeft = styled(CornerMarker)` @@ -150,16 +153,28 @@ export function Root({ - + - + - + - + {label} {logos} diff --git a/packages/twenty-website/public/images/readme/book-icon.svg b/packages/twenty-website/public/images/readme/book-icon.svg new file mode 100644 index 00000000000..a21bb9485e6 Binary files /dev/null and b/packages/twenty-website/public/images/readme/book-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/code-icon.svg b/packages/twenty-website/public/images/readme/code-icon.svg new file mode 100644 index 00000000000..d4c56e01bf2 Binary files /dev/null and b/packages/twenty-website/public/images/readme/code-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/github-cover-dark.png b/packages/twenty-website/public/images/readme/github-cover-dark.png index eefe9c00dc3..d1218eefaaf 100644 Binary files a/packages/twenty-website/public/images/readme/github-cover-dark.png and b/packages/twenty-website/public/images/readme/github-cover-dark.png differ diff --git a/packages/twenty-website/public/images/readme/github-cover-light.png b/packages/twenty-website/public/images/readme/github-cover-light.png index edd19030213..17f2c177969 100644 Binary files a/packages/twenty-website/public/images/readme/github-cover-light.png and b/packages/twenty-website/public/images/readme/github-cover-light.png differ diff --git a/packages/twenty-website/public/images/readme/globe-icon.svg b/packages/twenty-website/public/images/readme/globe-icon.svg new file mode 100644 index 00000000000..13fbd24d57a Binary files /dev/null and b/packages/twenty-website/public/images/readme/globe-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/language-icon.svg b/packages/twenty-website/public/images/readme/language-icon.svg new file mode 100644 index 00000000000..e91550ecb7d Binary files /dev/null and b/packages/twenty-website/public/images/readme/language-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/linkedin-icon.svg b/packages/twenty-website/public/images/readme/linkedin-icon.svg new file mode 100644 index 00000000000..5f09a9ec9b2 Binary files /dev/null and b/packages/twenty-website/public/images/readme/linkedin-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/map-icon.svg b/packages/twenty-website/public/images/readme/map-icon.svg new file mode 100644 index 00000000000..ec4b078e65b Binary files /dev/null and b/packages/twenty-website/public/images/readme/map-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/message-icon.svg b/packages/twenty-website/public/images/readme/message-icon.svg new file mode 100644 index 00000000000..000a2a57457 Binary files /dev/null and b/packages/twenty-website/public/images/readme/message-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/monitor-icon.svg b/packages/twenty-website/public/images/readme/monitor-icon.svg new file mode 100644 index 00000000000..c00d29c7392 Binary files /dev/null and b/packages/twenty-website/public/images/readme/monitor-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/planner-icon.svg b/packages/twenty-website/public/images/readme/planner-icon.svg index 1715e5eb522..c6a1ad2ef6f 100644 Binary files a/packages/twenty-website/public/images/readme/planner-icon.svg and b/packages/twenty-website/public/images/readme/planner-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/product-hunt-banner.png b/packages/twenty-website/public/images/readme/product-hunt-banner.png new file mode 100644 index 00000000000..a57a66b8c57 Binary files /dev/null and b/packages/twenty-website/public/images/readme/product-hunt-banner.png differ diff --git a/packages/twenty-website/public/images/readme/rocket-icon.svg b/packages/twenty-website/public/images/readme/rocket-icon.svg new file mode 100644 index 00000000000..ed2801e7ab4 Binary files /dev/null and b/packages/twenty-website/public/images/readme/rocket-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/stack-nestjs.svg b/packages/twenty-website/public/images/readme/stack-nestjs.svg new file mode 100644 index 00000000000..0eccf9f1259 Binary files /dev/null and b/packages/twenty-website/public/images/readme/stack-nestjs.svg differ diff --git a/packages/twenty-website/public/images/readme/stack-nx.svg b/packages/twenty-website/public/images/readme/stack-nx.svg new file mode 100644 index 00000000000..03480bd647b Binary files /dev/null and b/packages/twenty-website/public/images/readme/stack-nx.svg differ diff --git a/packages/twenty-website/public/images/readme/stack-postgresql.svg b/packages/twenty-website/public/images/readme/stack-postgresql.svg new file mode 100644 index 00000000000..ef8a84efea8 Binary files /dev/null and b/packages/twenty-website/public/images/readme/stack-postgresql.svg differ diff --git a/packages/twenty-website/public/images/readme/stack-react.svg b/packages/twenty-website/public/images/readme/stack-react.svg new file mode 100644 index 00000000000..48b0c7c360f Binary files /dev/null and b/packages/twenty-website/public/images/readme/stack-react.svg differ diff --git a/packages/twenty-website/public/images/readme/stack-redis.svg b/packages/twenty-website/public/images/readme/stack-redis.svg new file mode 100644 index 00000000000..bd0adb694b0 Binary files /dev/null and b/packages/twenty-website/public/images/readme/stack-redis.svg differ diff --git a/packages/twenty-website/public/images/readme/stack-typescript.svg b/packages/twenty-website/public/images/readme/stack-typescript.svg new file mode 100644 index 00000000000..3610a90551f Binary files /dev/null and b/packages/twenty-website/public/images/readme/stack-typescript.svg differ diff --git a/packages/twenty-website/public/images/readme/star-icon.svg b/packages/twenty-website/public/images/readme/star-icon.svg new file mode 100644 index 00000000000..ce8149fa17f Binary files /dev/null and b/packages/twenty-website/public/images/readme/star-icon.svg differ diff --git a/packages/twenty-website/public/images/readme/v2-ai-agents-dark.png b/packages/twenty-website/public/images/readme/v2-ai-agents-dark.png new file mode 100644 index 00000000000..d24a3f9fadf Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-ai-agents-dark.png differ diff --git a/packages/twenty-website/public/images/readme/v2-ai-agents-light.png b/packages/twenty-website/public/images/readme/v2-ai-agents-light.png new file mode 100644 index 00000000000..c511c9fe1b0 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-ai-agents-light.png differ diff --git a/packages/twenty-website/public/images/readme/v2-ai-agents.png b/packages/twenty-website/public/images/readme/v2-ai-agents.png new file mode 100644 index 00000000000..a2beefeff3b Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-ai-agents.png differ diff --git a/packages/twenty-website/public/images/readme/v2-all-tools-dark.png b/packages/twenty-website/public/images/readme/v2-all-tools-dark.png new file mode 100644 index 00000000000..783b20ae662 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-all-tools-dark.png differ diff --git a/packages/twenty-website/public/images/readme/v2-all-tools-light.png b/packages/twenty-website/public/images/readme/v2-all-tools-light.png new file mode 100644 index 00000000000..e262f9de1a5 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-all-tools-light.png differ diff --git a/packages/twenty-website/public/images/readme/v2-build-apps-dark.png b/packages/twenty-website/public/images/readme/v2-build-apps-dark.png new file mode 100644 index 00000000000..eac6b93a1c2 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-build-apps-dark.png differ diff --git a/packages/twenty-website/public/images/readme/v2-build-apps-light.png b/packages/twenty-website/public/images/readme/v2-build-apps-light.png new file mode 100644 index 00000000000..6f3d2586b39 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-build-apps-light.png differ diff --git a/packages/twenty-website/public/images/readme/v2-build-apps.png b/packages/twenty-website/public/images/readme/v2-build-apps.png new file mode 100644 index 00000000000..6f3d2586b39 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-build-apps.png differ diff --git a/packages/twenty-website/public/images/readme/v2-crm-tools-dark.png b/packages/twenty-website/public/images/readme/v2-crm-tools-dark.png new file mode 100644 index 00000000000..08679042279 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-crm-tools-dark.png differ diff --git a/packages/twenty-website/public/images/readme/v2-crm-tools-light.png b/packages/twenty-website/public/images/readme/v2-crm-tools-light.png new file mode 100644 index 00000000000..8a77212b62d Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-crm-tools-light.png differ diff --git a/packages/twenty-website/public/images/readme/v2-crm-tools.png b/packages/twenty-website/public/images/readme/v2-crm-tools.png new file mode 100644 index 00000000000..90e34b48815 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-crm-tools.png differ diff --git a/packages/twenty-website/public/images/readme/v2-tools-dark.png b/packages/twenty-website/public/images/readme/v2-tools-dark.png new file mode 100644 index 00000000000..16bba7e0050 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-tools-dark.png differ diff --git a/packages/twenty-website/public/images/readme/v2-tools-light.png b/packages/twenty-website/public/images/readme/v2-tools-light.png new file mode 100644 index 00000000000..ee284b3f5ad Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-tools-light.png differ diff --git a/packages/twenty-website/public/images/readme/v2-tools.png b/packages/twenty-website/public/images/readme/v2-tools.png new file mode 100644 index 00000000000..6e5e9c4540b Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-tools.png differ diff --git a/packages/twenty-website/public/images/readme/v2-version-control-dark.png b/packages/twenty-website/public/images/readme/v2-version-control-dark.png new file mode 100644 index 00000000000..c90a843b281 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-version-control-dark.png differ diff --git a/packages/twenty-website/public/images/readme/v2-version-control-light.png b/packages/twenty-website/public/images/readme/v2-version-control-light.png new file mode 100644 index 00000000000..db6d8c32098 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-version-control-light.png differ diff --git a/packages/twenty-website/public/images/readme/v2-version-control.png b/packages/twenty-website/public/images/readme/v2-version-control.png new file mode 100644 index 00000000000..db6d8c32098 Binary files /dev/null and b/packages/twenty-website/public/images/readme/v2-version-control.png differ diff --git a/packages/twenty-website/public/images/readme/x-icon.svg b/packages/twenty-website/public/images/readme/x-icon.svg new file mode 100644 index 00000000000..47d6b9f1780 Binary files /dev/null and b/packages/twenty-website/public/images/readme/x-icon.svg differ