diff --git a/packages/twenty-front/src/App.tsx b/packages/twenty-front/src/App.tsx
index 98d096cee..fd21a9c07 100644
--- a/packages/twenty-front/src/App.tsx
+++ b/packages/twenty-front/src/App.tsx
@@ -45,6 +45,7 @@ import { SettingsIntegrationEditDatabaseConnection } from '~/pages/settings/inte
import { SettingsIntegrationNewDatabaseConnection } from '~/pages/settings/integrations/SettingsIntegrationNewDatabaseConnection';
import { SettingsIntegrations } from '~/pages/settings/integrations/SettingsIntegrations';
import { SettingsIntegrationShowDatabaseConnection } from '~/pages/settings/integrations/SettingsIntegrationShowDatabaseConnection';
+import { Releases } from '~/pages/settings/Releases';
import { SettingsAppearance } from '~/pages/settings/SettingsAppearance';
import { SettingsBilling } from '~/pages/settings/SettingsBilling';
import { SettingsProfile } from '~/pages/settings/SettingsProfile';
@@ -207,6 +208,7 @@ export const App = () => {
path={SettingsPath.ObjectFieldEdit}
element={}
/>
+ } />
}
/>
diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx
index 9986414ae..1a91d922a 100644
--- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx
+++ b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx
@@ -9,6 +9,7 @@ import {
IconDoorEnter,
IconHierarchy2,
IconMail,
+ IconRocket,
IconSettings,
IconUserCircle,
IconUsers,
@@ -105,6 +106,11 @@ export const SettingsNavigationDrawerItems = () => {
+
`
display: flex;
@@ -8,8 +10,15 @@ const StyledSettingsPageContainer = styled.div<{ width?: number }>`
gap: ${({ theme }) => theme.spacing(8)};
overflow: auto;
padding: ${({ theme }) => theme.spacing(8)};
- width: ${({ width }) =>
- width ? width + 'px' : OBJECT_SETTINGS_WIDTH + 'px'};
+ width: ${({ width }) => {
+ if (isDefined(width)) {
+ return width + 'px';
+ }
+ if (useIsMobile()) {
+ return 'unset';
+ }
+ return OBJECT_SETTINGS_WIDTH + 'px';
+ }};
`;
export { StyledSettingsPageContainer as SettingsPageContainer };
diff --git a/packages/twenty-front/src/modules/types/SettingsPath.ts b/packages/twenty-front/src/modules/types/SettingsPath.ts
index 36ca5d42a..b4415d0f6 100644
--- a/packages/twenty-front/src/modules/types/SettingsPath.ts
+++ b/packages/twenty-front/src/modules/types/SettingsPath.ts
@@ -27,4 +27,5 @@ export enum SettingsPath {
IntegrationNewDatabaseConnection = 'integrations/:databaseKey/new',
DevelopersNewWebhook = 'webhooks/new',
DevelopersNewWebhookDetail = 'webhooks/:webhookId',
+ Releases = 'releases',
}
diff --git a/packages/twenty-front/src/pages/settings/Releases.tsx b/packages/twenty-front/src/pages/settings/Releases.tsx
new file mode 100644
index 000000000..1fbe5b50c
--- /dev/null
+++ b/packages/twenty-front/src/pages/settings/Releases.tsx
@@ -0,0 +1,119 @@
+import React, { useEffect, useState } from 'react';
+import styled from '@emotion/styled';
+import rehypeStringify from 'rehype-stringify';
+import remarkParse from 'remark-parse';
+import remarkRehype from 'remark-rehype';
+import { IconSettings } from 'twenty-ui';
+import { unified } from 'unified';
+import { visit } from 'unist-util-visit';
+
+import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
+import { H1Title } from '@/ui/display/typography/components/H1Title';
+import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
+import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
+
+const StyledH1Title = styled(H1Title)`
+ margin-bottom: 0;
+`;
+
+type ReleaseNote = {
+ slug: string;
+ date: string;
+ release: string;
+ content: string;
+ html: string;
+};
+
+const StyledReleaseContainer = styled.div`
+ img {
+ margin: ${({ theme }) => theme.spacing(6)} 0px 0px;
+ max-width: 100%;
+ }
+
+ p img {
+ margin: 0px;
+ }
+
+ h3 {
+ margin: ${({ theme }) => theme.spacing(6)} 0px 0px;
+ }
+ code {
+ background: ${({ theme }) => theme.background.tertiary};
+ padding: 4px;
+ border-radius: 4px;
+ }
+ p {
+ color: #474747;
+ font-family: Inter, sans-serif;
+ font-size: ${({ theme }) => theme.font.size.md};
+ line-height: 19.5px;
+ font-weight: ${({ theme }) => theme.font.weight.regular};
+ margin: ${({ theme }) => theme.spacing(6)} 0px 0px;
+ text-align: justify;
+ }
+`;
+
+const StyledReleaseHeader = styled.h2`
+ font-weight: ${({ theme }) => theme.font.weight.medium};
+ line-height: 18px;
+ font-size: ${({ theme }) => theme.font.size.md};
+ margin: 0;
+ margin-top: ${({ theme }) => theme.spacing(10)};
+
+ &:first-of-type {
+ margin-top: 0;
+ }
+`;
+
+const StyledReleaseDate = styled.span`
+ font-weight: ${({ theme }) => theme.font.weight.regular};
+ font-size: 12px;
+ line-height: 18px;
+ color: ${({ theme }) => theme.font.color.tertiary};
+`;
+
+export const Releases = () => {
+ const [releases, setReleases] = useState([]);
+
+ useEffect(() => {
+ fetch('https://twenty.com/api/releases').then(async (res) => {
+ const json = await res.json();
+ for (const release of json) {
+ release.html = String(
+ await unified()
+ .use(remarkParse)
+ .use(remarkRehype)
+ .use(rehypeStringify)
+ .use(() => (tree: any) => {
+ visit(tree, (node) => {
+ if (node.tagName === 'h1' || node.tagName === 'h2') {
+ node.tagName = 'h3';
+ }
+ });
+ })
+ .process(release.content),
+ );
+ }
+ setReleases(json);
+ });
+ }, []);
+
+ return (
+
+
+
+
+
+ {releases.map((release) => (
+
+ {release.release}
+ {release.date}
+
+
+ ))}
+
+
+
+
+ );
+};
diff --git a/packages/twenty-ui/src/display/icon/components/TablerIcons.ts b/packages/twenty-ui/src/display/icon/components/TablerIcons.ts
index cac8c23a5..3f16a342c 100644
--- a/packages/twenty-ui/src/display/icon/components/TablerIcons.ts
+++ b/packages/twenty-ui/src/display/icon/components/TablerIcons.ts
@@ -123,6 +123,7 @@ export {
IconRelationOneToMany,
IconRelationOneToOne,
IconRepeat,
+ IconRocket,
IconSearch,
IconSend,
IconSettings,
diff --git a/packages/twenty-website/src/middleware.ts b/packages/twenty-website/src/middleware.ts
index 9fa6c5205..749753244 100644
--- a/packages/twenty-website/src/middleware.ts
+++ b/packages/twenty-website/src/middleware.ts
@@ -1,20 +1,9 @@
import { NextResponse } from 'next/server';
-const allowedOrigins = [
- 'http://localhost:3000',
- 'https://app.twenty.com',
- 'https://twenty.com',
-];
-
-export function middleware(req: any) {
+export function middleware() {
const res = NextResponse.next();
- const origin = req.headers.get('origin');
-
- if (allowedOrigins.includes(origin)) {
- res.headers.append('Access-Control-Allow-Origin', origin);
- }
-
+ res.headers.append('Access-Control-Allow-Origin', '*');
res.headers.append('Access-Control-Allow-Credentials', 'true');
res.headers.append(
'Access-Control-Allow-Methods',