Skip to content

landing redesign - #1481

Merged
nearnshaw merged 3 commits into
mainfrom
landing-redesign
Aug 14, 2026
Merged

landing redesign#1481
nearnshaw merged 3 commits into
mainfrom
landing-redesign

Conversation

@nearnshaw

@nearnshaw nearnshaw commented Aug 10, 2026

Copy link
Copy Markdown
Member

CH Landind Redesign

Redid the landing page based on this Figma
https://www.figma.com/design/SDSx2kigI76sGeCkSIHFx0/%F0%9F%A7%B0-UX-Enhancement-%7C-Creators-Hub-%7C-07-26?node-id=1401-1298&p=f&t=DJUr6FJTbyb6iXLL-0

Things I intentionally didn't include from the design, to keep the changes light:

  • analytics
  • the redesign of the Settings menu
  • the redesign of the Report a bug
  • the redesign of the Check for updates flow
Screenshot 2026-08-10 at 6 38 07 PM

--

Screenshot 2026-08-10 at 6 38 30 PM

--

Screenshot 2026-08-10 at 6 38 18 PM

@github-actions

Copy link
Copy Markdown
Contributor

Test this pull request on windows-latest

Download the correct version for your architecture:

win-x64

@github-actions

Copy link
Copy Markdown
Contributor

Test this pull request on macos-latest

Download the correct version for your architecture:

mac-x64
mac-arm64

Click here if you don't know which version to download

For running this unsigned version of the app, you will need to run the xattr command on it:

  1. Extract the app from the downloaded .dmg file (double-click it)
  2. Place the extracted app anywhere you like in your file system
  3. Open a terminal on the directory where the app is
  4. Run xattr -c app-name, replacing "app-name" for the actual name of the app
  5. Double-click the app ✅

@decentraland-bot decentraland-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: #1481 — landing redesign

Branch: landing-redesignmain
Files changed: 30 (+1075 −451)
CI: ✅ All checks passing (lint, typecheck, unit tests, E2E mac, builds Windows/macOS)


Summary

Comprehensive redesign of the Creator Hub landing page. Replaces the old card-based layout (SignInCard, ScenesCard, LearnCard, FeedbackCard) with a modern row-based layout (MyScenesRow, TemplatesRow, LearnRow). Adds a LogoMenu dropdown in the navbar (About, Check for Updates, Settings, Report Bug, Help submenu), a CreateButton split-button, and a standalone About modal. The old navbar action buttons (Report Issue, Help icon, Settings icon) and ConnectionStatusIndicator are removed.

Verdict: ✅ APPROVE

No P0 or P1 issues found. The code is well-structured, correctly typed, and the Electron security model is respected. Several P2 improvement suggestions below.


Specific Review Areas (per requester)

1. Auto-update flow (Electron) ✅

The chain Navbar.handleCheckForUpdatesAppSettings(initialTab=ABOUT, autoCheckForUpdates=true)AboutTabUpdateSettings(autoCheck=true)useEffect fires handleCheckForUpdates is correct. handleCheckForUpdates is stable (deps: [dispatch], dispatch is stable). The useEffect fires once when the modal opens with autoCheck=true. handleCloseSettings properly resets autoCheckForUpdates to false, preventing re-triggers on subsequent opens.

2. useEffect loops ✅

  • UpdateSettings: useEffect(() => { if (autoCheck) handleCheckForUpdates(); }, [autoCheck, handleCheckForUpdates]) — safe, both deps are stable.
  • AppSettings: useEffect(() => { if (open) setActiveTab(initialTab); }, [open, initialTab]) — safe, initialTab only changes before the modal opens.
  • No infinite loop risk in any effect.

3. Link injection ✅

  • All URLs passed to misc.openExternal come from trusted sources: config files (HELP_FAQ_URL, CONTACT_SUPPORT_URL, DISCORD_URL, REPORT_ISSUES_URL) or hardcoded arrays (VIDEOS, DOCS).
  • misc.openExternal in preload validates with isUrl() before IPC, rejecting non-URL inputs.
  • Template thumbnails use STUDIOS_ADMIN_URL (first-party, in the security restrictions allowlist).
  • YouTube thumbnail URLs are built from hardcoded video IDs in resources.ts.
  • backgroundImage: url(${imageUrl}) — set via React's style prop (DOM property assignment), not raw CSS. Sources are all trusted (base64 project thumbnails, static imports, first-party CDN URLs).
  • No user-controllable data reaches shell.openExternal or CSS injection sinks.

4. Button clickability ✅

  • CreateButton: MUI ButtonGroup + Menu + MenuItem — fully interactive, proper data-testid, aria-haspopup, aria-expanded.
  • LogoMenu: MUI Menu + MenuItem with proper refs, submenu pattern with hover/click.
  • LearnTab buttons: native <button> elements.
  • LogoButton: native <button> with :focus-visible styles.

5. Security ✅

  • No hardcoded secrets or credentials.
  • No new dependencies.
  • All external URLs from trusted config or hardcoded data.
  • STUDIOS_ADMIN_URL is in the Electron security restrictions allowlist.
  • No dangerouslySetInnerHTML, no unsanitized user input.
  • Config URLs in dev.json/prd.json are all first-party Decentraland domains.

6. useCallback / component logic ✅

  • All useCallback dependency arrays are correct.
  • Closure factories (handleClickProject, handleClickTemplate, handleClickResource) are a standard React pattern — they create new closures per .map() call but this is expected and acceptable with ROW_SIZE = 4.
  • handleCreateProject correctly captures newProject in its deps.

P2 Findings (non-blocking suggestions)

[P2] Duplicated NewProjectPayload type

packages/creator-hub/renderer/src/components/CreateButton/types.ts and packages/creator-hub/renderer/src/components/HomePage/types.ts define the exact same NewProjectPayload type. Consider extracting to a shared location (e.g. alongside the CreateProject modal types) to avoid drift.

[P2] Duplicated project creation flow

Both CreateButton and TemplatesRow implement identical logic: getAvailableProject() → trim path → setNewProject() → render CreateProject modal → createProject(). This pattern also exists in TemplatesPage. Consider extracting into a useCreateProject hook that encapsulates the state + callbacks + modal rendering.

[P2] docIcons array recreated every render

In LearnRow, the docIcons array containing JSX elements is recreated on every render. Move it outside the component as a module constant (React elements are immutable and safe to reuse).

[P2] React.memo partially ineffective

HomeCard and Row are wrapped in React.memo, but they receive new function references as onClick props on each render (from closure factories in .map()). With only 4 items per row this is negligible, but worth noting — the memoization doesn't prevent re-renders here.

[P2] <video> elements won't play

HomeCard renders <video src={videoUrl} muted loop /> without autoPlay or controls. The video will load but display only the first frame (or nothing). If hover-to-play is intended, onMouseEnter/onMouseLeave handlers to call .play()/.pause() are missing.

[P2] Accessibility: <div> used as interactive elements

HomeCard and HomeRowHeader.Clickable use <div onClick> without role="button", tabIndex={0}, or keyboard event handlers. Consider using <button> (with reset styles) or adding the appropriate ARIA attributes for keyboard/screen-reader users.

[P2] PR title convention

The PR title "landing redesign" doesn't follow the repo's semantic commit format (e.g. feat: redesign landing page). Most recent merged PRs use the type: summary pattern.


Consumer Impact

This is a renderer-only UI change — no public API surface, exported packages, or shared types are affected. No downstream consumer impact.


Reviewed by Jarvis 🤖 · Requested by Gabriel Díaz (<@U03MGHMAJL8>) via Slack

onClickSignIn: () => void;
export type NewProjectPayload = {
name: string;
path: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] NewProjectPayload is defined identically in CreateButton/types.ts (lines 1–4) and here. Consider sharing from a single location to prevent drift.

},
[createProject, newProject],
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] docIcons is a static array of React elements but is recreated on every render of LearnRow. Since these are just icon components with no dynamic props, move them outside the component as a module-level constant:

Suggested change
const DOC_ICONS = [
<RocketLaunchOutlinedIcon />,
<CodeIcon />,
<AccountTreeOutlinedIcon />,
<WidgetsOutlinedIcon />,
];

</CardActions>
) : null}
</Card>
<Row

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] <video src={videoUrl} muted loop /> — without autoPlay or controls, videos will load but not play. If the intent is hover-to-play, consider adding onMouseEnter={(e) => e.currentTarget.play()} and onMouseLeave={(e) => { e.currentTarget.pause(); e.currentTarget.currentTime = 0; }}.

const handleSeeAll = useCallback(() => navigate('/scenes'), [navigate]);
const handleClickProject = useCallback(
(project: Project) => () => runProject(project),
[runProject],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Accessibility: <div className="HomeCard" onClick={onClick}> is not keyboard-accessible. Consider using <button> with reset styles, or add role="button", tabIndex={0}, and an onKeyDown handler for Enter/Space.

# Conflicts:
#	packages/creator-hub/renderer/src/config/env/dev.json
#	packages/creator-hub/renderer/src/modules/utils.ts
@nearnshaw
nearnshaw merged commit a012e4f into main Aug 14, 2026
19 checks passed
@nearnshaw
nearnshaw deleted the landing-redesign branch August 14, 2026 01:02
@balducciv

Copy link
Copy Markdown

QA update
Tested on both Mac and Windows.

✅ Passed:

LogoMenu

Top nav

  • Home, Scenes, Manage, Learn, More all navigate correctly

Create flow

  • "+ Create" → Create Project popup
  • Dropdown → New Scene → Create Project popup
  • Dropdown → Import Scene → file explorer

Auth

  • Sign in / Sign out both work

My Scenes

  • "My Scenes >" → Scenes tab
  • Can open a scene directly from homepage

Templates

  • "Templates >" → Templates tab
  • Choosing a template from homepage → Create Project popup

Learn

  • "Learn >" → Learn tab
  • Videos / Documentation toggle works

Build

  • Footer v0.45.0 matches PR build on both platforms

🐛 Bug found

Scroll position carries over when navigating away from the homepage.
If you scroll down on the homepage and then click into a section (Templates, Learn, etc. — via the ">" links or top nav tabs), the destination page opens at the same scroll offset instead of resetting to the top. Happens 100% of the time, confirmed on both Mac and Windows. Screenrecording attached.

❓ To confirm:
Opening a scene from "My Scenes" and then going back (clicking the back/return button) lands on the Scenes tab instead of back on Home, is this intentional or should it return Home?

⚠️ Known non-blocking gaps (already flagged in code review, confirmed in manual testing):

  • Video hover-play on homepage/Learn cards doesn't work
  • Keyboard nav (Tab) only reaches top nav + Learn's Videos/Documentation toggle — card grids aren't in the tab order

None of the issues are blockers; this is good to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants