diff --git a/packages/twenty-docker/twenty-website/Dockerfile b/packages/twenty-docker/twenty-website/Dockerfile
index 9d1823f335..2ff7cb808b 100644
--- a/packages/twenty-docker/twenty-website/Dockerfile
+++ b/packages/twenty-docker/twenty-website/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:24-alpine as twenty-website-build
+FROM node:24-alpine AS twenty-website-build
WORKDIR /app
@@ -24,7 +24,7 @@ COPY ./packages/twenty-ui /app/packages/twenty-ui
COPY ./packages/twenty-website /app/packages/twenty-website
RUN npx nx build twenty-website
-FROM node:24-alpine as twenty-website
+FROM node:24-alpine AS twenty-website
WORKDIR /app/packages/twenty-website
diff --git a/packages/twenty-docker/twenty/Dockerfile b/packages/twenty-docker/twenty/Dockerfile
index 0c9f01b4d4..7818be7425 100644
--- a/packages/twenty-docker/twenty/Dockerfile
+++ b/packages/twenty-docker/twenty/Dockerfile
@@ -1,5 +1,5 @@
# Base image for common dependencies
-FROM node:24-alpine as common-deps
+FROM node:24-alpine AS common-deps
WORKDIR /app
@@ -21,7 +21,7 @@ RUN yarn && yarn cache clean && npx nx reset
# Build the back
-FROM common-deps as twenty-server-build
+FROM common-deps AS twenty-server-build
# Copy sourcecode after installing dependences to accelerate subsequents builds
COPY ./packages/twenty-emails /app/packages/twenty-emails
@@ -33,7 +33,7 @@ RUN npx nx run twenty-server:build
RUN yarn workspaces focus --production twenty-emails twenty-shared twenty-server
# Build the front
-FROM common-deps as twenty-front-build
+FROM common-deps AS twenty-front-build
ARG REACT_APP_SERVER_BASE_URL
@@ -44,7 +44,7 @@ RUN npx nx build twenty-front
# Final stage: Run the application
-FROM node:24-alpine as twenty
+FROM node:24-alpine AS twenty
# Used to run healthcheck in docker
RUN apk add --no-cache curl jq
@@ -58,10 +58,10 @@ RUN chmod +x /app/entrypoint.sh
WORKDIR /app/packages/twenty-server
ARG REACT_APP_SERVER_BASE_URL
-ENV REACT_APP_SERVER_BASE_URL $REACT_APP_SERVER_BASE_URL
+ENV REACT_APP_SERVER_BASE_URL=$REACT_APP_SERVER_BASE_URL
ARG APP_VERSION
-ENV APP_VERSION $APP_VERSION
+ENV APP_VERSION=$APP_VERSION
# Copy built applications from previous stages
COPY --chown=1000 --from=twenty-server-build /app /app
diff --git a/packages/twenty-front/src/modules/object-record/record-group/components/RecordGroupReorderConfirmationModal.tsx b/packages/twenty-front/src/modules/object-record/record-group/components/RecordGroupReorderConfirmationModal.tsx
index 276afc8b52..9db9848489 100644
--- a/packages/twenty-front/src/modules/object-record/record-group/components/RecordGroupReorderConfirmationModal.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-group/components/RecordGroupReorderConfirmationModal.tsx
@@ -2,6 +2,7 @@ import { RECORD_GROUP_REORDER_CONFIRMATION_MODAL_ID } from '@/object-record/reco
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
+import { type ReactNode } from 'react';
import { createPortal } from 'react-dom';
type RecordGroupReorderConfirmationModalProps = {
@@ -10,19 +11,23 @@ type RecordGroupReorderConfirmationModalProps = {
export const RecordGroupReorderConfirmationModal = ({
onConfirmClick,
-}: RecordGroupReorderConfirmationModalProps) => {
+}: RecordGroupReorderConfirmationModalProps): ReactNode => {
const recordGroupSort = useRecoilComponentValue(
recordIndexRecordGroupSortComponentState,
);
- return createPortal(
- ,
- document.body,
+ return (
+ <>
+ {createPortal(
+ ,
+ document.body,
+ )}
+ >
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx
index fea5e034e4..2cd4889a7d 100644
--- a/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-inline-cell/components/RecordInlineCellEditMode.tsx
@@ -92,17 +92,19 @@ export const RecordInlineCellEditMode = ({
ref={refs.setReference}
data-testid="inline-cell-edit-mode-container"
>
- {createPortal(
-
- {children}
- ,
- document.body,
- )}
+ <>
+ {createPortal(
+
+ {children}
+ ,
+ document.body,
+ )}
+ >
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx
index f34e9eb802..4326c40574 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellPortalWrapper.tsx
@@ -8,7 +8,7 @@ import { RecordTableCellFieldContextWrapper } from '@/object-record/record-table
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
import { type TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
-import ReactDOM from 'react-dom';
+import { createPortal } from 'react-dom';
import { isDefined } from 'twenty-shared/utils';
export const RecordTableCellPortalWrapper = ({
@@ -43,32 +43,36 @@ export const RecordTableCellPortalWrapper = ({
return null;
}
- return ReactDOM.createPortal(
-
+ {createPortal(
+
-
-
- {children}
-
-
- ,
- anchorElement,
+ isRecordReadOnly,
+ }}
+ >
+
+
+ {children}
+
+
+ ,
+ anchorElement,
+ )}
+ >
);
};
diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/components/columns.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/components/columns.tsx
index dc40e0695b..6e9900dd57 100644
--- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/components/columns.tsx
+++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/ValidationStep/components/columns.tsx
@@ -118,15 +118,17 @@ export const generateColumns = (
{column.label}
- {column.description &&
- createPortal(
- ,
- document.body,
- )}
+ <>
+ {column.description &&
+ createPortal(
+ ,
+ document.body,
+ )}
+ >
),
editable: column.fieldType.type !== 'checkbox',
diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx
index b63d34f2b4..b2c7a0b38d 100644
--- a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx
+++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/InternalDatePicker.tsx
@@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { DateTime } from 'luxon';
-import { lazy, Suspense, useContext } from 'react';
+import { lazy, Suspense, useContext, type ComponentType } from 'react';
+import type { ReactDatePickerProps as ReactDatePickerLibProps } from 'react-datepicker';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
@@ -325,7 +326,17 @@ type DateTimePickerProps = {
onClear?: () => void;
};
-const ReactDatePicker = lazy(() => import('react-datepicker'));
+type DatePickerPropsType = ReactDatePickerLibProps<
+ boolean | undefined,
+ boolean | undefined
+>;
+
+const ReactDatePicker = lazy(
+ () =>
+ import('react-datepicker') as Promise<{
+ default: ComponentType;
+ }>,
+);
export const DateTimePicker = ({
date,
diff --git a/packages/twenty-front/src/modules/ui/input/editor/components/CustomSlashMenu.tsx b/packages/twenty-front/src/modules/ui/input/editor/components/CustomSlashMenu.tsx
index 8d9f00f203..c0b909d031 100644
--- a/packages/twenty-front/src/modules/ui/input/editor/components/CustomSlashMenu.tsx
+++ b/packages/twenty-front/src/modules/ui/input/editor/components/CustomSlashMenu.tsx
@@ -48,34 +48,36 @@ export const CustomSlashMenu = ({
return (
- {createPortal(
-
-
+ {createPortal(
+
-
-
- item.title)}
- >
- {items.map((item) => (
-
- ))}
-
-
-
-
- ,
- document.body,
- )}
+
+
+
+ item.title)}
+ >
+ {items.map((item) => (
+
+ ))}
+
+
+
+
+ ,
+ document.body,
+ )}
+ >
);
};
diff --git a/packages/twenty-website/src/app/(public)/releases/utils/get-github-release-date-from-release-note.ts b/packages/twenty-website/src/app/(public)/releases/utils/get-github-release-date-from-release-note.ts
index d86fe87533..6d885d97a1 100644
--- a/packages/twenty-website/src/app/(public)/releases/utils/get-github-release-date-from-release-note.ts
+++ b/packages/twenty-website/src/app/(public)/releases/utils/get-github-release-date-from-release-note.ts
@@ -1,43 +1,22 @@
import { type GithubReleases } from '@/database/model';
-function formatDate(dateString: string) {
- const date = new Date(dateString);
-
- const formatter = new Intl.DateTimeFormat('en-US', {
- month: 'short',
- day: 'numeric',
- });
-
- return formatter.format(date) + getOrdinal(date.getDate());
-}
-
-function getOrdinal(day: number) {
- if (day > 3 && day < 21) return 'th';
- switch (day % 10) {
- case 1:
- return 'st';
- case 2:
- return 'nd';
- case 3:
- return 'rd';
- default:
- return 'th';
- }
-}
-
+// Return an ISO date string so downstream components can format consistently
export const getGithubReleaseDateFromReleaseNote = (
githubReleases: GithubReleases[],
noteTagName: string,
noteDate: string,
) => {
const formattedNoteTagName = `v${noteTagName}`;
- const date = githubReleases?.find?.(
+ const publishedAt = githubReleases?.find?.(
(githubRelease) => githubRelease?.tagName === formattedNoteTagName,
)?.publishedAt;
- if (date) {
- return formatDate(date);
+ // If we have a GitHub publishedAt date, return it as-is (ISO date string)
+ if (publishedAt) {
+ return publishedAt;
}
+ // Fall back to the MDX frontmatter date
return noteDate;
};
+
diff --git a/packages/twenty-website/src/shared-utils/formatDisplayDate.ts b/packages/twenty-website/src/shared-utils/formatDisplayDate.ts
index 5854b56fa6..9134f27c8f 100644
--- a/packages/twenty-website/src/shared-utils/formatDisplayDate.ts
+++ b/packages/twenty-website/src/shared-utils/formatDisplayDate.ts
@@ -2,11 +2,15 @@ export const formatGithubPublishedAtDisplayDate = (
dateString: string,
): string => {
const date = new Date(dateString);
+ if (Number.isNaN(date.getTime())) return '';
+
+ const now = new Date();
+ const isCurrentYear = date.getFullYear() === now.getFullYear();
const formatter = new Intl.DateTimeFormat('en-US', {
- month: 'short',
+ month: isCurrentYear ? 'long' : 'short',
day: 'numeric',
- year: 'numeric',
+ ...(isCurrentYear ? {} : { year: 'numeric' }),
});
return formatter.format(date);