From 6de9d972ec921834dc7a7b83722c09c8b7e9cdf2 Mon Sep 17 00:00:00 2001 From: bosiraphael <71827178+bosiraphael@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:27:05 +0100 Subject: [PATCH 01/11] Change calendar transparency (#3732) fix --- .../components/SettingsAccountsSettingsSection.tsx | 8 ++++++-- .../settings/components/SettingsNavigationCard.tsx | 6 ++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx index 3c5337e65b0..0bd6a76e254 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx @@ -12,6 +12,10 @@ const StyledCardsContainer = styled.div` margin-top: ${({ theme }) => theme.spacing(6)}; `; +const StyledSettingsNavigationCard = styled(SettingsNavigationCard)` + color: ${({ theme }) => theme.font.color.extraLight}; +`; + export const SettingsAccountsSettingsSection = () => { const navigate = useNavigate(); @@ -29,14 +33,14 @@ export const SettingsAccountsSettingsSection = () => { > Set email visibility, manage your blocklist and more. - Configure and customize your calendar preferences. - + ); diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationCard.tsx b/packages/twenty-front/src/modules/settings/components/SettingsNavigationCard.tsx index 001ed5f8fed..3167f4257f7 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationCard.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsNavigationCard.tsx @@ -15,6 +15,7 @@ type SettingsNavigationCardProps = { Icon: IconComponent; onClick?: () => void; title: string; + className?: string; }; const StyledCard = styled(Card)<{ @@ -63,15 +64,16 @@ export const SettingsNavigationCard = ({ Icon, onClick, title, + className, }: SettingsNavigationCardProps) => { const theme = useTheme(); return ( - + - + {title} {hasSoonPill && } From 33bb48e68161a3f7d1b12f8f4c066060b1674d18 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Mon, 5 Feb 2024 11:27:51 +0100 Subject: [PATCH 02/11] Refactored dependencies from App component (#3763) * Refactored PageTitle to remove a dependency to location from App component * Refactored DefaultHomePage and DefaultPageTitle to remove dependencies from App component. --- packages/twenty-front/src/App.tsx | 15 +++++---------- packages/twenty-front/src/DefaultPageTitle.tsx | 11 +++++++++++ .../twenty-front/src/pages/DefaultHomePage.tsx | 9 +++++++++ 3 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 packages/twenty-front/src/DefaultPageTitle.tsx create mode 100644 packages/twenty-front/src/pages/DefaultHomePage.tsx diff --git a/packages/twenty-front/src/App.tsx b/packages/twenty-front/src/App.tsx index 33e6f267696..36a847dda77 100644 --- a/packages/twenty-front/src/App.tsx +++ b/packages/twenty-front/src/App.tsx @@ -1,19 +1,19 @@ -import { Navigate, Route, Routes, useLocation } from 'react-router-dom'; +import { Route, Routes } from 'react-router-dom'; import { AppPath } from '@/types/AppPath'; import { SettingsPath } from '@/types/SettingsPath'; import { DefaultLayout } from '@/ui/layout/page/DefaultLayout'; -import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; +import { DefaultPageTitle } from '~/DefaultPageTitle'; import { CommandMenuEffect } from '~/effect-components/CommandMenuEffect'; import { GotoHotkeysEffect } from '~/effect-components/GotoHotkeysEffect'; -import { useDefaultHomePagePath } from '~/hooks/useDefaultHomePagePath'; import { CreateProfile } from '~/pages/auth/CreateProfile'; import { CreateWorkspace } from '~/pages/auth/CreateWorkspace'; import { PasswordReset } from '~/pages/auth/PasswordReset'; import { PlanRequired } from '~/pages/auth/PlanRequired'; import { SignInUp } from '~/pages/auth/SignInUp'; import { VerifyEffect } from '~/pages/auth/VerifyEffect'; +import { DefaultHomePage } from '~/pages/DefaultHomePage'; import { ImpersonateEffect } from '~/pages/impersonate/ImpersonateEffect'; import { NotFound } from '~/pages/not-found/NotFound'; import { RecordIndexPage } from '~/pages/object-record/RecordIndexPage'; @@ -38,20 +38,15 @@ import { SettingsProfile } from '~/pages/settings/SettingsProfile'; import { SettingsWorkspace } from '~/pages/settings/SettingsWorkspace'; import { SettingsWorkspaceMembers } from '~/pages/settings/SettingsWorkspaceMembers'; import { Tasks } from '~/pages/tasks/Tasks'; -import { getPageTitleFromPath } from '~/utils/title-utils'; export const App = () => { - const { pathname } = useLocation(); - const { defaultHomePagePath } = useDefaultHomePagePath(); - - const pageTitle = getPageTitleFromPath(pathname); const isNewRecordBoardEnabled = useIsFeatureEnabled( 'IS_NEW_RECORD_BOARD_ENABLED', ); return ( <> - + @@ -64,7 +59,7 @@ export const App = () => { } /> } /> } /> - } /> + } /> } /> } /> diff --git a/packages/twenty-front/src/DefaultPageTitle.tsx b/packages/twenty-front/src/DefaultPageTitle.tsx new file mode 100644 index 00000000000..87b3c17f0b6 --- /dev/null +++ b/packages/twenty-front/src/DefaultPageTitle.tsx @@ -0,0 +1,11 @@ +import { useLocation } from 'react-router-dom'; + +import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; +import { getPageTitleFromPath } from '~/utils/title-utils'; + +export const DefaultPageTitle = () => { + const { pathname } = useLocation(); + const pageTitle = getPageTitleFromPath(pathname); + + return ; +}; diff --git a/packages/twenty-front/src/pages/DefaultHomePage.tsx b/packages/twenty-front/src/pages/DefaultHomePage.tsx new file mode 100644 index 00000000000..5fe09abdc37 --- /dev/null +++ b/packages/twenty-front/src/pages/DefaultHomePage.tsx @@ -0,0 +1,9 @@ +import { Navigate } from 'react-router-dom'; + +import { useDefaultHomePagePath } from '~/hooks/useDefaultHomePagePath'; + +export const DefaultHomePage = () => { + const { defaultHomePagePath } = useDefaultHomePagePath(); + + return ; +}; From 8dda4b0b8f6a0872605426b6b35dae01305c0151 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Mon, 5 Feb 2024 18:26:12 +0530 Subject: [PATCH 03/11] GH 3365 Add contributors page on twenty-website (#3745) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add transition in mobile navbar * add contributors listing page * Add breadcrumb component * Add profilecard component * Make profile info dynamic * Style activity log component * Make title a re-usable component * Make card container re-usable * add rank and active days logic * complete single contributor page * add styles for mobile * Add github link * Reset header desktop * update calendar height * remove conditional header * add GH PR link * display 10 prs * Remove employees and fix rank * Unrelated CSS adjustment --------- Co-authored-by: Félix Malfait --- .../src/app/components/AvatarGrid.tsx | 23 +++- .../src/app/components/Breadcrumbs.tsx | 55 +++++++++ .../src/app/components/HeaderDesktop.tsx | 89 +++------------ .../src/app/components/HeaderMobile.tsx | 16 ++- .../src/app/components/Icons.tsx | 37 +++++- .../developers/contributors/Header.tsx | 25 +++++ .../app/components/oss-friends/Background.tsx | 7 +- .../[slug]/components/ActivityLog.tsx | 20 +++- .../[slug]/components/Breadcrumb.tsx | 16 +++ .../[slug]/components/CardContainer.tsx | 17 +++ .../[slug]/components/ContentContainer.tsx | 26 +++++ .../[slug]/components/ProfileCard.tsx | 100 +++++++++++++++++ .../[slug]/components/ProfileInfo.tsx | 86 ++++++++++++++ .../[slug]/components/PullRequestItem.tsx | 94 ++++++++++++++++ .../[slug]/components/PullRequests.tsx | 44 ++++++++ .../[slug]/components/ThankYou.tsx | 38 +++++++ .../contributors/[slug]/components/Title.tsx | 13 +++ .../developers/contributors/[slug]/page.tsx | 106 ++++++++++++------ .../src/app/developers/contributors/page.tsx | 32 ++++-- packages/twenty-website/src/lib/utils.ts | 32 ++++++ 20 files changed, 749 insertions(+), 127 deletions(-) create mode 100644 packages/twenty-website/src/app/components/Breadcrumbs.tsx create mode 100644 packages/twenty-website/src/app/components/developers/contributors/Header.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/Breadcrumb.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/CardContainer.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/ContentContainer.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/ProfileCard.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/ProfileInfo.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/PullRequestItem.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/PullRequests.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/ThankYou.tsx create mode 100644 packages/twenty-website/src/app/developers/contributors/[slug]/components/Title.tsx create mode 100644 packages/twenty-website/src/lib/utils.ts diff --git a/packages/twenty-website/src/app/components/AvatarGrid.tsx b/packages/twenty-website/src/app/components/AvatarGrid.tsx index 5332eb3aeee..833525d5b57 100644 --- a/packages/twenty-website/src/app/components/AvatarGrid.tsx +++ b/packages/twenty-website/src/app/components/AvatarGrid.tsx @@ -9,14 +9,29 @@ export interface User { } const AvatarGridContainer = styled.div` - display: grid; - grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); - grid-gap: 10px; + margin: 0 auto; + max-width: 1024px; + justify-items: center; + display: flex; + justify-content: center; + gap: 32px; + flex-wrap: wrap; `; const AvatarItem = styled.div` position: relative; - width: 100%; + width: 124px; + height: 124px; + border: 3px solid #141414; + border-radius: 16px; + overflow: hidden; + transition: 200ms; + + &:hover { + -webkit-box-shadow: -6px 6px 0px 1px rgba(0, 0, 0, 1); + -moz-box-shadow: -6px 6px 0px 1px rgba(0, 0, 0, 1); + box-shadow: -6px 6px 0px 1px rgba(0, 0, 0, 1); + } img { width: 100%; diff --git a/packages/twenty-website/src/app/components/Breadcrumbs.tsx b/packages/twenty-website/src/app/components/Breadcrumbs.tsx new file mode 100644 index 00000000000..045dbd7be20 --- /dev/null +++ b/packages/twenty-website/src/app/components/Breadcrumbs.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import styled from '@emotion/styled'; +import Link from 'next/link'; + +const Container = styled.div` + display: flex; + gap: 8px; + color: #b3b3b3; +`; + +const InternalLinkItem = styled(Link)` + text-decoration: none; + color: #b3b3b3; +`; + +const ExternalLinkItem = styled.a` + text-decoration: none; + color: #b3b3b3; +`; + +const ActivePage = styled.span` + color: #818181; +`; + +interface BreadcrumbsProps { + items: { + uri: string; + label: string; + isExternal?: boolean; + }[]; + activePage: string; + separator: string; +} + +export const Breadcrumbs = ({ + items, + activePage, + separator, +}: BreadcrumbsProps) => { + return ( + + {items.map((item, index) => ( + + {item.isExternal ? ( + {item.label} + ) : ( + {item.label} + )} + {separator} + + ))} + {activePage} + + ); +}; diff --git a/packages/twenty-website/src/app/components/HeaderDesktop.tsx b/packages/twenty-website/src/app/components/HeaderDesktop.tsx index d91b88f914b..2a081465a71 100644 --- a/packages/twenty-website/src/app/components/HeaderDesktop.tsx +++ b/packages/twenty-website/src/app/components/HeaderDesktop.tsx @@ -2,11 +2,10 @@ import styled from '@emotion/styled'; import { IBM_Plex_Mono } from 'next/font/google'; -import { usePathname } from 'next/navigation'; import { ExternalArrow } from '@/app/components/ExternalArrow'; -import { DiscordIcon, GithubIcon, GithubIcon2, XIcon } from './Icons'; +import { GithubIcon } from './Icons'; import { Logo } from './Logo'; const IBMPlexMono = IBM_Plex_Mono({ @@ -102,88 +101,34 @@ const LinkNextToCTA = styled.a` `; const CallToAction = () => { - const path = usePathname(); - const isTwentyDev = path.includes('developers'); - return ( - {isTwentyDev ? ( - <> - - - ) : ( - <> - - Sign in - - - Get Started - - - )} + + Sign in + + + Get Started + ); }; export const HeaderDesktop = () => { - const path = usePathname(); - const isTwentyDev = path.includes('developers'); - return ( ); diff --git a/packages/twenty-website/src/app/components/HeaderMobile.tsx b/packages/twenty-website/src/app/components/HeaderMobile.tsx index e7f7e29e657..207caf88064 100644 --- a/packages/twenty-website/src/app/components/HeaderMobile.tsx +++ b/packages/twenty-website/src/app/components/HeaderMobile.tsx @@ -36,6 +36,7 @@ const LinkList = styled.div` display: flex; flex-direction: column; gap: 16px; + align-items: center; `; const ListItem = styled.a` @@ -45,7 +46,7 @@ const ListItem = styled.a` gap: 4px; align-items: center; border-radius: 8px; - height: 40px; + height: 48px; padding-left: 16px; padding-right: 16px; &:hover { @@ -174,6 +175,9 @@ const NavOpen = styled.div` gap: 33px; padding-top: 32px; z-index: 100; + transition: transform 0.2s ease-in; + display: flex; + transform-origin: top; `; const MobileMenu = styled.div` @@ -208,15 +212,19 @@ export const HeaderMobile = () => { - + - Pricing Story + Pricing Docs - 5.7k + 8.3k diff --git a/packages/twenty-website/src/app/components/Icons.tsx b/packages/twenty-website/src/app/components/Icons.tsx index b851db6cb19..661b4021c2f 100644 --- a/packages/twenty-website/src/app/components/Icons.tsx +++ b/packages/twenty-website/src/app/components/Icons.tsx @@ -7,7 +7,7 @@ const getSize = (size: string) => { case 'L': return '48px'; default: - return '14px'; + return size; } }; @@ -117,3 +117,38 @@ export const GithubIcon2 = ({ size = 'S', color = 'rgb(179, 179, 179)' }) => { ); }; + +export const PullRequestIcon = ({ size = 'S', color = 'rgb(179,179,179)' }) => { + const dimension = getSize(size); + return ( +
+ + + +
+ ); +}; + +export const HeartIcon = ({ size = 'S', color = 'rgb(179,179,179)' }) => { + const dimension = getSize(size); + return ( +
+ + + +
+ ); +}; diff --git a/packages/twenty-website/src/app/components/developers/contributors/Header.tsx b/packages/twenty-website/src/app/components/developers/contributors/Header.tsx new file mode 100644 index 00000000000..d9a8509bbe6 --- /dev/null +++ b/packages/twenty-website/src/app/components/developers/contributors/Header.tsx @@ -0,0 +1,25 @@ +'use client'; + +import styled from '@emotion/styled'; + +const Title = styled.h2` + font-size: 56px; + font-weight: 600; + color: #b3b3b3; + margin-bottom: 0px; + margin-top: 64px; + + @media (max-width: 810px) { + font-size: 28px; + } +`; + +export const Header = () => { + return ( + <> + + Our amazing <br /> <span style={{ color: 'black' }}>Contributors</span> + + + ); +}; diff --git a/packages/twenty-website/src/app/components/oss-friends/Background.tsx b/packages/twenty-website/src/app/components/oss-friends/Background.tsx index 83040d67823..f97b976d481 100644 --- a/packages/twenty-website/src/app/components/oss-friends/Background.tsx +++ b/packages/twenty-website/src/app/components/oss-friends/Background.tsx @@ -7,19 +7,20 @@ const BackgroundContainer = styled.div` top: 100%; left: 0px; width: 100%; - height: 200%; + height: 100%; + max-height: 200%; background-image: url(https://framerusercontent.com/images/nqEmdwe7yDXNsOZovuxG5zvj2E.png); background-size: auto 20px; background-repeat: repeat; transform-origin: center center; z-index: -2; - } `; const Gradient = styled.div` position: absolute; width: 100%; - height: 200%; + height: 100%; + max-height: 200%; top: 100%; left: 0; right: 0; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/ActivityLog.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ActivityLog.tsx index e7e19346544..fbe842f935b 100644 --- a/packages/twenty-website/src/app/developers/contributors/[slug]/components/ActivityLog.tsx +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ActivityLog.tsx @@ -2,10 +2,28 @@ import { ResponsiveTimeRange } from '@nivo/calendar'; +import { CardContainer } from '@/app/developers/contributors/[slug]/components/CardContainer'; +import { Title } from '@/app/developers/contributors/[slug]/components/Title'; + export const ActivityLog = ({ data, }: { data: { value: number; day: string }[]; }) => { - return ; + return ( + + Activity +
+ +
+
+ ); }; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/Breadcrumb.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/Breadcrumb.tsx new file mode 100644 index 00000000000..b5fea70bfec --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/Breadcrumb.tsx @@ -0,0 +1,16 @@ +'use client'; + +import { Breadcrumbs } from '@/app/components/Breadcrumbs'; + +const BREADCRUMB_ITEMS = [ + { + uri: '/developers/contributors', + label: 'Contributors', + }, +]; + +export const Breadcrumb = ({ active }: { active: string }) => { + return ( + + ); +}; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/CardContainer.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/CardContainer.tsx new file mode 100644 index 00000000000..7a2f828be38 --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/CardContainer.tsx @@ -0,0 +1,17 @@ +import styled from '@emotion/styled'; + +export const CardContainer = styled.div` + border: 3px solid #141414; + width: 100%; + border-radius: 12px; + padding: 40px; + display: flex; + gap: 32px; + flex-direction: column; + background-color: #fafafa; + + @media (max-width: 810px) { + gap: 16px; + padding: 24px; + } +`; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/ContentContainer.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ContentContainer.tsx new file mode 100644 index 00000000000..a24728a7fb6 --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ContentContainer.tsx @@ -0,0 +1,26 @@ +'use client'; + +import styled from '@emotion/styled'; + +const Container = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + width: 100%; + max-width: 898px; + padding: 40px; + + gap: 40px; + @media (max-width: 809px) { + width: 100%; + padding: 40px 24px 40px 24px; + } +`; + +export const ContentContainer = ({ + children, +}: { + children?: React.ReactNode; +}) => { + return {children}; +}; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/ProfileCard.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ProfileCard.tsx new file mode 100644 index 00000000000..f88a8d8b201 --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ProfileCard.tsx @@ -0,0 +1,100 @@ +'use client'; + +import styled from '@emotion/styled'; +import { format } from 'date-fns'; + +import { GithubIcon } from '@/app/components/Icons'; + +const ProfileContainer = styled.div` + display: flex; + gap: 32px; + width: 100%; + align-items: center; +`; + +const Avatar = styled.div` + border: 3px solid #141414; + width: 96px; + height: 96px; + border-radius: 16px; + overflow: hidden; + flex-shrink: 0; + + img { + width: 100%; + display: block; + height: 100%; + object-fit: cover; + } +`; + +const Details = styled.div` + display: flex; + flex-direction: column; + gap: 4px; + + .username { + font-size: 40px; + font-weight: 700; + line-height: 48px; + margin: 0; + display: flex; + gap: 12px; + + @media (max-width: 810px) { + font-size: 24px; + line-height: 28.8px; + } + } + + .duration { + font-size: 24px; + font-weight: 400; + color: #818181; + margin: 0; + + @media (max-width: 810px) { + font-size: 20px; + line-height: 28px; + } + } +`; + +const StyledGithubIcon = styled(GithubIcon)` + @media (max-width: 810px) { + width: 20px; + height: 20px; + } +`; + +interface ProfileCardProps { + username: string; + avatarUrl: string; + firstContributionAt: string; +} + +export const ProfileCard = ({ + username, + avatarUrl, + firstContributionAt, +}: ProfileCardProps) => { + return ( + + + {username} + +
+

+ @{username} + + + +

+

+ Contributing since{' '} + {format(new Date(firstContributionAt), 'MMMM yyyy')} +

+
+
+ ); +}; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/ProfileInfo.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ProfileInfo.tsx new file mode 100644 index 00000000000..2e2c9135c95 --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ProfileInfo.tsx @@ -0,0 +1,86 @@ +'use client'; + +import styled from '@emotion/styled'; + +import { CardContainer } from '@/app/developers/contributors/[slug]/components/CardContainer'; + +const Container = styled(CardContainer)` + flex-direction: row; + + @media (max-width: 810px) { + flex-direction: column; + } + + .item { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex-grow: 1; + flex-basis: 0; + + .title { + font-size: 24px; + color: #b3b3b3; + margin: 0; + + @media (max-width: 810px) { + font-size: 20px; + } + } + + .value { + font-size: 56px; + font-weight: 700; + color: #474747; + + @media (max-width: 810px) { + font-size: 32px; + } + } + } + + .separator { + width: 2px; + background-color: #141414; + border-radius: 40px; + + @media (max-width: 810px) { + width: 100%; + height: 2px; + } + } +`; + +interface ProfileInfoProps { + mergedPRsCount: number; + rank: string; + activeDays: number; +} + +export const ProfileInfo = ({ + mergedPRsCount, + rank, + activeDays, +}: ProfileInfoProps) => { + return ( + <> + +
+

Merged PR

+ {mergedPRsCount} +
+
+
+

Rank

+ {rank}% +
+
+
+

Active Days

+ {activeDays} +
+
+ + ); +}; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/PullRequestItem.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/PullRequestItem.tsx new file mode 100644 index 00000000000..0b1655fbfee --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/PullRequestItem.tsx @@ -0,0 +1,94 @@ +import { Tooltip } from 'react-tooltip'; +import styled from '@emotion/styled'; +import { format } from 'date-fns'; + +import { PullRequestIcon } from '@/app/components/Icons'; +import { formatIntoRelativeDate } from '@/lib/utils'; + +const StyledTooltip = styled(Tooltip)``; + +const Item = styled.div` + display: flex; + gap: 17px; +`; + +const StyledTitle = styled.a` + font-size: 24px; + font-weight: 400; + color: #474747; + margin: 0; + text-decoration: none; + + @media (max-width: 810px) { + font-size: 20px; + } +`; + +const StyledDescription = styled.div` + font-size: 20px; + line-height: 28px; + font-weight: 500; + color: #b3b3b3; + + @media (max-width: 810px) { + font-size: 18px; + } +`; + +const StyledPullRequestIcon = styled(PullRequestIcon)` + @media screen { + width: 20px; + height: 20px; + } +`; + +interface PullRequestItemProps { + id: string; + title: string; + url: string; + createdAt: string; + mergedAt: string | null; + authorId: string; +} + +export const PullRequestItem = ({ + id, + title, + url, + createdAt, + mergedAt, + authorId, +}: PullRequestItemProps) => { + const prNumber = url.split('/').slice(-1)[0]; + return ( + +
+ +
+
+ + {title} + + + #{prNumber} by {authorId.slice(1)} was{' '} + {mergedAt ? `merged` : `opened`}{' '} + + {formatIntoRelativeDate(mergedAt ? mergedAt : createdAt)} + + + +
+
+ ); +}; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/PullRequests.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/PullRequests.tsx new file mode 100644 index 00000000000..869730c159f --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/PullRequests.tsx @@ -0,0 +1,44 @@ +'use client'; + +import styled from '@emotion/styled'; + +import { CardContainer } from '@/app/developers/contributors/[slug]/components/CardContainer'; +import { PullRequestItem } from '@/app/developers/contributors/[slug]/components/PullRequestItem'; +import { Title } from '@/app/developers/contributors/[slug]/components/Title'; + +const List = styled.div` + display: flex; + gap: 24px; + flex-direction: column; +`; +interface PullRequestsProps { + list: { + id: string; + title: string; + url: string; + createdAt: string; + mergedAt: string | null; + authorId: string; + }[]; +} + +export const PullRequests = ({ list }: PullRequestsProps) => { + return ( + + Pull Requests + + {list.map((pr) => ( + + ))} + + + ); +}; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/ThankYou.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ThankYou.tsx new file mode 100644 index 00000000000..4a93eb6ba32 --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/ThankYou.tsx @@ -0,0 +1,38 @@ +'use client'; + +import styled from '@emotion/styled'; + +import { HeartIcon } from '@/app/components/Icons'; +import { CardContainer } from '@/app/developers/contributors/[slug]/components/CardContainer'; + +const StyledTitle = styled.div` + display: flex; + font-size: 24px; + font-weight: 500; + gap: 8px; + + @media (max-width: 810px) { + font-size: 20px; + } +`; + +const StyledHeartIcon = styled(HeartIcon)` + @media (max-width: 810px) { + width: 16px !important; + height: 16px !important; + } +`; + +interface ThankYouProps { + authorId: string; +} + +export const ThankYou = ({ authorId }: ThankYouProps) => { + return ( + + + Thank you @{authorId} + + + ); +}; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/components/Title.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/components/Title.tsx new file mode 100644 index 00000000000..8e15d06546a --- /dev/null +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/components/Title.tsx @@ -0,0 +1,13 @@ +import styled from '@emotion/styled'; + +export const Title = styled.h3` + margin: 0; + font-size: 32px; + line-height: 41.6px; + font-weight: 500; + + @media (max-width: 810px) { + font-size: 24px; + line-height: 31.2px; + } +`; diff --git a/packages/twenty-website/src/app/developers/contributors/[slug]/page.tsx b/packages/twenty-website/src/app/developers/contributors/[slug]/page.tsx index 694640b09ae..309c817aed3 100644 --- a/packages/twenty-website/src/app/developers/contributors/[slug]/page.tsx +++ b/packages/twenty-website/src/app/developers/contributors/[slug]/page.tsx @@ -1,8 +1,14 @@ import Database from 'better-sqlite3'; import { Metadata } from 'next'; -import Image from 'next/image'; -import { ActivityLog } from './components/ActivityLog'; +import { Background } from '@/app/components/oss-friends/Background'; +import { ActivityLog } from '@/app/developers/contributors/[slug]/components/ActivityLog'; +import { Breadcrumb } from '@/app/developers/contributors/[slug]/components/Breadcrumb'; +import { ContentContainer } from '@/app/developers/contributors/[slug]/components/ContentContainer'; +import { ProfileCard } from '@/app/developers/contributors/[slug]/components/ProfileCard'; +import { ProfileInfo } from '@/app/developers/contributors/[slug]/components/ProfileInfo'; +import { PullRequests } from '@/app/developers/contributors/[slug]/components/PullRequests'; +import { ThankYou } from '@/app/developers/contributors/[slug]/components/ThankYou'; interface Contributor { login: string; @@ -57,6 +63,7 @@ export default async function ({ params }: { params: { slug: string } }) { ) .all({ user_id: params.slug }) as { value: number; day: string }[]; + // Latest PRs. const pullRequestList = db .prepare( ` @@ -68,53 +75,88 @@ export default async function ({ params }: { params: { slug: string } }) { createdAt, updatedAt, closedAt, - mergedAt + mergedAt, + authorId FROM pullRequests WHERE authorId = (SELECT id FROM users WHERE login = :user_id) ORDER BY DATE(createdAt) DESC + LIMIT + 10 `, ) .all({ user_id: params.slug }) as { title: string; createdAt: string; url: string; + id: string; + mergedAt: string | null; + authorId: string; + }[]; + + const mergedPullRequests = db + .prepare( + ` + SELECT * FROM ( + SELECT + merged_pr_counts.*, + (RANK() OVER(ORDER BY merged_count) - 1) / CAST( total_authors as float) * 100 as rank_percentage + FROM + ( + SELECT + authorId, + COUNT(*) FILTER (WHERE mergedAt IS NOT NULL) as merged_count + FROM + pullRequests pr + JOIN + users u ON pr.authorId = u.id + WHERE + u.isEmployee = FALSE + GROUP BY + authorId + ) AS merged_pr_counts + CROSS JOIN + ( + SELECT COUNT(DISTINCT authorId) as total_authors + FROM pullRequests pr + JOIN + users u ON pr.authorId = u.id + WHERE + u.isEmployee = FALSE + ) AS author_counts + ) WHERE authorId = (SELECT id FROM users WHERE login = :user_id) + `, + ) + .all({ user_id: params.slug }) as { + merged_count: number; + rank_percentage: number; }[]; db.close(); return ( -
-
- {contributor.login} + + + + -

{contributor.login}

-
-
-
- -
-
- {pullRequestList.map((pr) => ( - - ))} -
-
-
+ + + + + + ); } diff --git a/packages/twenty-website/src/app/developers/contributors/page.tsx b/packages/twenty-website/src/app/developers/contributors/page.tsx index ef7ea6cfdd7..051a2f9fa05 100644 --- a/packages/twenty-website/src/app/developers/contributors/page.tsx +++ b/packages/twenty-website/src/app/developers/contributors/page.tsx @@ -1,6 +1,9 @@ import Database from 'better-sqlite3'; import AvatarGrid from '@/app/components/AvatarGrid'; +import { Header } from '@/app/components/developers/contributors/Header'; +import { Background } from '@/app/components/oss-friends/Background'; +import { ContentContainer } from '@/app/components/oss-friends/ContentContainer'; interface Contributor { login: string; @@ -14,16 +17,19 @@ const Contributors = async () => { const contributors = db .prepare( `SELECT - u.login, - u.avatarUrl, - COUNT(pr.id) AS pullRequestCount - FROM + u.login, + u.avatarUrl, + COUNT(pr.id) AS pullRequestCount + FROM users u - JOIN + JOIN pullRequests pr ON u.id = pr.authorId - GROUP BY + WHERE + u.isEmployee = FALSE + AND u.login NOT IN ('dependabot', 'cyborch', 'emilienchvt', 'Samox') + GROUP BY u.id - ORDER BY + ORDER BY pullRequestCount DESC; `, ) @@ -32,9 +38,15 @@ const Contributors = async () => { db.close(); return ( -
- -
+ <> + + +
+
+ +
+ + ); }; diff --git a/packages/twenty-website/src/lib/utils.ts b/packages/twenty-website/src/lib/utils.ts new file mode 100644 index 00000000000..91aa777546c --- /dev/null +++ b/packages/twenty-website/src/lib/utils.ts @@ -0,0 +1,32 @@ +import { differenceInDays, formatDistance } from 'date-fns'; + +const formatIntoRelativeDate = (dateString: string) => { + if (!dateString) return ''; + const inputDate = new Date(dateString); + const currentDate = new Date(); + + const daysDifference = differenceInDays(currentDate, inputDate); + let formattedDate = ''; + if (daysDifference === 0) { + formattedDate = 'today'; + } else if (daysDifference === 1) { + formattedDate = 'yesterday'; + } else if (daysDifference < 7) { + formattedDate = formatDistance(inputDate, currentDate, { addSuffix: true }); + } else if (daysDifference < 14) { + formattedDate = 'last week'; + } else if (daysDifference < 30) { + formattedDate = Math.floor(daysDifference / 7) + ' weeks ago'; + } else if (daysDifference < 60) { + formattedDate = 'last month'; + } else if (daysDifference < 365) { + formattedDate = Math.floor(daysDifference / 30) + ' months'; + } else if (daysDifference < 730) { + formattedDate = 'last year'; + } else { + formattedDate = Math.floor(daysDifference / 365) + ' years ago'; + } + return formattedDate; +}; + +export { formatIntoRelativeDate }; From 6748dfebc4b595b940a827f6ee1026387eb532e2 Mon Sep 17 00:00:00 2001 From: Jeet Desai <52026385+jeet1desai@users.noreply.github.com> Date: Mon, 5 Feb 2024 19:29:37 +0530 Subject: [PATCH 04/11] Added loader in sign-in-up button (#3801) #3375 added loader in sign-in-up button --- .../auth/sign-in-up/components/SignInUpForm.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx index c45efb44577..85d04ba2074 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx @@ -5,6 +5,7 @@ import styled from '@emotion/styled'; import { motion } from 'framer-motion'; import { IconGoogle } from '@/ui/display/icon/components/IconGoogle'; +import { Loader } from '@/ui/feedback/loader/components/Loader'; import { MainButton } from '@/ui/input/button/components/MainButton'; import { TextInput } from '@/ui/input/components/TextInput'; import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn'; @@ -85,8 +86,12 @@ export const SignInUpForm = () => { return 'Continue'; } - return signInUpMode === SignInUpMode.SignIn ? 'Sign in' : 'Sign up'; - }, [signInUpMode, signInUpStep]); + return signInUpMode === SignInUpMode.SignIn + ? 'Sign in' + : isSubmitting + ? 'Creating workspace' + : 'Sign up'; + }, [signInUpMode, signInUpStep, isSubmitting]); const title = useMemo(() => { if (signInUpMode === SignInUpMode.Invite) { @@ -215,6 +220,7 @@ export const SignInUpForm = () => { setShowErrors(true); handleSubmit(submitCredentials)(); }} + Icon={() => isSubmitting && } disabled={ SignInUpStep.Init ? false From a5989a470cfa0c6677e5ef880c43fd1d0f21aa2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 5 Feb 2024 15:01:37 +0100 Subject: [PATCH 05/11] Improve Documentation (#3795) * Begin docs improvement * Keep improving documentation * Upgrade Docusarus * Fix broken links --- README.md | 2 +- package.json | 8 +- .../docs/contributor/_category_.json | 4 +- .../bug-and-requests.mdx | 2 +- .../docs/contributor/frontend/_category_.json | 4 +- .../frontend/advanced/_category_.json | 4 - .../frontend/basics/_category_.json | 4 - .../contributor/frontend/basics/basics.mdx | 53 --- .../frontend/basics/contributing.mdx | 44 --- .../frontend/basics/design-system.mdx | 10 - .../{advanced => }/best-practices.mdx | 2 +- .../{basics => }/folder-architecture.mdx | 0 .../docs/contributor/frontend/frontend.mdx | 80 +++- .../frontend/{advanced => }/hotkeys.mdx | 0 .../frontend/{advanced => }/style-guide.mdx | 0 .../frontend/{basics => }/work-with-figma.mdx | 0 .../docs/contributor/server/_category_.json | 4 +- .../contributor/server/basics/_category_.json | 4 - .../contributor/server/basics/overview.mdx | 35 -- .../contributor/server/basics/workflows.mdx | 61 --- .../server/{others => }/best-practices.mdx | 0 .../server/{basics => }/custom-objects.mdx | 0 .../server/{others => }/feature-flags.mdx | 0 .../{basics => }/folder-architecture.mdx | 0 .../contributor/server/others/_category_.json | 4 - .../contributor/server/{basics => }/queue.mdx | 0 .../docs/contributor/server/server.mdx | 87 +++- .../server/{others => }/zapier.mdx | 0 .../docs/developer/_category_.json | 4 - .../docs/developer/graphql_api.mdx | 25 -- .../twenty-docs/docs/developer/rest_api.mdx | 29 -- packages/twenty-docs/docs/index.mdx | 38 +- .../twenty-docs/docs/start/_category_.json | 2 +- packages/twenty-docs/docs/start/cloud.mdx | 21 + .../docs/start/getting-started.mdx | 29 -- .../local-setup/_category_.json | 2 +- .../local-setup/docker-setup.mdx | 4 +- .../local-setup/ide-setup.mdx | 4 +- .../local-setup/local-setup.mdx | 11 +- .../local-setup/troubleshooting.mdx | 2 +- .../local-setup/yarn-setup.mdx | 2 +- .../start/self-hosting/1-click-deploy.mdx | 20 + .../start/self-hosting/docker-compose.mdx | 62 +++ .../self-hosting/environment-variables.mdx | 173 -------- .../docs/start/self-hosting/self-hosting.mdx | 183 ++++++++- .../docs/start/self-hosting/upgrade-guide.mdx | 8 + .../ui-components/_category_.json | 0 .../ui-components/display/_category_.json | 0 .../ui-components/display/app-tooltip.mdx | 0 .../ui-components/display/checkmark.mdx | 0 .../ui-components/display/chip.mdx | 0 .../ui-components/display/icons.mdx | 0 .../ui-components/display/soon-pill.mdx | 0 .../ui-components/display/tag.mdx | 0 .../ui-components/feedback/_category_.json | 0 .../ui-components/feedback/progress-bar.mdx | 0 .../ui-components/input/_category_.json | 0 .../ui-components/input/block-editor.mdx | 0 .../ui-components/input/button.mdx | 0 .../ui-components/input/checkbox.mdx | 0 .../ui-components/input/color-scheme.mdx | 0 .../ui-components/input/icon-picker.mdx | 0 .../ui-components/input/image-input.mdx | 0 .../ui-components/input/radio.mdx | 0 .../ui-components/input/select.mdx | 0 .../ui-components/input/text.mdx | 0 .../ui-components/input/toggle.mdx | 0 .../ui-components/navigation/_category_.json | 0 .../ui-components/navigation/bread-crumb.mdx | 0 .../ui-components/navigation/link.mdx | 0 .../ui-components/navigation/menu-item.mdx | 0 .../navigation/navigation-bar.mdx | 0 .../ui-components/navigation/step-bar.mdx | 0 .../ui-components/ui-components.mdx | 0 packages/twenty-docs/docusaurus.config.js | 103 +++-- packages/twenty-docs/sidebars.js | 106 ++++- packages/twenty-docs/src/css/custom.css | 54 ++- .../twenty-docs/src/theme/DocCard/index.js | 36 +- .../src/theme/DocSidebarItem/index.js | 67 ++++ .../src/theme/Icon/DarkMode/index.js | 9 +- .../src/theme/Icon/LightMode/index.js | 9 +- .../src/theme/Navbar/Search/index.js | 5 + .../src/theme/NavbarItem/ComponentTypes.js | 24 ++ .../src/theme/NavbarItem/GithubLink.tsx | 21 + packages/twenty-docs/src/theme/icons.js | 96 ++--- .../static/img/dark-doc-preview.png | Bin 296857 -> 384070 bytes .../static/img/light-doc-preview.png | Bin 367251 -> 340943 bytes packages/twenty-front/package.json | 2 +- packages/twenty-server/package.json | 2 +- packages/twenty-utils/dangerfile.ts | 4 +- yarn.lock | 371 +++++++++--------- 91 files changed, 1045 insertions(+), 895 deletions(-) rename packages/twenty-docs/docs/{start => contributor}/bug-and-requests.mdx (94%) delete mode 100644 packages/twenty-docs/docs/contributor/frontend/advanced/_category_.json delete mode 100644 packages/twenty-docs/docs/contributor/frontend/basics/_category_.json delete mode 100644 packages/twenty-docs/docs/contributor/frontend/basics/basics.mdx delete mode 100644 packages/twenty-docs/docs/contributor/frontend/basics/contributing.mdx delete mode 100644 packages/twenty-docs/docs/contributor/frontend/basics/design-system.mdx rename packages/twenty-docs/docs/contributor/frontend/{advanced => }/best-practices.mdx (99%) rename packages/twenty-docs/docs/contributor/frontend/{basics => }/folder-architecture.mdx (100%) rename packages/twenty-docs/docs/contributor/frontend/{advanced => }/hotkeys.mdx (100%) rename packages/twenty-docs/docs/contributor/frontend/{advanced => }/style-guide.mdx (100%) rename packages/twenty-docs/docs/contributor/frontend/{basics => }/work-with-figma.mdx (100%) delete mode 100644 packages/twenty-docs/docs/contributor/server/basics/_category_.json delete mode 100644 packages/twenty-docs/docs/contributor/server/basics/overview.mdx delete mode 100644 packages/twenty-docs/docs/contributor/server/basics/workflows.mdx rename packages/twenty-docs/docs/contributor/server/{others => }/best-practices.mdx (100%) rename packages/twenty-docs/docs/contributor/server/{basics => }/custom-objects.mdx (100%) rename packages/twenty-docs/docs/contributor/server/{others => }/feature-flags.mdx (100%) rename packages/twenty-docs/docs/contributor/server/{basics => }/folder-architecture.mdx (100%) delete mode 100644 packages/twenty-docs/docs/contributor/server/others/_category_.json rename packages/twenty-docs/docs/contributor/server/{basics => }/queue.mdx (100%) rename packages/twenty-docs/docs/contributor/server/{others => }/zapier.mdx (100%) delete mode 100644 packages/twenty-docs/docs/developer/_category_.json delete mode 100644 packages/twenty-docs/docs/developer/graphql_api.mdx delete mode 100644 packages/twenty-docs/docs/developer/rest_api.mdx create mode 100644 packages/twenty-docs/docs/start/cloud.mdx delete mode 100644 packages/twenty-docs/docs/start/getting-started.mdx rename packages/twenty-docs/docs/{contributor => start}/local-setup/_category_.json (88%) rename packages/twenty-docs/docs/{contributor => start}/local-setup/docker-setup.mdx (96%) rename packages/twenty-docs/docs/{contributor => start}/local-setup/ide-setup.mdx (85%) rename packages/twenty-docs/docs/{contributor => start}/local-setup/local-setup.mdx (66%) rename packages/twenty-docs/docs/{contributor => start}/local-setup/troubleshooting.mdx (86%) rename packages/twenty-docs/docs/{contributor => start}/local-setup/yarn-setup.mdx (98%) create mode 100644 packages/twenty-docs/docs/start/self-hosting/1-click-deploy.mdx create mode 100644 packages/twenty-docs/docs/start/self-hosting/docker-compose.mdx delete mode 100644 packages/twenty-docs/docs/start/self-hosting/environment-variables.mdx create mode 100644 packages/twenty-docs/docs/start/self-hosting/upgrade-guide.mdx rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/_category_.json (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/display/_category_.json (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/display/app-tooltip.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/display/checkmark.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/display/chip.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/display/icons.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/display/soon-pill.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/display/tag.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/feedback/_category_.json (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/feedback/progress-bar.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/_category_.json (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/block-editor.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/button.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/checkbox.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/color-scheme.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/icon-picker.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/image-input.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/radio.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/select.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/text.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/input/toggle.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/navigation/_category_.json (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/navigation/bread-crumb.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/navigation/link.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/navigation/menu-item.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/navigation/navigation-bar.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/navigation/step-bar.mdx (100%) rename packages/twenty-docs/docs/{contributor/frontend => }/ui-components/ui-components.mdx (100%) create mode 100644 packages/twenty-docs/src/theme/DocSidebarItem/index.js create mode 100644 packages/twenty-docs/src/theme/Navbar/Search/index.js create mode 100644 packages/twenty-docs/src/theme/NavbarItem/ComponentTypes.js create mode 100644 packages/twenty-docs/src/theme/NavbarItem/GithubLink.tsx diff --git a/README.md b/README.md index 685fd0bb36d..1e60833efa9 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ We’ve spent thousands of hours grappling with traditional CRMs like Pipedrive and Salesforce to align them with our business needs, only to end up frustrated — customizations are complex and the closed ecosystems of these platforms can feel restrictive. -We felt the need for a CRM platform that empowers rather than constrains. We believe the next great CRM will come from the open source community. And we’ve packed Twenty with powerful features to give you full control and help you win more deals. +We felt the need for a CRM platform that empowers rather than constrains. We believe the next great CRM will come from the open source community. And we’ve packed Twenty with powerful features to give you full control and help you run your business efficiently.
diff --git a/package.json b/package.json index 2c6eafec7ce..be7799e9e9b 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "@chakra-ui/accordion": "^2.3.0", "@chakra-ui/system": "^2.6.0", "@codesandbox/sandpack-react": "^2.11.3", - "@docusaurus/core": "^3.0.0", - "@docusaurus/preset-classic": "^3.0.0", + "@docusaurus/core": "^3.1.0", + "@docusaurus/preset-classic": "^3.1.0", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@floating-ui/react": "^0.24.3", @@ -157,8 +157,8 @@ "devDependencies": { "@babel/core": "^7.14.5", "@babel/preset-react": "^7.14.5", - "@docusaurus/module-type-aliases": "^3.0.0", - "@docusaurus/tsconfig": "3.0.0", + "@docusaurus/module-type-aliases": "^3.1.0", + "@docusaurus/tsconfig": "3.1.0", "@graphql-codegen/cli": "^3.3.1", "@graphql-codegen/client-preset": "^4.1.0", "@graphql-codegen/typescript": "^3.0.4", diff --git a/packages/twenty-docs/docs/contributor/_category_.json b/packages/twenty-docs/docs/contributor/_category_.json index c4117720daf..e12f1ce53d7 100644 --- a/packages/twenty-docs/docs/contributor/_category_.json +++ b/packages/twenty-docs/docs/contributor/_category_.json @@ -1,4 +1,4 @@ { - "label": "Contributor guide", - "position": 2 + "label": "Contributing", + "position": 3 } diff --git a/packages/twenty-docs/docs/start/bug-and-requests.mdx b/packages/twenty-docs/docs/contributor/bug-and-requests.mdx similarity index 94% rename from packages/twenty-docs/docs/start/bug-and-requests.mdx rename to packages/twenty-docs/docs/contributor/bug-and-requests.mdx index ca11ade5d64..63d022f4a8d 100644 --- a/packages/twenty-docs/docs/start/bug-and-requests.mdx +++ b/packages/twenty-docs/docs/contributor/bug-and-requests.mdx @@ -1,5 +1,5 @@ --- -title: Bugs & Requests +title: Bugs and Requests sidebar_position: 3 sidebar_custom_props: icon: TbBug diff --git a/packages/twenty-docs/docs/contributor/frontend/_category_.json b/packages/twenty-docs/docs/contributor/frontend/_category_.json index 0c949e0fa50..254ec2489a9 100644 --- a/packages/twenty-docs/docs/contributor/frontend/_category_.json +++ b/packages/twenty-docs/docs/contributor/frontend/_category_.json @@ -1,3 +1,5 @@ { - "position": 3 + "position": 3, + "collapsible": true, + "collapsed": true } diff --git a/packages/twenty-docs/docs/contributor/frontend/advanced/_category_.json b/packages/twenty-docs/docs/contributor/frontend/advanced/_category_.json deleted file mode 100644 index dd1c52f2ee6..00000000000 --- a/packages/twenty-docs/docs/contributor/frontend/advanced/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Advanced", - "position": 3 -} diff --git a/packages/twenty-docs/docs/contributor/frontend/basics/_category_.json b/packages/twenty-docs/docs/contributor/frontend/basics/_category_.json deleted file mode 100644 index daec3e16a89..00000000000 --- a/packages/twenty-docs/docs/contributor/frontend/basics/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Basics", - "position": 1 -} diff --git a/packages/twenty-docs/docs/contributor/frontend/basics/basics.mdx b/packages/twenty-docs/docs/contributor/frontend/basics/basics.mdx deleted file mode 100644 index 69b2e233f4c..00000000000 --- a/packages/twenty-docs/docs/contributor/frontend/basics/basics.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Basics -sidebar_position: 0 ---- - -import DocCardList from '@theme/DocCardList'; - - - -## Tech Stack - -The project has a clean and simple stack, with minimal boilerplate code. - -**App** - -- [React](https://react.dev/) -- [Apollo](https://www.apollographql.com/docs/) -- [GraphQL Codegen](https://the-guild.dev/graphql/codegen) -- [Recoil](https://recoiljs.org/docs/introduction/core-concepts) -- [TypeScript](https://www.typescriptlang.org/) - -**Testing** - -- [Jest](https://jestjs.io/) -- [Storybook](https://storybook.js.org/) - -**Tooling** - -- [Yarn](https://yarnpkg.com/) -- [Craco](https://craco.js.org/docs/) -- [ESLint](https://eslint.org/) - -## Architecture - -### Routing - -[React Router](https://reactrouter.com/) handles the routing. - -To avoid unnecessary [re-renders](/contributor/frontend/advanced/best-practices#managing-re-renders) all the routing logic is in a `useEffect` in `PageChangeEffect`. - -### State Management - -[Recoil](https://recoiljs.org/docs/introduction/core-concepts) handles state management. - -See [best practices](/contributor/frontend/advanced/best-practices#state-management) for more information on state management. - -## Testing - -[Jest](https://jestjs.io/) serves as the tool for unit testing while [Storybook](https://storybook.js.org/) is for component testing. - -Jest is mainly for testing utility functions, and not components themselves. - -Storybook is for testing the behavior of isolated components, as well as displaying the [design system](/contributor/frontend/basics/design-system). diff --git a/packages/twenty-docs/docs/contributor/frontend/basics/contributing.mdx b/packages/twenty-docs/docs/contributor/frontend/basics/contributing.mdx deleted file mode 100644 index 885a8a2d070..00000000000 --- a/packages/twenty-docs/docs/contributor/frontend/basics/contributing.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Contributing -sidebar_position: 1 -description: Learn how you can contribute to the project -sidebar_custom_props: - icon: TbTopologyStar ---- - -## Pre-requisites - -Make sure that your [IDE is correctly setup](/contributor/local-setup/ide-setup) and that your backend is running on `localhost:3000`. - - -## Starting a new feature - -Make sure your database is running on the URL provided in your `server/.env` file. - -```bash -cd front -yarn - -yarn start -``` - -## Regenerate graphql schema based on API graphql schema - -```bash -yarn graphql:generate -``` - -## Lint - -```bash -yarn lint -``` - -## Test - -```bash -yarn test # run jest tests -yarn storybook:dev # run storybook -yarn storybook:test # run tests (needs yarn storybook:dev to be running) -yarn storybook:coverage # run tests (needs yarn storybook:dev to be running) -``` diff --git a/packages/twenty-docs/docs/contributor/frontend/basics/design-system.mdx b/packages/twenty-docs/docs/contributor/frontend/basics/design-system.mdx deleted file mode 100644 index 11790e14c37..00000000000 --- a/packages/twenty-docs/docs/contributor/frontend/basics/design-system.mdx +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Design System -description: What our design system looks like -sidebar_position: 7 -sidebar_custom_props: - icon: TbPaint ---- - -The CRM depends on its internal and custom design system, constructed on top of styled-components. - diff --git a/packages/twenty-docs/docs/contributor/frontend/advanced/best-practices.mdx b/packages/twenty-docs/docs/contributor/frontend/best-practices.mdx similarity index 99% rename from packages/twenty-docs/docs/contributor/frontend/advanced/best-practices.mdx rename to packages/twenty-docs/docs/contributor/frontend/best-practices.mdx index 872e12a513a..e946733f370 100644 --- a/packages/twenty-docs/docs/contributor/frontend/advanced/best-practices.mdx +++ b/packages/twenty-docs/docs/contributor/frontend/best-practices.mdx @@ -268,7 +268,7 @@ Prop drilling, in the React context, refers to the practice of passing state var 3. **Reduced Component Reusability**: A component receiving a lot of props solely for passing them down becomes less general-purpose and harder to reuse in different contexts. -If you feel that you are using excessive prop drilling, see [state management best practices](/contributor/frontend/advanced/best-practices#state-management). +If you feel that you are using excessive prop drilling, see [state management best practices](#state-management). ## Imports diff --git a/packages/twenty-docs/docs/contributor/frontend/basics/folder-architecture.mdx b/packages/twenty-docs/docs/contributor/frontend/folder-architecture.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/frontend/basics/folder-architecture.mdx rename to packages/twenty-docs/docs/contributor/frontend/folder-architecture.mdx diff --git a/packages/twenty-docs/docs/contributor/frontend/frontend.mdx b/packages/twenty-docs/docs/contributor/frontend/frontend.mdx index 1069f4000db..434bac164be 100644 --- a/packages/twenty-docs/docs/contributor/frontend/frontend.mdx +++ b/packages/twenty-docs/docs/contributor/frontend/frontend.mdx @@ -1,14 +1,86 @@ --- id: frontend title: Frontend Development -displayed_sidebar: frontendSidebar sidebar_position: 0 sidebar_custom_props: icon: TbTerminal2 - isSidebarRoot: true --- -Welcome to the Frontend Development section of the documentation. -Here you will find information about the frontend development process, the recommended tools, and the best practices you should follow. +import DocCardList from '@theme/DocCardList'; + + +## Useful commands + +### Starting the app + +```bash + nx start twenty-front + ``` + +### Regenerate graphql schema based on API graphql schema + +```bash +nx graphql:generate twenty-front +``` + +### Lint + +```bash +nx lint twenty-front +``` + +### Test + +```bash +nx test twenty-front# run jest tests +nx storybook:dev twenty-front# run storybook +nx storybook:test twenty-front# run tests # (needs yarn storybook:dev to be running) +nx storybook:coverage twenty-front # (needs yarn storybook:dev to be running) +``` + +## Tech Stack + +The project has a clean and simple stack, with minimal boilerplate code. + +**App** + +- [React](https://react.dev/) +- [Apollo](https://www.apollographql.com/docs/) +- [GraphQL Codegen](https://the-guild.dev/graphql/codegen) +- [Recoil](https://recoiljs.org/docs/introduction/core-concepts) +- [TypeScript](https://www.typescriptlang.org/) + +**Testing** + +- [Jest](https://jestjs.io/) +- [Storybook](https://storybook.js.org/) + +**Tooling** + +- [Yarn](https://yarnpkg.com/) +- [Craco](https://craco.js.org/docs/) +- [ESLint](https://eslint.org/) + +## Architecture + +### Routing + +[React Router](https://reactrouter.com/) handles the routing. + +To avoid unnecessary [re-renders](/contributor/frontend/best-practices#managing-re-renders) all the routing logic is in a `useEffect` in `PageChangeEffect`. + +### State Management + +[Recoil](https://recoiljs.org/docs/introduction/core-concepts) handles state management. + +See [best practices](/contributor/frontend/best-practices#state-management) for more information on state management. + +## Testing + +[Jest](https://jestjs.io/) serves as the tool for unit testing while [Storybook](https://storybook.js.org/) is for component testing. + +Jest is mainly for testing utility functions, and not components themselves. + +Storybook is for testing the behavior of isolated components, as well as displaying the design system. diff --git a/packages/twenty-docs/docs/contributor/frontend/advanced/hotkeys.mdx b/packages/twenty-docs/docs/contributor/frontend/hotkeys.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/frontend/advanced/hotkeys.mdx rename to packages/twenty-docs/docs/contributor/frontend/hotkeys.mdx diff --git a/packages/twenty-docs/docs/contributor/frontend/advanced/style-guide.mdx b/packages/twenty-docs/docs/contributor/frontend/style-guide.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/frontend/advanced/style-guide.mdx rename to packages/twenty-docs/docs/contributor/frontend/style-guide.mdx diff --git a/packages/twenty-docs/docs/contributor/frontend/basics/work-with-figma.mdx b/packages/twenty-docs/docs/contributor/frontend/work-with-figma.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/frontend/basics/work-with-figma.mdx rename to packages/twenty-docs/docs/contributor/frontend/work-with-figma.mdx diff --git a/packages/twenty-docs/docs/contributor/server/_category_.json b/packages/twenty-docs/docs/contributor/server/_category_.json index 484e2553d79..cf5d22abcbc 100644 --- a/packages/twenty-docs/docs/contributor/server/_category_.json +++ b/packages/twenty-docs/docs/contributor/server/_category_.json @@ -1,3 +1,5 @@ { - "position": 4 + "position": 4, + "collapsible": true, + "collapsed": true } diff --git a/packages/twenty-docs/docs/contributor/server/basics/_category_.json b/packages/twenty-docs/docs/contributor/server/basics/_category_.json deleted file mode 100644 index daec3e16a89..00000000000 --- a/packages/twenty-docs/docs/contributor/server/basics/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Basics", - "position": 1 -} diff --git a/packages/twenty-docs/docs/contributor/server/basics/overview.mdx b/packages/twenty-docs/docs/contributor/server/basics/overview.mdx deleted file mode 100644 index 1cd742a3ce3..00000000000 --- a/packages/twenty-docs/docs/contributor/server/basics/overview.mdx +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Overview -sidebar_position: 0 -sidebar_custom_props: - icon: TbEyeglass ---- - -Twenty primarily uses NestJS for the backend. - -Prisma was the first choice as the ORM with a lot of auto-generated code under the hood. But to offer users flexibility and allow them to create custom fields and custom objects, something more low-level than Prisma made more sense to have more fine-grained control. This is why the project now uses TypeORM. - -Here's what the tech stack now looks like. - -## Tech Stack - -**Core** -- [NestJS](https://nestjs.com/) -- [TypeORM](https://typeorm.io/) -- [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server) - -**Database** -- [Postgres](https://www.postgresql.org/) - -**Third-party integrations** -- [Sentry](https://sentry.io/welcome/) for tracking bugs - -**Testing** -- [Jest](https://jestjs.io/) - -**Tooling** -- [Yarn](https://yarnpkg.com/) -- [ESLint](https://eslint.org/) - -**Development** -- [AWS EKS](https://aws.amazon.com/eks/) \ No newline at end of file diff --git a/packages/twenty-docs/docs/contributor/server/basics/workflows.mdx b/packages/twenty-docs/docs/contributor/server/basics/workflows.mdx deleted file mode 100644 index 5b3fc5a2980..00000000000 --- a/packages/twenty-docs/docs/contributor/server/basics/workflows.mdx +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Development workflow -sidebar_position: 3 -sidebar_custom_props: - icon: TbTopologyStar ---- - -## First time setup - -``` -cd server -yarn # install dependencies - -yarn prisma:migrate # run migrations -yarn prisma:generate # generate prisma and nestjs-graphql schemas -yarn prisma:seed # provision database with seeds - -# alternatively, you can run -yarn prisma:reset # all-in-one command to reset, migrate, seed and generate schemas -``` - -## Starting a new feature - -Make sure your database is running on the URL provided in your `server/.env` file. - -``` -cd server -yarn -yarn prisma:migrate && yarn prisma:generate - -yarn start:dev -``` - -## Lint - -``` -yarn lint -``` - -## Test - -``` -yarn test -``` - -## Resetting the database - -If you want to reset the database, you can run the following command: - -```bash -cd server -yarn database:reset -``` - -:::warning - -This will drop the database and re-run the migrations and seed. - -Make sure to back up any data you want to keep before running this command. - -::: \ No newline at end of file diff --git a/packages/twenty-docs/docs/contributor/server/others/best-practices.mdx b/packages/twenty-docs/docs/contributor/server/best-practices.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/server/others/best-practices.mdx rename to packages/twenty-docs/docs/contributor/server/best-practices.mdx diff --git a/packages/twenty-docs/docs/contributor/server/basics/custom-objects.mdx b/packages/twenty-docs/docs/contributor/server/custom-objects.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/server/basics/custom-objects.mdx rename to packages/twenty-docs/docs/contributor/server/custom-objects.mdx diff --git a/packages/twenty-docs/docs/contributor/server/others/feature-flags.mdx b/packages/twenty-docs/docs/contributor/server/feature-flags.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/server/others/feature-flags.mdx rename to packages/twenty-docs/docs/contributor/server/feature-flags.mdx diff --git a/packages/twenty-docs/docs/contributor/server/basics/folder-architecture.mdx b/packages/twenty-docs/docs/contributor/server/folder-architecture.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/server/basics/folder-architecture.mdx rename to packages/twenty-docs/docs/contributor/server/folder-architecture.mdx diff --git a/packages/twenty-docs/docs/contributor/server/others/_category_.json b/packages/twenty-docs/docs/contributor/server/others/_category_.json deleted file mode 100644 index da47888894f..00000000000 --- a/packages/twenty-docs/docs/contributor/server/others/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Others", - "position": 2 -} diff --git a/packages/twenty-docs/docs/contributor/server/basics/queue.mdx b/packages/twenty-docs/docs/contributor/server/queue.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/server/basics/queue.mdx rename to packages/twenty-docs/docs/contributor/server/queue.mdx diff --git a/packages/twenty-docs/docs/contributor/server/server.mdx b/packages/twenty-docs/docs/contributor/server/server.mdx index 8109acefa64..19b0a540176 100644 --- a/packages/twenty-docs/docs/contributor/server/server.mdx +++ b/packages/twenty-docs/docs/contributor/server/server.mdx @@ -1,12 +1,91 @@ --- title: Backend Development -displayed_sidebar: backendSidebar sidebar_position: 0 sidebar_custom_props: icon: TbTerminal - isSidebarRoot: true --- -Welcome to the Backend Development section of the documentation. -Here you will find information about the development process, the recommended tools, and the best practices you should follow. \ No newline at end of file +import DocCardList from '@theme/DocCardList'; + + + + +## Useful commands + +### First time setup + +``` +yarn prisma:migrate # run migrations +yarn prisma:generate # generate prisma and nestjs-graphql schemas +yarn prisma:seed # provision database with seeds + +# alternatively, you can run +yarn prisma:reset # all-in-one command to reset, migrate, seed and generate schemas +``` + +### Starting the app + +``` +nx prisma:migrate twenty-server +nx prisma:generate twenty-server +nx start:dev twenty-server +``` + +### Lint + +``` +nx lint twenty-server +``` + +### Test + +``` +nx test twenty-server +``` + +### Resetting the database + +If you want to reset the database, you can run the following command: + +```bash +nx database:reset twenty-server +``` + +:::warning + +This will drop the database and re-run the migrations and seed. + +Make sure to back up any data you want to keep before running this command. + +::: + +## Tech Stack + +Twenty primarily uses NestJS for the backend. + +Prisma was the first ORM we used. But in order to allow users to create custom fields and custom objects, a lower-level made more sense as we need to have fine-grained control. The project now uses TypeORM. + +Here's what the tech stack now looks like. + + +**Core** +- [NestJS](https://nestjs.com/) +- [TypeORM](https://typeorm.io/) +- [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server) + +**Database** +- [Postgres](https://www.postgresql.org/) + +**Third-party integrations** +- [Sentry](https://sentry.io/welcome/) for tracking bugs + +**Testing** +- [Jest](https://jestjs.io/) + +**Tooling** +- [Yarn](https://yarnpkg.com/) +- [ESLint](https://eslint.org/) + +**Development** +- [AWS EKS](https://aws.amazon.com/eks/) \ No newline at end of file diff --git a/packages/twenty-docs/docs/contributor/server/others/zapier.mdx b/packages/twenty-docs/docs/contributor/server/zapier.mdx similarity index 100% rename from packages/twenty-docs/docs/contributor/server/others/zapier.mdx rename to packages/twenty-docs/docs/contributor/server/zapier.mdx diff --git a/packages/twenty-docs/docs/developer/_category_.json b/packages/twenty-docs/docs/developer/_category_.json deleted file mode 100644 index 8736dcf6235..00000000000 --- a/packages/twenty-docs/docs/developer/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Developer guide", - "position": 3 -} diff --git a/packages/twenty-docs/docs/developer/graphql_api.mdx b/packages/twenty-docs/docs/developer/graphql_api.mdx deleted file mode 100644 index 7adb92f180b..00000000000 --- a/packages/twenty-docs/docs/developer/graphql_api.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: GraphQL API -sidebar_position: 2 -sidebar_custom_props: - icon: TbBrandGraphql ---- - -Use the [in-browser GraphiQL app](https://docs.twenty.com/graphql/) to browse, query, and mutate the introspection query. - -## What is GraphQL? - -GraphQL is a query language for APIs that enables declarative data fetching that allows a client to specify the exact data it needs from the API. - -Instead of exposing various endpoints that return fixed data structures, GraphQL exposes only a single endpoint that precisely returns the data that the client asked for. This makes GraphQL more flexible and efficient than other kinds of APIs, like REST APIs. - -You can learn more about GraphQL by going through this [Introduction](https://www.howtographql.com/basics/0-introduction/). - -## About GraphQL Introspection - -GraphQL query language is strongly typed, which makes it possible for you to query and understand the underlying schema. - -With the Introspection feature, you can query the schema and discover the queries (to request data), mutations (to update data), types, and fields available in a particular GraphQL API. - -## Try the GraphQL Playground -You can use the browser-based, interactive [GraphQL playground](https://docs.twenty.com/graphql/) to run mutations and queries to discover valid fields and where you can use them. diff --git a/packages/twenty-docs/docs/developer/rest_api.mdx b/packages/twenty-docs/docs/developer/rest_api.mdx deleted file mode 100644 index 90674e790bc..00000000000 --- a/packages/twenty-docs/docs/developer/rest_api.mdx +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: REST API -sidebar_position: 3 -sidebar_custom_props: - icon: TbApi ---- - -To use the REST API, you will need an API key. -Connect to your Twenty account ang do to Setting > Developers to generate one. - -## Using Postman? - -You can use [Postman](https://www.postman.com/) to interact with your Twenty objects using the API. -You will need to provide your API key as a Bearer token, -see [Bearer Token Postman Doc](https://learning.postman.com/docs/sending-requests/authorization/authorization-types/#bearer-token) -if needed. - -## Programmatic use? - -You can call the REST API in your application using this endpoint -[https://api.twenty.com/rest](https://api.twenty.com/rest). -You will need to provide your API key as a Bearer token in -your `headers.Authorization = 'Bearer '`. - -## Try the REST API Playground - -You can use the browser-based, interactive -[REST API playground documentation](https://docs.twenty.com/rest-api) -to Create, Read, Update or Delete your workspace objects. diff --git a/packages/twenty-docs/docs/index.mdx b/packages/twenty-docs/docs/index.mdx index 7dd4a6b7605..5a3ee40e896 100644 --- a/packages/twenty-docs/docs/index.mdx +++ b/packages/twenty-docs/docs/index.mdx @@ -3,36 +3,24 @@ id: homepage sidebar_position: 0 sidebar_class_name: display-none title: Welcome +hide_title: true +hide_table_of_contents: true custom_edit_url: null +pagination_next: null --- import ThemedImage from '@theme/ThemedImage'; -import Footer from '@theme/Footer' - -Twenty is an Open Source CRM that provides flexibility, tailored to your business needs. It helps you break free from vendor lock-in and limitations, and provides the tools you need to harness the full potential of your data while ensuring a sleek and effortlessly intuitive design that teams will love to use. - -## Idea Behind Twenty -We’ve spent thousands of hours grappling with traditional CRMs like Pipedrive and Salesforce to align them with our business needs, only to end up frustrated—customizations are complex and the closed ecosystems of these platforms can feel restrictive. +Twenty is a CRM designed to fit your unique business needs. +It was brought to life by a passionate community that cares about quality and precision in engineering. -The need for a CRM solution that empowers rather than constrains was clear, which inspired us to create Twenty. It's a next-generation open-source CRM that offers you the flexibility to shape it according to your business objectives and meet your team’s unique needs. Twenty is full of powerful features to give you full control and help you win more deals. - -## Getting started - -There are three ways for you to get started with Twenty: -- **Cloud:** The fastest and easiest way to try the app (it's free) -- **Local:** If you're a developer and would like to experiment or contribute to the app -- **Self-hosting:** If you want greater control over your data and want to run the app on your own server - -See the [Getting Started](./start/getting-started/) guide to learn more. - -## Contributing - -Contributions are what makes the open source community such a great place. - -Code contributions through pull request are most welcome. See the [local setup guide](../contributor/local-setup) to get started. - -You can also contribute by creating an issue to report a bug you've spotted, joining discussions or writing documentation. +There are three different ways to get started: +- **Managed Cloud:** The fastest and easiest way to try the app +- **Loca Setup:** If you're a developer and would like to contribute to the app +- **Self-hosting:** If you know how to run a server and want to host the app yourself -