feat: Static URL Support for Applications and Pages#41312
feat: Static URL Support for Applications and Pages#41312ashit-rath merged 27 commits intoreleasefrom
Conversation
WalkthroughAdded static URL (slug) support across routing, URL assembly, APIs, Redux (actions/reducers/sagas/selectors), and UI; propagated Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as "App Settings UI"
participant Redux
participant Saga
participant API
participant State
User->>UI: Type app slug
UI->>Redux: dispatch VALIDATE_APP_SLUG
Redux->>Saga: validateAppSlugSaga (debounced)
Saga->>API: validateAppSlug(slug)
API-->>Saga: { isUniqueSlugAvailable }
Saga->>Redux: VALIDATE_APP_SLUG_SUCCESS / VALIDATE_APP_SLUG_ERROR
Redux->>State: update validity flags
State-->>UI: show availability
User->>UI: Confirm change
UI->>Redux: dispatch ENABLE_STATIC_URL / PERSIST_APP_SLUG
Redux->>Saga: enableStaticUrlSaga / persistAppSlugSaga
Saga->>API: enable/persist endpoints
API-->>Saga: success
Saga->>Redux: ENABLE_STATIC_URL_SUCCESS / PERSIST_APP_SLUG_SUCCESS
Redux->>State: update app/page slug and routing type
sequenceDiagram
participant Browser
participant Router
participant Redux
participant Engine
Browser->>Router: GET /app/:staticApplicationSlug/:pageSlug
Router->>Redux: extract staticApplicationSlug, staticPageSlug
Router->>Engine: dispatch initAppViewerAction(staticApplicationSlug, staticPageSlug)
Engine->>Redux: selector getBasePageIdFromStaticSlug(staticPageSlug)
Redux-->>Engine: basePageId (matched by page.uniqueSlug)
Engine->>Engine: loadAppData(basePageId)
Engine-->>Browser: render resolved page
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Key areas needing extra attention:
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🔴🔴🔴 Cyclic Dependency Check: This PR has increased the number of cyclic dependencies by 2, when compared with the release branch. Refer this document to identify the cyclic dependencies introduced by this PR. You can view the dependency diff in the run log. Look for the check-cyclic-dependencies job in the run. |
|
🔴🔴🔴 Cyclic Dependency Check: This PR has increased the number of cyclic dependencies by 2, when compared with the release branch. Refer this document to identify the cyclic dependencies introduced by this PR. You can view the dependency diff in the run log. Look for the check-cyclic-dependencies job in the run. |
Revised the invalid app slug message that clarifies that the slug can only contain lowercase letters, numbers, and hyphens. Keep consistency on the term Slug instead of App URL.
|
Deploy-Preview-URL: https://ce-41312.dp.appsmith.com |
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (5)
app/client/src/ce/constants/messages.ts (1)
1919-1933: Align wording with “slug” and improve placeholder/empty text.Use a slug-focused placeholder and explicit empty error:
-export const GENERAL_SETTINGS_APP_URL_PLACEHOLDER = () => "app-url"; +export const GENERAL_SETTINGS_APP_URL_PLACEHOLDER = () => "app-slug"; @@ -export const GENERAL_SETTINGS_APP_URL_EMPTY_VALUE_MESSAGE = () => - "Enter a value"; +export const GENERAL_SETTINGS_APP_URL_EMPTY_VALUE_MESSAGE = () => + "App slug cannot be empty";app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx (1)
779-788: Default to false on VALIDATE_APP_SLUG_ERROR.Defensive default avoids inconsistent state if payload is malformed:
- isApplicationSlugValid: action.payload.isValid, + isApplicationSlugValid: false,app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx (2)
387-402: Normalize slugs to lowercase at the shared helper to avoid case-only collisions.Current flow allows uppercase; spec is lowercase/0-9/hyphen. Fix once in filterAccentedAndSpecialCharacters and drop local workarounds. Also ensures reserved-pattern checks (ObjectId/UUID) aren’t bypassed by uppercase.
Apply in utils (single source of truth), then keep this file unchanged:
diff --git a/app/client/src/pages/AppIDE/components/AppSettings/utils.ts b/app/client/src/pages/AppIDE/components/AppSettings/utils.ts @@ export const filterAccentedAndSpecialCharacters = (value: string) => { return decodeURI(value) .replaceAll(" ", "-") - .replaceAll(/[^A-Za-z0-9-]/g, ""); + .replaceAll(/[^A-Za-z0-9-]/g, "") + .toLowerCase(); };This will also make checkPageNameSlugConflict comparisons robust.
Also applies to: 330-359, 58-62
540-542: Fix CSS class typo (extra parenthesis).- <strong className="text-[color:var(--appsmith-color-black-800))]"> + <strong className="text-[color:var(--appsmith-color-black-800)]">app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (1)
292-295: Fix CSS class typo (extra parenthesis).- <strong className="text-[color:var(--appsmith-color-black-800))]"> + <strong className="text-[color:var(--appsmith-color-black-800)]">
🧹 Nitpick comments (12)
app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx (6)
295-314: Guard save while validation is in-flight to avoid persisting a stale slug.If the user hits Enter before availability result returns, you may persist an unverified slug. Add a simple guard:
const saveStaticPageSlug = useCallback(() => { - if (!canManagePages || page.uniqueSlug === staticPageSlug) return; + if (!canManagePages || page.uniqueSlug === staticPageSlug) return; + // Wait for validation to complete + if (isValidatingPageSlug) return; // Don't save if there's a validation error if (staticPageSlugError) return; // Don't save if the page slug is not valid if (!isPageSlugValid) return; dispatch(persistPageSlug(page.pageId, staticPageSlug || "")); -}, [ +}, [ page.pageId, page.uniqueSlug, staticPageSlug, canManagePages, dispatch, staticPageSlugError, - isPageSlugValid, + isPageSlugValid, + isValidatingPageSlug, ]);Optionally track “lastValidatedSlug” in state to ensure it matches the current input before saving.
387-399: Debounce availability checks to reduce chatty API calls.Wrap validatePageSlug in a debounced callback (e.g., 300–500 ms) to avoid 1 req/keystroke:
+import { debounce } from "lodash"; @@ - const onStaticPageSlugChange = (value: string) => { + const debouncedValidate = useMemo( + () => debounce((slug: string) => dispatch(validatePageSlug(page.pageId, slug)), 400), + [dispatch, page.pageId], + ); + const onStaticPageSlugChange = (value: string) => { const normalizedValue = value.length > 0 ? filterAccentedAndSpecialCharacters(value) : value; @@ - if (!errorMessage && normalizedValue && normalizedValue.trim().length > 0) { - dispatch(validatePageSlug(page.pageId, normalizedValue)); - } + if (!errorMessage && normalizedValue && normalizedValue.trim().length > 0) { + debouncedValidate(normalizedValue); + }Remember to cancel on unmount if needed.
522-533: Use origin for copy to include port and avoid mismatch.String-build misses port; origin is simpler:
- onCopy={async () => { - navigator.clipboard.writeText( - location.protocol + - "//" + - window.location.hostname + - pathPreview.relativePath, - ); - }} + onCopy={async () => { + navigator.clipboard.writeText( + window.location.origin + pathPreview.relativePath, + ); + }}
165-171: Don’t render Icon when no icon is intended.You set icon: "" for the deploy message but always render . Make icon optional and guard the render:
- return { icon: "" as const, color: "var(--ads-v2-color-fg)", message: ... }; + return { color: "var(--ads-v2-color-fg)", message: ... };- <Icon - color={pageSlugValidationMessage.color} - name={pageSlugValidationMessage.icon} - size="sm" - /> + {pageSlugValidationMessage.icon && ( + <Icon + color={pageSlugValidationMessage.color} + name={pageSlugValidationMessage.icon} + size="sm" + /> + )}Also applies to: 505-517
491-491: Localize label instead of hardcoding “Page slug”.Add PAGE_SETTINGS_PAGE_SLUG_LABEL to messages.ts and use createMessage here for consistency/i18n.
113-134: Prefer useMemo over useCallback+invoke for computing pathPreview.You’re creating a function only to call it immediately. Simplify:
- const pathPreview = useCallback(getUrlPreview, [ /* deps */ ])( - page.pageId, pageName, page.pageName, currentApplication?.uniqueSlug || "", - customSlug, page.customSlug, isStaticUrlEnabled, staticPageSlug, page.uniqueSlug || page.slug, - ); + const pathPreview = useMemo( + () => + getUrlPreview( + page.pageId, + pageName, + page.pageName, + currentApplication?.uniqueSlug || "", + customSlug, + page.customSlug, + isStaticUrlEnabled, + staticPageSlug, + page.uniqueSlug || page.slug, + ), + [ + page.pageId, + pageName, + page.pageName, + currentApplication?.uniqueSlug, + customSlug, + page.customSlug, + isStaticUrlEnabled, + staticPageSlug, + page.uniqueSlug, + page.slug, + ], + );app/client/src/ce/sagas/ApplicationSagas.tsx (2)
1347-1391: Include the error object in DISABLE_STATIC_URL_ERROR for better diagnostics.Currently only message/show are dispatched. Add the error for central handlers/toasts:
- yield put({ - type: ReduxActionErrorTypes.DISABLE_STATIC_URL_ERROR, - payload: { - show: true, - message: createMessage(ERROR_IN_DISABLING_STATIC_URL), - }, - }); + yield put({ + type: ReduxActionErrorTypes.DISABLE_STATIC_URL_ERROR, + payload: { + error, + show: true, + message: createMessage(ERROR_IN_DISABLING_STATIC_URL), + }, + });
204-207: Nit: fix variable name typo.Rename appicationViewPageUrl → applicationViewPageUrl.
Also applies to: 210-215
app/client/src/ce/constants/messages.ts (1)
1962-1967: Add label for page slug to avoid hardcoded string in UI.Add and use in PageSettings:
+export const PAGE_SETTINGS_PAGE_SLUG_LABEL = () => "Page slug";app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (2)
218-240: Reuse the shared normalizer for consistency with page slugs.Use filterAccentedAndSpecialCharacters (with the proposed toLowerCase) to keep behavior identical across app/page slug inputs:
-import { APPLICATION_SLUG_REGEX } from ... // keep regex +import { filterAccentedAndSpecialCharacters } from "../utils"; @@ - const onSlugChange = useCallback( - (value: string) => { - // Convert to lowercase and replace spaces with hyphens - const normalizedValue = value.toLowerCase().replace(/\s+/g, "-"); + const onSlugChange = useCallback( + (value: string) => { + const normalizedValue = + value.length > 0 ? filterAccentedAndSpecialCharacters(value) : value;Keeps a single acceptance surface for characters.
104-106: Initialize toggle from staticUrlEnabled, not just presence of uniqueSlug.uniqueSlug may exist historically; the feature flag is controlled by staticUrlEnabled.
-const [isStaticUrlToggleEnabled, setIsStaticUrlToggleEnabled] = - useState(!!applicationSlug); +const [isStaticUrlToggleEnabled, setIsStaticUrlToggleEnabled] = + useState(!!application?.staticUrlEnabled);app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx (1)
831-838: Wire up isErrorPersistingAppSlug to reflect failures (or remove the field).You introduced isErrorPersistingAppSlug but never update it. Either use it:
[ReduxActionTypes.ENABLE_STATIC_URL_SUCCESS]: (state) => ({ ...state, isPersistingAppSlug: false, + isErrorPersistingAppSlug: false, }), [ReduxActionErrorTypes.ENABLE_STATIC_URL_ERROR]: (state) => ({ ...state, isPersistingAppSlug: false, + isErrorPersistingAppSlug: true, }), @@ [ReduxActionTypes.DISABLE_STATIC_URL_SUCCESS]: (state) => ({ ...state, isPersistingAppSlug: false, + isErrorPersistingAppSlug: false, }), [ReduxActionErrorTypes.DISABLE_STATIC_URL_ERROR]: (state) => ({ ...state, isPersistingAppSlug: false, + isErrorPersistingAppSlug: true, }), @@ [ReduxActionTypes.PERSIST_APP_SLUG_SUCCESS]: (state) => ({ ...state, isPersistingAppSlug: false, + isErrorPersistingAppSlug: false, }), [ReduxActionTypes.PERSIST_APP_SLUG_ERROR]: (state) => ({ ...state, isPersistingAppSlug: false, + isErrorPersistingAppSlug: true, }),…or drop the field to avoid dead state.
Also applies to: 853-860, 875-882, 48-53, 915-919
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
app/client/src/ce/constants/messages.ts(1 hunks)app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx(3 hunks)app/client/src/ce/sagas/ApplicationSagas.tsx(4 hunks)app/client/src/ce/selectors/applicationSelectors.tsx(2 hunks)app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx(7 hunks)app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx(13 hunks)app/client/src/pages/AppViewer/Navigation/components/MenuItem/index.tsx(3 hunks)app/client/src/pages/AppViewer/Navigation/components/TopHeader.tsx(1 hunks)app/client/src/pages/AppViewer/Navigation/hooks/useNavigateToAnotherPage.tsx(1 hunks)app/client/src/pages/AppViewer/Navigation/index.tsx(1 hunks)app/client/src/pages/AppViewer/PageMenu.tsx(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- app/client/src/pages/AppViewer/PageMenu.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
- app/client/src/pages/AppViewer/Navigation/hooks/useNavigateToAnotherPage.tsx
- app/client/src/pages/AppViewer/Navigation/components/MenuItem/index.tsx
- app/client/src/ce/selectors/applicationSelectors.tsx
- app/client/src/pages/AppViewer/Navigation/index.tsx
- app/client/src/pages/AppViewer/Navigation/components/TopHeader.tsx
🧰 Additional context used
🧬 Code graph analysis (4)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (5)
app/client/src/ce/selectors/applicationSelectors.tsx (5)
getIsApplicationSlugValid(64-65)getIsValidatingAppSlug(62-63)getIsFetchingAppSlugSuggestion(212-213)getAppSlugSuggestion(215-216)getIsPersistingAppSlug(60-61)app/client/src/ce/entities/FeatureFlag.ts (1)
FEATURE_FLAG(2-68)app/client/src/ce/constants/messages.ts (12)
STATIC_URL_CHANGE_SUCCESS(1938-1939)STATIC_URL_DISABLED_SUCCESS(1936-1937)GENERAL_SETTINGS_APP_URL_EMPTY_VALUE_MESSAGE(1932-1933)GENERAL_SETTINGS_APP_URL_INVALID_MESSAGE(1923-1924)GENERAL_SETTINGS_NAME_EMPTY_MESSAGE(1914-1915)GENERAL_SETTINGS_APP_ICON_LABEL(1918-1918)GENERAL_SETTINGS_APP_URL_LABEL(1919-1919)GENERAL_SETTINGS_APP_URL_PLACEHOLDER_FETCHING(1921-1922)GENERAL_SETTINGS_APP_URL_PLACEHOLDER(1920-1920)GENERAL_SETTINGS_APP_URL_CHECKING_MESSAGE(1927-1928)GENERAL_SETTINGS_APP_URL_AVAILABLE_MESSAGE(1929-1929)GENERAL_SETTINGS_APP_URL_UNAVAILABLE_MESSAGE(1930-1931)app/client/src/ce/actions/applicationActions.ts (6)
enableStaticUrl(322-330)persistAppSlug(82-90)resetAppSlugValidation(341-345)validateAppSlug(92-99)fetchAppSlugSuggestion(101-108)disableStaticUrl(332-339)app/client/src/ce/api/ApplicationApi.tsx (5)
enableStaticUrl(544-552)persistAppSlug(522-533)validateAppSlug(535-542)fetchAppSlugSuggestion(560-566)disableStaticUrl(554-558)
app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx (9)
app/client/src/entities/Page/types.ts (1)
Page(1-13)app/client/src/selectors/editorSelectors.tsx (5)
getIsStaticUrlEnabled(253-254)getIsPersistingPageSlug(288-291)getIsValidatingPageSlug(298-299)getIsPageSlugValid(301-302)getPageList(163-164)app/client/src/ce/selectors/applicationSelectors.tsx (1)
getCurrentApplication(46-50)app/client/src/ce/constants/messages.ts (17)
PAGE_SETTINGS_PAGE_SLUG_DEPLOY_MESSAGE(1950-1951)PAGE_SETTINGS_PAGE_SLUG_CHECKING_MESSAGE(1945-1946)PAGE_SETTINGS_PAGE_SLUG_AVAILABLE_MESSAGE(1947-1947)PAGE_SETTINGS_PAGE_SLUG_UNAVAILABLE_MESSAGE(1948-1949)PAGE_SETTINGS_NAME_EMPTY_MESSAGE(1963-1964)PAGE_SETTINGS_ACTION_NAME_CONFLICT_ERROR(1980-1981)PAGE_SETTINGS_PAGE_NAME_CONFLICTING_SLUG_MESSAGE(1952-1953)PAGE_SETTINGS_PAGE_NAME_LABEL(1962-1962)PAGE_SETTINGS_PAGE_URL_VERSION_UPDATE_1(1968-1968)PAGE_SETTINGS_PAGE_URL_VERSION_UPDATE_2(1969-1969)PAGE_SETTINGS_PAGE_URL_VERSION_UPDATE_3(1970-1971)PAGE_SETTINGS_PAGE_URL_LABEL(1967-1967)PAGE_SETTINGS_SHOW_PAGE_NAV(1972-1972)PAGE_SETTINGS_SHOW_PAGE_NAV_TOOLTIP(1973-1974)PAGE_SETTINGS_SET_AS_HOMEPAGE(1975-1975)PAGE_SETTINGS_SET_AS_HOMEPAGE_TOOLTIP(1976-1977)PAGE_SETTINGS_SET_AS_HOMEPAGE_TOOLTIP_NON_HOME_PAGE(1978-1979)app/client/src/utils/helpers.tsx (1)
isNameValid(521-534)app/client/src/ce/utils/BusinessFeatures/permissionPageHelpers.tsx (1)
getHasManagePagePermission(112-118)app/client/src/api/PageApi.tsx (2)
persistPageSlug(306-311)validatePageSlug(313-318)app/client/src/actions/pageActions.tsx (2)
persistPageSlug(709-717)validatePageSlug(719-727)app/client/src/pages/AppIDE/components/AppSettings/utils.ts (1)
filterAccentedAndSpecialCharacters(96-100)
app/client/src/ce/sagas/ApplicationSagas.tsx (4)
app/client/src/ce/selectors/applicationSelectors.tsx (1)
getCurrentApplication(46-50)app/client/src/ce/api/ApplicationApi.tsx (1)
ApplicationApi(291-567)app/client/src/sagas/ErrorSagas.tsx (1)
validateResponse(100-155)app/client/src/ce/constants/messages.ts (1)
ERROR_IN_DISABLING_STATIC_URL(1934-1935)
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx (2)
app/client/src/ce/constants/ReduxActionConstants.tsx (2)
ReduxActionTypes(1321-1365)ReduxActionErrorTypes(1367-1394)app/client/src/actions/ReduxActionTypes.ts (1)
ReduxAction(9-12)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: perform-test / client-build / client-build
- GitHub Check: perform-test / rts-build / build
- GitHub Check: perform-test / server-build / server-unit-tests
- GitHub Check: client-lint / client-lint
- GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
- GitHub Check: client-unit-tests / client-unit-tests
- GitHub Check: client-prettier / prettier-check
- GitHub Check: client-build / client-build
🔇 Additional comments (2)
app/client/src/ce/sagas/ApplicationSagas.tsx (2)
197-207: Publish flow waits for fresh app before building URL — good.This ensures static slugs (if enabled) are reflected before opening the viewer.
1185-1241: Persist app slug request shape LGTM.Uses only branchedApplicationId and uniqueApplicationSlug as per API; re-fetch on success is correct.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/client/src/ce/middlewares/RouteParamsMiddleware.ts (1)
120-129: Bug: application.baseid typo breaks URL params.Should be baseId. As written, baseApplicationId becomes undefined.
- appParams = { - baseApplicationId: application.baseid, + appParams = { + baseApplicationId: application.baseId, applicationSlug: application.slug, applicationVersion: application.applicationVersion, staticApplicationSlug: application?.staticUrlSettings?.uniqueSlug || "", };app/client/src/ce/entities/URLRedirect/URLAssembly.ts (1)
241-248: Reset staticApplicationSlug when resetting URL params.Avoid leaking a prior app’s static slug into subsequent routes.
resetURLParams() { this.appParams = { baseApplicationId: "", - applicationSlug: "", + applicationSlug: "", + staticApplicationSlug: "", }; this.pageParams = {}; }
♻️ Duplicate comments (3)
app/client/src/ce/middlewares/RouteParamsMiddleware.ts (1)
131-139: Wrap case body to avoid leaking const declarations across cases.Block-scope the declarations in CLONE_PAGE_SUCCESS.
- case ReduxActionTypes.CLONE_PAGE_SUCCESS: - const { basePageId, pageSlug, uniqueSlug } = action.payload; + case ReduxActionTypes.CLONE_PAGE_SUCCESS: { + const { basePageId, pageSlug, uniqueSlug } = action.payload; pageParams = [ { basePageId, pageSlug, staticPageSlug: uniqueSlug || "", }, ]; break; + }app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx (1)
539-545: Fix CSS class typo (extra closing parenthesis).The utility is invalid: extra “)”.
- <strong className="text-[color:var(--appsmith-color-black-800))]"> + <strong className="text-[color:var(--appsmith-color-black-800)]">app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (1)
292-299: Fix CSS class typo (extra closing parenthesis).Invalid color utility.
- <strong className="text-[color:var(--appsmith-color-black-800))]"> + <strong className="text-[color:var(--appsmith-color-black-800)]">
🧹 Nitpick comments (7)
app/client/src/pages/AppViewer/index.tsx (3)
168-181: Guard baseApplicationId for static routes.Static viewer paths don’t carry baseApplicationId. Pass an empty string to avoid undefined leaking into the init payload.
dispatch( initAppViewerAction({ - baseApplicationId, + baseApplicationId: baseApplicationId || "", branch, basePageId: resolvedBasePageId || "", mode: APP_MODE.PUBLISHED, staticApplicationSlug, staticPageSlug, }), );
112-121: Type the selector arg and handle explicit nulls from slug lookup.Minor: add DefaultRootState type and coalesce null to undefined for downstream checks.
- const resolvedBasePageIdFromSlug = useSelector((state) => - staticPageSlug - ? getBasePageIdFromStaticSlug(state, staticPageSlug) - : undefined, - ); + const resolvedBasePageIdFromSlug = useSelector((state: DefaultRootState) => { + if (!staticPageSlug) return undefined; + const id = getBasePageIdFromStaticSlug(state, staticPageSlug); + return id ?? undefined; + });
205-218: Trim unused dependency to avoid extra re-renders.pathname isn’t used inside the effect.
- }, [ + }, [ baseApplicationId, branch, dispatch, pages, prevValues?.resolvedBasePageId, prevValues?.branch, prevValues?.location, props.location, resolvedBasePageId, staticApplicationSlug, staticPageSlug, - pathname, ]);app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx (1)
487-503: Localize the “Page slug” label and placeholder.Ensure consistency with the rest of the file that uses createMessage().
- label="Page slug" + label={createMessage(PAGE_SETTINGS_PAGE_URL_LABEL)} ... - placeholder="Page slug" + placeholder={createMessage(PAGE_SETTINGS_PAGE_URL_LABEL)}app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (2)
221-243: Debounce app slug availability checks to reduce API churn.Dispatching validateAppSlug on every keypress can flood the API.
+ // memoized debounced validator + const debouncedValidateAppSlug = React.useMemo( + () => debounce((slug: string) => dispatch(validateAppSlug(slug)), 300), + [dispatch], + ); const onSlugChange = useCallback( (value: string) => { const normalizedValue = value.toLowerCase().replace(/\s+/g, "-"); if (normalizedValue && normalizedValue.trim().length > 0) { const isValid = APPLICATION_SLUG_REGEX.test(normalizedValue); setIsClientSideSlugValid(isValid); if (isValid) { - dispatch(validateAppSlug(normalizedValue)); + debouncedValidateAppSlug(normalizedValue); } } else { setIsClientSideSlugValid(true); } setApplicationSlug(normalizedValue); }, - [dispatch], + [debouncedValidateAppSlug], );
100-114: Use backend “enabled” flag as the toggle source of truth.Initialize and sync the switch from application.staticUrlSettings.enabled, not slug presence.
- const [isStaticUrlToggleEnabled, setIsStaticUrlToggleEnabled] = - useState(!!applicationSlug); + const [isStaticUrlToggleEnabled, setIsStaticUrlToggleEnabled] = + useState(!!application?.staticUrlSettings?.enabled); + useEffect(() => { + setIsStaticUrlToggleEnabled(!!application?.staticUrlSettings?.enabled); + }, [application?.staticUrlSettings?.enabled]);Also applies to: 115-121
app/client/src/selectors/editorSelectors.tsx (1)
179-198: Solid implementation of parameterized selector.The logic correctly handles edge cases and uses the standard pattern for parameterized selectors with
createSelector.Consider replacing
anywithDefaultRootStatefor the unused state parameter to maintain type safety:export const getBasePageIdFromStaticSlug = createSelector( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [getPageList, (_: any, staticPageSlug: string) => staticPageSlug], + [getPageList, (_: DefaultRootState, staticPageSlug: string) => staticPageSlug], (pages: Page[], staticPageSlug: string) => {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
app/client/src/ce/entities/URLRedirect/URLAssembly.ts(7 hunks)app/client/src/ce/middlewares/RouteParamsMiddleware.ts(8 hunks)app/client/src/entities/Application/types.ts(1 hunks)app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx(7 hunks)app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx(13 hunks)app/client/src/pages/AppViewer/AppViewerPageContainer.tsx(4 hunks)app/client/src/pages/AppViewer/index.tsx(5 hunks)app/client/src/selectors/editorSelectors.tsx(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- app/client/src/pages/AppViewer/AppViewerPageContainer.tsx
- app/client/src/entities/Application/types.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/sagas/InitSagas.ts:260-271
Timestamp: 2025-10-28T03:30:58.271Z
Learning: In app/client/src/sagas/InitSagas.ts, when constructing consolidatedApiParams for static page URLs, the code intentionally reuses applicationId and defaultPageId fields to pass staticApplicationSlug and staticPageSlug values respectively. This is by design, even though ConsolidatedApiParams type has dedicated staticApplicationSlug and staticPageSlug fields.
📚 Learning: 2025-10-28T03:30:58.271Z
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/sagas/InitSagas.ts:260-271
Timestamp: 2025-10-28T03:30:58.271Z
Learning: In app/client/src/sagas/InitSagas.ts, when constructing consolidatedApiParams for static page URLs, the code intentionally reuses applicationId and defaultPageId fields to pass staticApplicationSlug and staticPageSlug values respectively. This is by design, even though ConsolidatedApiParams type has dedicated staticApplicationSlug and staticPageSlug fields.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsxapp/client/src/pages/AppViewer/index.tsxapp/client/src/ce/entities/URLRedirect/URLAssembly.tsapp/client/src/ce/middlewares/RouteParamsMiddleware.ts
🧬 Code graph analysis (4)
app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx (10)
app/client/src/entities/Page/types.ts (1)
Page(1-13)app/client/src/selectors/editorSelectors.tsx (7)
getCurrentApplicationId(240-241)selectApplicationVersion(249-251)getIsStaticUrlEnabled(253-254)getIsPersistingPageSlug(288-291)getIsValidatingPageSlug(298-299)getIsPageSlugValid(301-302)getPageList(163-164)app/client/src/ce/selectors/applicationSelectors.tsx (1)
getCurrentApplication(46-50)app/client/src/ce/entities/FeatureFlag.ts (1)
FEATURE_FLAG(2-68)app/client/src/ce/constants/messages.ts (17)
PAGE_SETTINGS_PAGE_SLUG_DEPLOY_MESSAGE(1950-1951)PAGE_SETTINGS_PAGE_SLUG_CHECKING_MESSAGE(1945-1946)PAGE_SETTINGS_PAGE_SLUG_AVAILABLE_MESSAGE(1947-1947)PAGE_SETTINGS_PAGE_SLUG_UNAVAILABLE_MESSAGE(1948-1949)PAGE_SETTINGS_NAME_EMPTY_MESSAGE(1963-1964)PAGE_SETTINGS_ACTION_NAME_CONFLICT_ERROR(1980-1981)PAGE_SETTINGS_PAGE_NAME_CONFLICTING_SLUG_MESSAGE(1952-1953)PAGE_SETTINGS_PAGE_NAME_LABEL(1962-1962)PAGE_SETTINGS_PAGE_URL_VERSION_UPDATE_1(1968-1968)PAGE_SETTINGS_PAGE_URL_VERSION_UPDATE_2(1969-1969)PAGE_SETTINGS_PAGE_URL_VERSION_UPDATE_3(1970-1971)PAGE_SETTINGS_PAGE_URL_LABEL(1967-1967)PAGE_SETTINGS_SHOW_PAGE_NAV(1972-1972)PAGE_SETTINGS_SHOW_PAGE_NAV_TOOLTIP(1973-1974)PAGE_SETTINGS_SET_AS_HOMEPAGE(1975-1975)PAGE_SETTINGS_SET_AS_HOMEPAGE_TOOLTIP(1976-1977)PAGE_SETTINGS_SET_AS_HOMEPAGE_TOOLTIP_NON_HOME_PAGE(1978-1979)app/client/src/utils/helpers.tsx (1)
isNameValid(521-534)app/client/src/ce/utils/BusinessFeatures/permissionPageHelpers.tsx (1)
getHasManagePagePermission(112-118)app/client/src/api/PageApi.tsx (2)
persistPageSlug(306-311)validatePageSlug(313-318)app/client/src/actions/pageActions.tsx (2)
persistPageSlug(709-717)validatePageSlug(719-727)app/client/src/pages/AppIDE/components/AppSettings/utils.ts (1)
filterAccentedAndSpecialCharacters(96-100)
app/client/src/pages/AppViewer/index.tsx (4)
app/client/src/selectors/editorSelectors.tsx (2)
getPageList(163-164)getBasePageIdFromStaticSlug(179-198)app/client/src/pages/utils.ts (1)
getIsBranchUpdated(5-16)app/client/src/actions/initActions.ts (1)
initAppViewerAction(38-57)app/client/src/actions/pageActions.tsx (1)
fetchPublishedPageResources(302-313)
app/client/src/ce/entities/URLRedirect/URLAssembly.ts (1)
app/client/src/ce/constants/routes/appRoutes.ts (4)
BUILDER_PATH_STATIC(27-27)VIEWER_PATH_STATIC(28-28)PLACEHOLDER_PAGE_SLUG(201-201)PLACEHOLDER_APP_SLUG(199-199)
app/client/src/selectors/editorSelectors.tsx (2)
app/client/src/ce/selectors/entitiesSelector.ts (1)
getPageList(1053-1056)app/client/src/entities/Page/types.ts (1)
Page(1-13)
🪛 Biome (2.1.2)
app/client/src/ce/middlewares/RouteParamsMiddleware.ts
[error] 131-131: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: perform-test / server-build / server-unit-tests
- GitHub Check: perform-test / client-build / client-build
- GitHub Check: client-lint / client-lint
- GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
- GitHub Check: client-unit-tests / client-unit-tests
- GitHub Check: client-build / client-build
- GitHub Check: client-prettier / prettier-check
🔇 Additional comments (2)
app/client/src/selectors/editorSelectors.tsx (2)
253-254: LGTM!Clean selector with proper optional chaining and boolean coercion.
288-302: LGTM!These plain selector functions are correctly implemented for simple property access. Using plain functions instead of
createSelectoris appropriate here and more performant for direct state access. The default values and optional chaining ensure safe fallbacks.
app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (1)
305-312: Fix class name typo in AppUrlContent.Extra closing parenthesis breaks the CSS variable reference.
Apply this diff to fix:
- <strong className="text-[color:var(--appsmith-color-black-800))]"> + <strong className="text-[color:var(--appsmith-color-black-800)]">
🧹 Nitpick comments (5)
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx (1)
823-831: Consider clearing appSlugSuggestion consistently across all success handlers.ENABLE_STATIC_URL_SUCCESS clears
appSlugSuggestion(line 829), but DISABLE_STATIC_URL_SUCCESS and PERSIST_APP_SLUG_SUCCESS don't. This leaves potentially stale suggestion data in state.If suggestions are only relevant during enablement, the current approach is fine. Otherwise, consider clearing suggestions in all success handlers for consistency.
[ReduxActionTypes.DISABLE_STATIC_URL_SUCCESS]: ( state: ApplicationsReduxState, ) => { return { ...state, isPersistingAppSlug: false, + appSlugSuggestion: "", }; },[ReduxActionTypes.PERSIST_APP_SLUG_SUCCESS]: ( state: ApplicationsReduxState, ) => { return { ...state, isPersistingAppSlug: false, + appSlugSuggestion: "", }; },Also applies to: 846-853, 868-875
app/client/src/entities/URLRedirect/SlugURLRedirect.ts (1)
29-35: Conditional static slug computation is correct.The mode-based check ensures static slugs are only used in viewer mode (
APP_MODE.PUBLISHED), which aligns with the PR objectives. The optional chaining and empty string fallbacks provide graceful degradation when static URLs aren't configured.Consider extracting the mode check to reduce repetition:
- // Only use static slugs for viewer mode, not for edit mode - const staticApplicationSlug = - this._mode === APP_MODE.PUBLISHED - ? currentApplication?.staticUrlSettings?.uniqueSlug || "" - : ""; - const staticPageSlug = - this._mode === APP_MODE.PUBLISHED ? currentPage?.uniqueSlug || "" : ""; + // Only use static slugs for viewer mode, not for edit mode + const isPublishedMode = this._mode === APP_MODE.PUBLISHED; + const staticApplicationSlug = isPublishedMode + ? currentApplication?.staticUrlSettings?.uniqueSlug || "" + : ""; + const staticPageSlug = isPublishedMode + ? currentPage?.uniqueSlug || "" + : "";app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (3)
119-124: Optimize effect dependencies.The dependency array includes both
applicationandapplication?.name. Since only thenameproperty is used (line 121), including the entireapplicationobject causes unnecessary re-runs when unrelated properties change.Apply this diff:
useEffect( function updateApplicationName() { !isSavingAppName && setApplicationName(application?.name); }, - [application, application?.name, isSavingAppName], + [application?.name, isSavingAppName], );
195-211: Optimize debounced callback dependencies.The dependency array includes the entire
applicationobject, but onlyapplication?.nameis accessed (line 197). This causes the debounced function to be recreated whenever any application property changes.Apply this diff:
[applicationName, application, applicationId, isAppNameValid, dispatch], + [applicationName, application?.name, applicationId, isAppNameValid, dispatch], );
356-373: Remove unused dependency from useMemo.
isApplicationSlugValidis listed in the dependency array (line 372) but is never referenced in the function body. This causes unnecessary recomputation when server validation state changes.Apply this diff:
}, [ isFetchingAppSlugSuggestion, applicationSlug, isClientSideSlugValid, - isApplicationSlugValid, ]);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx(3 hunks)app/client/src/entities/URLRedirect/SlugURLRedirect.ts(1 hunks)app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx(7 hunks)app/client/src/sagas/InitSagas.ts(9 hunks)app/client/src/sagas/__tests__/initSagas.test.ts(2 hunks)app/client/src/utils/helpers.tsx(8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app/client/src/sagas/tests/initSagas.test.ts
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/sagas/InitSagas.ts:260-271
Timestamp: 2025-10-28T03:30:58.299Z
Learning: In app/client/src/sagas/InitSagas.ts, when constructing consolidatedApiParams for static page URLs, the code intentionally reuses applicationId and defaultPageId fields to pass staticApplicationSlug and staticPageSlug values respectively. This is by design, even though ConsolidatedApiParams type has dedicated staticApplicationSlug and staticPageSlug fields.
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx:330-359
Timestamp: 2025-10-28T09:17:22.519Z
Learning: In the Appsmith codebase, slug normalization for static URLs (application slugs and page slugs) handles lowercase conversion on the backend. The frontend helper `filterAccentedAndSpecialCharacters` in `app/client/src/pages/AppIDE/components/AppSettings/utils.ts` intentionally preserves the user's input casing to avoid modifying the entered value too drastically, as the backend will normalize to lowercase during persistence.
Learnt from: ashit-rath
PR: appsmithorg/appsmith#33809
File: app/client/src/workers/Evaluation/evaluate.ts:209-229
Timestamp: 2024-10-08T15:32:34.115Z
Learning: User ashit-rath prefers using `forEach` over `for...of` for iterating over objects and arrays in JavaScript.
Learnt from: ashit-rath
PR: appsmithorg/appsmith#33809
File: app/client/src/workers/Evaluation/evaluate.ts:209-229
Timestamp: 2024-07-26T21:12:57.228Z
Learning: User ashit-rath prefers using `forEach` over `for...of` for iterating over objects and arrays in JavaScript.
📚 Learning: 2025-10-28T03:30:58.299Z
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/sagas/InitSagas.ts:260-271
Timestamp: 2025-10-28T03:30:58.299Z
Learning: In app/client/src/sagas/InitSagas.ts, when constructing consolidatedApiParams for static page URLs, the code intentionally reuses applicationId and defaultPageId fields to pass staticApplicationSlug and staticPageSlug values respectively. This is by design, even though ConsolidatedApiParams type has dedicated staticApplicationSlug and staticPageSlug fields.
Applied to files:
app/client/src/entities/URLRedirect/SlugURLRedirect.tsapp/client/src/sagas/InitSagas.tsapp/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsxapp/client/src/ce/reducers/uiReducers/applicationsReducer.tsxapp/client/src/utils/helpers.tsx
📚 Learning: 2025-10-28T09:17:22.519Z
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx:330-359
Timestamp: 2025-10-28T09:17:22.519Z
Learning: In the Appsmith codebase, slug normalization for static URLs (application slugs and page slugs) handles lowercase conversion on the backend. The frontend helper `filterAccentedAndSpecialCharacters` in `app/client/src/pages/AppIDE/components/AppSettings/utils.ts` intentionally preserves the user's input casing to avoid modifying the entered value too drastically, as the backend will normalize to lowercase during persistence.
Applied to files:
app/client/src/entities/URLRedirect/SlugURLRedirect.tsapp/client/src/sagas/InitSagas.tsapp/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsxapp/client/src/ce/reducers/uiReducers/applicationsReducer.tsxapp/client/src/utils/helpers.tsx
📚 Learning: 2024-12-10T10:52:38.873Z
Learnt from: brayn003
PR: appsmithorg/appsmith#38060
File: app/client/src/git/sagas/fetchLocalProfileSaga.ts:8-13
Timestamp: 2024-12-10T10:52:38.873Z
Learning: In `app/client/src/git/sagas/fetchLocalProfileSaga.ts` and similar Git sagas, error handling for `baseArtifactId` is managed outside the scope, so validation checks for `baseArtifactId` within the saga functions are unnecessary.
Applied to files:
app/client/src/sagas/InitSagas.tsapp/client/src/ce/reducers/uiReducers/applicationsReducer.tsx
📚 Learning: 2024-07-26T21:12:57.228Z
Learnt from: ankitakinger
PR: appsmithorg/appsmith#29965
File: app/client/src/utils/storage.ts:129-129
Timestamp: 2024-07-26T21:12:57.228Z
Learning: The `migrateAppIdToEditorId` function in `app/client/src/utils/storage.ts` is intended to be called only when `appId` is present and `editorId` is not in the payload. This context should be considered in future reviews related to this function.
Applied to files:
app/client/src/sagas/InitSagas.tsapp/client/src/ce/reducers/uiReducers/applicationsReducer.tsx
📚 Learning: 2024-07-26T21:12:57.228Z
Learnt from: ankitakinger
PR: appsmithorg/appsmith#29965
File: app/client/src/ce/sagas/ApplicationSagas.tsx:736-742
Timestamp: 2024-07-26T21:12:57.228Z
Learning: The use of `editorId` instead of `appId` is an intentional change in the PR and is part of reverting to a previous functionality.
Applied to files:
app/client/src/sagas/InitSagas.ts
📚 Learning: 2025-04-28T16:16:02.155Z
Learnt from: brayn003
PR: appsmithorg/appsmith#40462
File: app/client/src/git/components/ImportOverrideModal/ImportOverrideModalView.tsx:34-40
Timestamp: 2025-04-28T16:16:02.155Z
Learning: The Appsmith team prefers not to include HTML markup in string constants. Text styling or emphasis should be handled through proper React components rather than HTML tags in strings.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-12-11T08:33:24.352Z
Learnt from: brayn003
PR: appsmithorg/appsmith#38088
File: app/client/src/git/components/GitQuickActions/BranchButton/index.tsx:72-74
Timestamp: 2024-12-11T08:33:24.352Z
Learning: In the 'BranchButton' component in 'app/client/src/git/components/GitQuickActions/BranchButton/index.tsx' (TypeScript, React), the `useEffect` hook that checks for label ellipsis does not need to include `currentBranch` in its dependency array.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: alex-golovanov
PR: appsmithorg/appsmith#36665
File: app/client/src/IDE/Components/FileTab/styles.tsx:19-19
Timestamp: 2024-10-08T15:32:34.115Z
Learning: Do not suggest replacing hardcoded `padding-top: 6px;` with design variables in `app/client/src/IDE/Components/FileTab/styles.tsx`.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-11-12T11:42:28.998Z
Learnt from: ankitakinger
PR: appsmithorg/appsmith#37330
File: app/client/src/pages/common/SearchBar/HomepageHeaderAction.tsx:95-95
Timestamp: 2024-11-12T11:42:28.998Z
Learning: In icon provider components within the TypeScript/React codebase, old settings icons like `"settings-2-line"` and `"settings-control"` are intentionally provided alongside new icons. These references are acceptable and should not be flagged for updates.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-11-12T07:37:42.598Z
Learnt from: ankitakinger
PR: appsmithorg/appsmith#37330
File: app/client/src/pages/Editor/gitSync/components/GitChangesList/StaticChange.tsx:52-52
Timestamp: 2024-11-12T07:37:42.598Z
Learning: The icon provider components in `app/client/packages/design-system/widgets-old/src/Icon/index.tsx` and `app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx` should provide both `settings-2-line` and `settings-v3` icons and should not be updated to remove the old icon.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-12-10T10:53:17.146Z
Learnt from: brayn003
PR: appsmithorg/appsmith#38060
File: app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.ts:16-24
Timestamp: 2024-12-10T10:53:17.146Z
Learning: In the `getPullBtnStatus` function (`app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.ts`), default parameter values should be explicitly mentioned to handle component state properly, even if all props are required.
Applied to files:
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx
📚 Learning: 2024-12-05T10:56:13.739Z
Learnt from: brayn003
PR: appsmithorg/appsmith#37984
File: app/client/src/git/requests/fetchSSHKeyRequest.ts:5-9
Timestamp: 2024-12-05T10:56:13.739Z
Learning: In `app/client/src/git/requests/fetchSSHKeyRequest.ts`, the `fetchSSHKeyRequest` function does not require explicit error handling for `baseApplicationId`; the function should throw an error naturally if `baseApplicationId` is missing or invalid.
Applied to files:
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx
📚 Learning: 2024-12-16T19:47:22.699Z
Learnt from: brayn003
PR: appsmithorg/appsmith#38171
File: app/client/src/git/ce/components/DefaultBranch/DefaultBranchView.tsx:92-100
Timestamp: 2024-12-16T19:47:22.699Z
Learning: In this codebase, action creators like `updateDefaultBranch` do not throw errors, so adding error handling around them is unnecessary.
Applied to files:
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx
📚 Learning: 2024-07-26T21:12:57.228Z
Learnt from: sneha122
PR: appsmithorg/appsmith#30012
File: app/client/src/pages/Editor/DataSourceEditor/RestAPIDatasourceForm.tsx:679-682
Timestamp: 2024-07-26T21:12:57.228Z
Learning: The user `sneha122` has confirmed the resolution of the feedback regarding the redundancy of `|| false` in the `_.get` expression within the `RestAPIDatasourceForm.tsx` file.
Applied to files:
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx
📚 Learning: 2024-07-26T21:12:57.228Z
Learnt from: sharat87
PR: appsmithorg/appsmith#30252
File: deploy/docker/fs/usr/lib/python3/dist-packages/supervisor/appsmith_supervisor_stdout.py:21-29
Timestamp: 2024-07-26T21:12:57.228Z
Learning: The user has confirmed that the suggested changes to handle potential exceptions and improve the robustness of the `main` function in `appsmith_supervisor_stdout.py` are acceptable.
Applied to files:
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx
📚 Learning: 2024-10-21T13:17:59.251Z
Learnt from: brayn003
PR: appsmithorg/appsmith#36989
File: app/client/packages/git/src/actions/helpers/createSingleArtifactAction.ts:52-68
Timestamp: 2024-10-21T13:17:59.251Z
Learning: In this codebase, when using Redux Toolkit's createSlice from Redux Toolkit, we can directly mutate the state within reducers since Immer handles immutability internally.
Applied to files:
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx
🧬 Code graph analysis (5)
app/client/src/entities/URLRedirect/SlugURLRedirect.ts (1)
app/client/src/utils/helpers.tsx (1)
getUpdatedRoute(1042-1095)
app/client/src/sagas/InitSagas.ts (3)
app/client/src/utils/helpers.tsx (1)
getSearchQuery(806-810)app/client/src/actions/initActions.ts (2)
initEditorAction(21-26)initAppViewerAction(38-57)app/client/src/ce/pages/Editor/Explorer/helpers.tsx (2)
isViewerPath(135-137)matchViewerPathTyped(122-133)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (6)
app/client/src/selectors/editorSelectors.tsx (1)
getCurrentBasePageId(176-177)app/client/src/ce/selectors/applicationSelectors.tsx (6)
getIsSavingAppName(56-57)getIsApplicationSlugValid(64-65)getIsValidatingAppSlug(62-63)getIsFetchingAppSlugSuggestion(212-213)getAppSlugSuggestion(215-216)getIsPersistingAppSlug(60-61)app/client/src/ce/entities/FeatureFlag.ts (1)
FEATURE_FLAG(2-68)app/client/src/ce/constants/messages.ts (12)
STATIC_URL_CHANGE_SUCCESS(1938-1939)STATIC_URL_DISABLED_SUCCESS(1936-1937)GENERAL_SETTINGS_APP_URL_EMPTY_VALUE_MESSAGE(1932-1933)GENERAL_SETTINGS_APP_URL_INVALID_MESSAGE(1923-1924)GENERAL_SETTINGS_NAME_EMPTY_MESSAGE(1914-1915)GENERAL_SETTINGS_APP_ICON_LABEL(1918-1918)GENERAL_SETTINGS_APP_URL_LABEL(1919-1919)GENERAL_SETTINGS_APP_URL_PLACEHOLDER_FETCHING(1921-1922)GENERAL_SETTINGS_APP_URL_PLACEHOLDER(1920-1920)GENERAL_SETTINGS_APP_URL_CHECKING_MESSAGE(1927-1928)GENERAL_SETTINGS_APP_URL_AVAILABLE_MESSAGE(1929-1929)GENERAL_SETTINGS_APP_URL_UNAVAILABLE_MESSAGE(1930-1931)app/client/src/ce/actions/applicationActions.ts (6)
enableStaticUrl(322-330)persistAppSlug(82-90)resetAppSlugValidation(341-345)validateAppSlug(92-99)fetchAppSlugSuggestion(101-108)disableStaticUrl(332-339)app/client/src/ce/api/ApplicationApi.tsx (5)
enableStaticUrl(544-552)persistAppSlug(522-533)validateAppSlug(535-542)fetchAppSlugSuggestion(560-566)disableStaticUrl(554-558)
app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx (2)
app/client/src/ce/constants/ReduxActionConstants.tsx (2)
ReduxActionTypes(1321-1365)ReduxActionErrorTypes(1367-1394)app/client/src/actions/ReduxActionTypes.ts (1)
ReduxAction(9-12)
app/client/src/utils/helpers.tsx (1)
app/client/src/ce/constants/routes/appRoutes.ts (1)
VIEWER_PATH_STATIC(28-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: perform-test / rts-build / build
- GitHub Check: perform-test / client-build / client-build
- GitHub Check: perform-test / server-build / server-unit-tests
- GitHub Check: client-build / client-build
- GitHub Check: client-check-cyclic-deps / check-cyclic-dependencies
- GitHub Check: client-lint / client-lint
- GitHub Check: client-prettier / prettier-check
- GitHub Check: client-unit-tests / client-unit-tests
🔇 Additional comments (3)
app/client/src/entities/URLRedirect/SlugURLRedirect.ts (1)
37-49: Implementation correctly handles empty static slugs—no changes needed.The downstream code consistently validates that both
staticApplicationSlugandstaticPageSlugare present using AND logic before applying static URL transformations. When either slug is empty, the code gracefully skips static URL handling and falls back to legacy URL patterns withbasePageId. This pattern is enforced across all consuming code paths (InitSagas, Engine, AppIDELoader, MenuItem, etc.), making the implementation safe and robust.app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (2)
225-247: Verify frontend lowercase conversion approach.Line 228 applies
.toLowerCase()directly in the frontend. According to retrieved learnings, thefilterAccentedAndSpecialCharactershelper intentionally preserves user input casing, with backend handling normalization. This code bypasses that helper and forces lowercase immediately. Confirm this is the intended UX for application slugs (different from page slugs) or if it should preserve casing like the helper does.Based on learnings.
259-303: Modal slug computation logic verified—no issues found.The code correctly handles all three scenarios:
- Enable first time: Transitions from legacy format (
appSlug/customSlug-pageId) to static format (staticAppSlug/uniqueSlug)- Change existing: Stays in static format while updating the slug
- Disable: Transitions back from static (
staticAppSlug/uniqueSlug) to legacy (appSlug/customSlug-pageId)Page slug properties are used consistently throughout the codebase:
uniqueSlugfor static URLs,customSlugfor legacy custom slugs, andslugas fallback. The page ID suffix is correctly included only in legacy format. The logic is sound.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (1)
307-314: Fix class name typo in AppUrlContent.Extra closing parenthesis breaks the CSS variable.
- <strong className="text-[color:var(--appsmith-color-black-800))]"> + <strong className="text-[color:var(--appsmith-color-black-800)]">
🧹 Nitpick comments (1)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (1)
358-375: Remove unused dependency from memoization.The
isApplicationSlugValidis included in the dependency array but not used in the function body. This can cause unnecessary re-computation.}, [ isFetchingAppSlugSuggestion, applicationSlug, isClientSideSlugValid, - isApplicationSlugValid, ]);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx(7 hunks)
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/sagas/InitSagas.ts:260-271
Timestamp: 2025-10-28T03:30:58.299Z
Learning: In app/client/src/sagas/InitSagas.ts, when constructing consolidatedApiParams for static page URLs, the code intentionally reuses applicationId and defaultPageId fields to pass staticApplicationSlug and staticPageSlug values respectively. This is by design, even though ConsolidatedApiParams type has dedicated staticApplicationSlug and staticPageSlug fields.
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/utils/helpers.tsx:1124-1136
Timestamp: 2025-10-30T07:15:20.265Z
Learning: In app/client/src/utils/helpers.tsx, within the getUpdateRouteForSlugPath function, the pageSlug parameter extracted from the route includes the trailing hyphen (e.g., "home-page-" not "home-page"). Additionally, when the static slug conversion branch is executed, params.basePageId is guaranteed to be defined because the code path requires successful page data fetch from the server as a precondition.
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx:330-359
Timestamp: 2025-10-28T09:17:22.519Z
Learning: In the Appsmith codebase, slug normalization for static URLs (application slugs and page slugs) handles lowercase conversion on the backend. The frontend helper `filterAccentedAndSpecialCharacters` in `app/client/src/pages/AppIDE/components/AppSettings/utils.ts` intentionally preserves the user's input casing to avoid modifying the entered value too drastically, as the backend will normalize to lowercase during persistence.
Learnt from: ashit-rath
PR: appsmithorg/appsmith#33809
File: app/client/src/workers/Evaluation/evaluate.ts:209-229
Timestamp: 2024-10-08T15:32:34.115Z
Learning: User ashit-rath prefers using `forEach` over `for...of` for iterating over objects and arrays in JavaScript.
Learnt from: ashit-rath
PR: appsmithorg/appsmith#33809
File: app/client/src/workers/Evaluation/evaluate.ts:209-229
Timestamp: 2024-07-26T21:12:57.228Z
Learning: User ashit-rath prefers using `forEach` over `for...of` for iterating over objects and arrays in JavaScript.
📚 Learning: 2025-10-28T09:17:22.519Z
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/pages/AppIDE/components/AppSettings/components/PageSettings.tsx:330-359
Timestamp: 2025-10-28T09:17:22.519Z
Learning: In the Appsmith codebase, slug normalization for static URLs (application slugs and page slugs) handles lowercase conversion on the backend. The frontend helper `filterAccentedAndSpecialCharacters` in `app/client/src/pages/AppIDE/components/AppSettings/utils.ts` intentionally preserves the user's input casing to avoid modifying the entered value too drastically, as the backend will normalize to lowercase during persistence.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2025-10-28T03:30:58.299Z
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/sagas/InitSagas.ts:260-271
Timestamp: 2025-10-28T03:30:58.299Z
Learning: In app/client/src/sagas/InitSagas.ts, when constructing consolidatedApiParams for static page URLs, the code intentionally reuses applicationId and defaultPageId fields to pass staticApplicationSlug and staticPageSlug values respectively. This is by design, even though ConsolidatedApiParams type has dedicated staticApplicationSlug and staticPageSlug fields.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2025-10-30T07:15:20.265Z
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/utils/helpers.tsx:1124-1136
Timestamp: 2025-10-30T07:15:20.265Z
Learning: In app/client/src/utils/helpers.tsx, within the getUpdateRouteForSlugPath function, the pageSlug parameter extracted from the route includes the trailing hyphen (e.g., "home-page-" not "home-page"). Additionally, when the static slug conversion branch is executed, params.basePageId is guaranteed to be defined because the code path requires successful page data fetch from the server as a precondition.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2025-10-30T07:17:49.624Z
Learnt from: ashit-rath
PR: appsmithorg/appsmith#41312
File: app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx:817-883
Timestamp: 2025-10-30T07:17:49.624Z
Learning: In app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx, the isErrorPersistingAppSlug flag is unused and should be removed. There is no corresponding selector to expose it, and no handlers set it to true.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2025-04-28T16:16:02.155Z
Learnt from: brayn003
PR: appsmithorg/appsmith#40462
File: app/client/src/git/components/ImportOverrideModal/ImportOverrideModalView.tsx:34-40
Timestamp: 2025-04-28T16:16:02.155Z
Learning: The Appsmith team prefers not to include HTML markup in string constants. Text styling or emphasis should be handled through proper React components rather than HTML tags in strings.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-12-11T08:33:24.352Z
Learnt from: brayn003
PR: appsmithorg/appsmith#38088
File: app/client/src/git/components/GitQuickActions/BranchButton/index.tsx:72-74
Timestamp: 2024-12-11T08:33:24.352Z
Learning: In the 'BranchButton' component in 'app/client/src/git/components/GitQuickActions/BranchButton/index.tsx' (TypeScript, React), the `useEffect` hook that checks for label ellipsis does not need to include `currentBranch` in its dependency array.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-10-08T15:32:34.115Z
Learnt from: alex-golovanov
PR: appsmithorg/appsmith#36665
File: app/client/src/IDE/Components/FileTab/styles.tsx:19-19
Timestamp: 2024-10-08T15:32:34.115Z
Learning: Do not suggest replacing hardcoded `padding-top: 6px;` with design variables in `app/client/src/IDE/Components/FileTab/styles.tsx`.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-11-12T11:42:28.998Z
Learnt from: ankitakinger
PR: appsmithorg/appsmith#37330
File: app/client/src/pages/common/SearchBar/HomepageHeaderAction.tsx:95-95
Timestamp: 2024-11-12T11:42:28.998Z
Learning: In icon provider components within the TypeScript/React codebase, old settings icons like `"settings-2-line"` and `"settings-control"` are intentionally provided alongside new icons. These references are acceptable and should not be flagged for updates.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
📚 Learning: 2024-11-12T07:37:42.598Z
Learnt from: ankitakinger
PR: appsmithorg/appsmith#37330
File: app/client/src/pages/Editor/gitSync/components/GitChangesList/StaticChange.tsx:52-52
Timestamp: 2024-11-12T07:37:42.598Z
Learning: The icon provider components in `app/client/packages/design-system/widgets-old/src/Icon/index.tsx` and `app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx` should provide both `settings-2-line` and `settings-v3` icons and should not be updated to remove the old icon.
Applied to files:
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx
🧬 Code graph analysis (1)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (6)
app/client/src/selectors/editorSelectors.tsx (2)
getPageList(163-164)getCurrentBasePageId(176-177)app/client/src/ce/selectors/applicationSelectors.tsx (6)
getIsSavingAppName(56-57)getIsApplicationSlugValid(64-65)getIsValidatingAppSlug(62-63)getIsFetchingAppSlugSuggestion(212-213)getAppSlugSuggestion(215-216)getIsPersistingAppSlug(60-61)app/client/src/ce/entities/FeatureFlag.ts (1)
FEATURE_FLAG(2-68)app/client/src/ce/constants/messages.ts (12)
STATIC_URL_CHANGE_SUCCESS(1938-1939)STATIC_URL_DISABLED_SUCCESS(1936-1937)GENERAL_SETTINGS_APP_URL_EMPTY_VALUE_MESSAGE(1932-1933)GENERAL_SETTINGS_APP_URL_INVALID_MESSAGE(1923-1924)GENERAL_SETTINGS_NAME_EMPTY_MESSAGE(1914-1915)GENERAL_SETTINGS_APP_ICON_LABEL(1918-1918)GENERAL_SETTINGS_APP_URL_LABEL(1919-1919)GENERAL_SETTINGS_APP_URL_PLACEHOLDER_FETCHING(1921-1922)GENERAL_SETTINGS_APP_URL_PLACEHOLDER(1920-1920)GENERAL_SETTINGS_APP_URL_CHECKING_MESSAGE(1927-1928)GENERAL_SETTINGS_APP_URL_AVAILABLE_MESSAGE(1929-1929)GENERAL_SETTINGS_APP_URL_UNAVAILABLE_MESSAGE(1930-1931)app/client/src/ce/actions/applicationActions.ts (6)
enableStaticUrl(322-330)persistAppSlug(82-90)resetAppSlugValidation(341-345)validateAppSlug(92-99)fetchAppSlugSuggestion(101-108)disableStaticUrl(332-339)app/client/src/ce/api/ApplicationApi.tsx (5)
enableStaticUrl(544-552)persistAppSlug(522-533)validateAppSlug(535-542)fetchAppSlugSuggestion(560-566)disableStaticUrl(554-558)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (57)
- GitHub Check: perform-test / ci-test / ci-test (59)
- GitHub Check: perform-test / ci-test / ci-test (58)
- GitHub Check: perform-test / ci-test / ci-test (56)
- GitHub Check: perform-test / ci-test / ci-test (43)
- GitHub Check: perform-test / ci-test / ci-test (57)
- GitHub Check: perform-test / ci-test / ci-test (33)
- GitHub Check: perform-test / ci-test / ci-test (54)
- GitHub Check: perform-test / ci-test / ci-test (52)
- GitHub Check: perform-test / ci-test / ci-test (50)
- GitHub Check: perform-test / ci-test / ci-test (44)
- GitHub Check: perform-test / ci-test / ci-test (49)
- GitHub Check: perform-test / ci-test / ci-test (51)
- GitHub Check: perform-test / ci-test / ci-test (36)
- GitHub Check: perform-test / ci-test / ci-test (37)
- GitHub Check: perform-test / ci-test / ci-test (53)
- GitHub Check: perform-test / ci-test / ci-test (45)
- GitHub Check: perform-test / ci-test / ci-test (41)
- GitHub Check: perform-test / ci-test / ci-test (42)
- GitHub Check: perform-test / ci-test / ci-test (21)
- GitHub Check: perform-test / ci-test / ci-test (55)
- GitHub Check: perform-test / ci-test / ci-test (47)
- GitHub Check: perform-test / ci-test / ci-test (48)
- GitHub Check: perform-test / ci-test / ci-test (39)
- GitHub Check: perform-test / ci-test / ci-test (32)
- GitHub Check: perform-test / ci-test / ci-test (28)
- GitHub Check: perform-test / ci-test / ci-test (16)
- GitHub Check: perform-test / ci-test / ci-test (7)
- GitHub Check: perform-test / ci-test / ci-test (38)
- GitHub Check: perform-test / ci-test / ci-test (14)
- GitHub Check: perform-test / ci-test / ci-test (35)
- GitHub Check: perform-test / ci-test / ci-test (46)
- GitHub Check: perform-test / ci-test / ci-test (8)
- GitHub Check: perform-test / ci-test / ci-test (26)
- GitHub Check: perform-test / ci-test / ci-test (40)
- GitHub Check: perform-test / ci-test / ci-test (31)
- GitHub Check: perform-test / ci-test / ci-test (27)
- GitHub Check: perform-test / ci-test / ci-test (29)
- GitHub Check: perform-test / ci-test / ci-test (34)
- GitHub Check: perform-test / ci-test / ci-test (24)
- GitHub Check: perform-test / ci-test / ci-test (25)
- GitHub Check: perform-test / ci-test / ci-test (22)
- GitHub Check: perform-test / ci-test / ci-test (20)
- GitHub Check: perform-test / ci-test / ci-test (19)
- GitHub Check: perform-test / ci-test / ci-test (12)
- GitHub Check: perform-test / ci-test / ci-test (17)
- GitHub Check: perform-test / ci-test / ci-test (18)
- GitHub Check: perform-test / ci-test / ci-test (10)
- GitHub Check: perform-test / ci-test / ci-test (23)
- GitHub Check: perform-test / ci-test / ci-test (13)
- GitHub Check: perform-test / ci-test / ci-test (0)
- GitHub Check: perform-test / ci-test / ci-test (9)
- GitHub Check: perform-test / ci-test / ci-test (11)
- GitHub Check: perform-test / ci-test / ci-test (6)
- GitHub Check: perform-test / ci-test / ci-test (2)
- GitHub Check: perform-test / ci-test / ci-test (3)
- GitHub Check: perform-test / ci-test / ci-test (4)
- GitHub Check: perform-test / ci-test / ci-test (1)
🔇 Additional comments (8)
app/client/src/pages/AppIDE/components/AppSettings/components/GeneralSettings.tsx (8)
1-58: LGTM: Imports and regex are well-structured.All imports are necessary for the static URL feature implementation. The
APPLICATION_SLUG_REGEXpattern correctly enforces lowercase letters, digits, and hyphens for slugs.
86-119: LGTM: State management is well-organized.The state variables properly track slug validation, modal state, and feature flag status. Initialization from
application?.staticUrlSettings?.uniqueSlugcorrectly handles the optional chaining.
121-142: LGTM: Effects properly synchronize state.The effects correctly handle state synchronization with appropriate guards. The
!isSavingAppNamecheck prevents race conditions during save operations.
144-195: LGTM: Modal handlers are well-implemented.The handlers correctly distinguish between enabling static URLs for the first time and updating an existing slug. The reset logic in
cancelSlugChangeproperly restores the original state.
227-249: LGTM: Slug change handler with proper validation flow.The handler correctly normalizes the slug (lowercase, hyphen substitution) and validates client-side before dispatching server-side validation. This provides immediate feedback to users while ensuring uniqueness through the backend check.
251-305: LGTM: URL computation logic handles all scenarios correctly.The modal slug computation properly handles three distinct cases: enabling static URLs for the first time, changing an existing static URL, and disabling static URLs. The fallback chain for page slugs (
uniqueSlug || customSlug || slug) ensures resilience.
316-356: LGTM: Toggle and disable handlers are well-implemented.The toggle handler correctly differentiates between disabling a persisted static URL (requiring confirmation) and disabling a newly toggled-on URL (immediate). The clipboard copy uses the modern
navigator.clipboardAPI.
397-599: LGTM: Render section properly implements the static URL UI.The component correctly gates the static URL feature behind the feature flag and shows appropriate validation states. The Apply button disable conditions comprehensively prevent invalid submissions.
🎯 Overview
This PR implements Static URL functionality for Appsmith applications and pages, allowing users to create clean, URLs without auto-generated IDs. This feature is gated behind the
release_static_url_enabledfeature flag.🚀 Key Features
1. Application-Level Static URLs
my-appinstead ofuntitled-application-5)2. Page-Level Static URLs
dashboardinstead ofpage1-68fb0a086001f8101c93e34q)3. URL Format Changes
Before (Legacy Format):
After (Static URL Format):
🏗️ Technical Implementation
New Routes
BUILDER_PATH_STATIC:/app/:staticApplicationSlug/:staticPageSlug/editVIEWER_PATH_STATIC:/app/:staticApplicationSlug/:staticPageSlugNew Redux Actions
ENABLE_STATIC_URL/DISABLE_STATIC_URL: Toggle static URL featurePERSIST_APP_SLUG/PERSIST_PAGE_SLUG: Save application/page slugsVALIDATE_APP_SLUG/VALIDATE_PAGE_SLUG: Validate slug availabilityFETCH_APP_SLUG_SUGGESTION: Get auto-generated suggestionsNew API Endpoints
Application APIs
POST /api/v1/applications/:applicationId/static-url- Enable static URL with initial slugPUT /api/v1/applications/:applicationId/static-url- Update application slugDELETE /api/v1/applications/:applicationId/static-url- Disable static URLGET /api/v1/applications/:applicationId/static-url/:uniqueSlug- Validate application slug availabilityGET /api/v1/applications/:applicationId/static-url/suggest-app-slug- Get slug suggestionPage APIs
PATCH /api/v1/pages/static-url- Update page slugGET /api/v1/pages/:pageId/static-url/verify/:uniqueSlug- Validate page slug availabilityURL Assembly Enhancements
URLAssemblyto support static URL generationURL_TYPE.STATICfor static URL routingstaticPageSlugis not set, falls back to regularpageSlug🎨 UI Components
General Settings (Application Level)
Page Settings (Page Level)
StaticURLConfirmationModal
🔄 State Management
Application Reducer
uniqueSlug: Stores the application's static slugstaticUrlEnabled: Boolean flag for static URL statusPage List Reducer
uniqueSlug: Stores each page's static slugApplications UI Reducer
isValidatingAppSlug: Validation in progressisApplicationSlugValid: Validation resultisFetchingAppSlugSuggestion: Fetching suggestionappSlugSuggestion: Auto-generated suggestionisPersistingAppSlug: Save in progress🛡️ Validation Rules
Application/Page Slug Requirements:
🔀 Navigation & Routing
Route Matching Updates
matchBuilderPathto includeBUILDER_PATH_STATICmatchViewerPathto includeVIEWER_PATH_STATICstaticApplicationSlugandstaticPageSlugPage Navigation
useStaticUrlGenerationfor generating static URLs in navigationuseNavigateToAnotherPageto support static URLs📦 Key Files Changed
Core Logic:
URLAssembly.ts: URL generation logic with static URL supportApplicationSagas.tsx: Sagas for enable/disable/persist operationsPageSagas.tsx: Page-level slug persistenceappRoutes.ts: New static URL routesUI Components:
GeneralSettings.tsx: Application-level static URL configurationPageSettings.tsx: Page-level static URL configurationStaticURLConfirmationModal.tsx: Confirmation dialog (new)UrlPreview.tsx: URL preview component (new)State Management:
applicationsReducer.tsx: Application UI stateappReducer.ts: Application entity statepageListReducer.tsx: Page list state⚙️ Feature Flag
release_static_url_enabled: Controls visibility of static URL featuresAutomation
/ok-to-test tags="@tag.All"
🔍 Cypress test results
Tip
🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/18936467359
Commit: a74b4ac
Cypress dashboard.
Tags:
@tag.AllSpec:
Thu, 30 Oct 2025 10:56:15 UTC
Communication
Should the DevRel and Marketing teams inform users about this change?
Summary by CodeRabbit
New Features
Bug Fixes / Improvements