Repository: solana-foundation/explorer
Pull request #531: Compact homepage
Author: login: ngundotra
Created: 2025-04-09T22:25:04Z | Merged: 2025-04-12T16:53:13Z

## Description

<!-- Provide a brief description of the changes in this PR -->
Compact `Live Cluster Stats` and `Live Transaction Stats` to make room for rich developer content.

Error message to homepage added if custom cluster fails to load.

## Type of change

<!-- Check the appropriate options that apply to this PR -->

-   [ ] Bug fix
-   [ ] New feature
-   [ ] Protocol integration
-   [ ] Documentation update
-   [x] Other (please describe): compact homepage to support rich developer doc links

## Screenshots

<!-- For UI changes, especially protocol screens, include screenshots showing the changes -->
<!-- This is REQUIRED for protocol integration PRs -->

<img width="1028" alt="Screenshot 2025-04-12 at 12 49 17 PM" src="https://github.com/user-attachments/assets/975a8023-0477-44ae-b5bb-1f2485399e34" />

## Testing

<!-- Describe how you tested your changes -->
<!-- For protocol integrations, explain how you verified the protocol data is correctly displayed -->

## Related Issues

<!-- Link to any related issues this PR addresses -->
<!-- Example: Fixes #123, Addresses #456 -->

## Checklist

<!-- Verify that you have completed the following before requesting review -->

-   [x] My code follows the project's style guidelines
-   [ ] I have added tests that prove my fix/feature works
-   [x] All tests pass locally and in CI
-   [ ] I have updated documentation as needed
-   [ ] CI/CD checks pass
-   [x] I have included screenshots for protocol screens (if applicable)
-   [ ] For security-related features, I have included links to related information

## Additional Notes

<!-- Add any other context about the PR here -->
<!-- For Solana Verify (Verified Builds) related changes, note that bugs should be reported to disclosures@solana.org -->

<!-- ELLIPSIS_HIDDEN -->

----

> [!IMPORTANT]
> Compact homepage layout by combining stats components and adding developer resources, with updates to `LiveTransactionStatsCard` and `TimestampToggle`.
> 
>   - **Homepage Layout**:
>     - Compact `Live Cluster Stats` and `Live Transaction Stats` into a single row in `page.tsx`.
>     - Add `DeveloperResources` component to `page.tsx` for developer content.
>   - **Components**:
>     - New `DeveloperResources` component with links to Solana developer resources.
>     - Update `LiveTransactionStatsCard` to remove footer and adjust layout for compact display.
>     - Modify `TimestampToggle` to accept `shorter` prop for abbreviated display.
>   - **Misc**:
>     - Rename `featureGate.tsx` to `UpcomingFeatures.tsx`.
> 
> <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=solana-foundation%2Fexplorer&utm_source=github&utm_medium=referral)<sup> for 4f401b3a2cdd25b1651f9e23e496e38e29856b46. It will automatically update as commits are pushed.</sup>

<!-- ELLIPSIS_HIDDEN -->

Linked issue #123: Transaction history for deleted accounts is not accessible
STR:
1. Transact with an account
2. Drain the account of all lamports

Now you can't see any of the account transactions in the explorer.

eg: 
![image](https://user-images.githubusercontent.com/1281082/82402544-871a7100-9a11-11ea-9cfc-b2b06c885205.png)
even though:
```
$ solana transaction-history 7bEc4uCz4mECXwynU5iR5Xr5A8tbWJ5Nyx7YWfvUmaZE
Transactions affecting 7bEc4uCz4mECXwynU5iR5Xr5A8tbWJ5Nyx7YWfvUmaZE within slots [11945508,11955508]
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
38 transactions found


Diff:
diff --git a/app/components/DeveloperResources.tsx b/app/components/DeveloperResources.tsx
new file mode 100644
index 000000000..b845b310d
--- /dev/null
+++ b/app/components/DeveloperResources.tsx
@@ -0,0 +1,83 @@
+'use client';
+
+export function DeveloperResources() {
+    return (
+        <div className="card">
+            <div className="card-body">
+                <div className="card-title d-flex justify-content-between border-bottom border-gray-300 pb-2">
+                    <div className="me-4">Kickstart your development journey on Solana</div>
+                    <div>
+                        Find more on{' '}
+                        <a href="https://solana.com/developers" target="_blank" rel="noreferrer">
+                            solana.com/developers
+                        </a>
+                    </div>
+                </div>
+                <div className="d-flex gap-4 pb-3 overflow-auto">
+                    <ResourceCard
+                        title="Setup Your Solana Environment"
+                        description="Get started in 5 minutes or less!"
+                        image="https://solana.com/opengraph/developers/docs/intro/installation"
+                        link="https://solana.com/docs/intro/installation"
+                    />
+                    <ResourceCard
+                        title="Quick Start Guide"
+                        description="Hands-on guide to the core concepts for building on Solana"
+                        image="https://solana.com/_next/image?url=%2Fassets%2Fdocs%2Fintro%2Fquickstart%2Fpg-not-connected.png&w=1920&q=75"
+                        link="https://solana.com/docs/intro/quick-start"
+                    />
+                    <ResourceCard
+                        title="Solana Developer Bootcamp"
+                        description="11 hours of video lessons on Solana Development"
+                        image="https://i.ytimg.com/vi/amAq-WHAFs8/maxresdefault.jpg"
+                        link="https://www.youtube.com/watch?v=amAq-WHAFs8"
+                    />
+                    <ResourceCard
+                        title="60 Days of Solana"
+                        description="A course designed for EVM developers to learn Solana"
+                        image="https://www.rareskills.io/wp-content/uploads/2024/08/og-image-rareskills.png"
+                        imageBackground="white"
+                        link="https://www.rareskills.io/solana-tutorial"
+                    />
+                </div>
+            </div>
+        </div>
+    );
+}
+
+function ResourceCard({
+    title,
+    description,
+    image,
+    link,
+    imageBackground,
+}: {
+    title: string;
+    description: string;
+    image: string;
+    imageBackground?: string;
+    link: string;
+}) {
+    return (
+        <div className="flex flex-col" style={{ height: '200px', width: '250px' }}>
+            <div className="w-full mb-3">
+                <a href={link} target="_blank" rel="noopener noreferrer" className="hover:cursor-pointer">
+                    <img
+                        src={image}
+                        alt={`${title} preview`}
+                        style={{
+                            backgroundColor: imageBackground,
+                            height: '120px',
+                            objectFit: 'cover',
+                            width: '250px',
+                        }}
+                    />
+                </a>
+            </div>
+            <div className="flex flex-col">
+                <p className="mb-1">{title}</p>
+                <p className="text-muted mb-2 text-wrap line-clamp-3">{description}</p>
+            </div>
+        </div>
+    );
+}
diff --git a/app/components/LiveTransactionStatsCard.tsx b/app/components/LiveTransactionStatsCard.tsx
index cb380855a..20696edc5 100644
--- a/app/components/LiveTransactionStatsCard.tsx
+++ b/app/components/LiveTransactionStatsCard.tsx
@@ -33,23 +33,11 @@ const SERIES_INFO = {
 export function LiveTransactionStatsCard() {
     const [series, setSeries] = React.useState<Series>('short');
     return (
-        <div className="card">
+        <div className="card flex-grow-1 d-flex flex-column">
             <div className="card-header">
                 <h4 className="card-header-title">Live Transaction Stats</h4>
             </div>
             <TpsCardBody series={series} setSeries={setSeries} />
-            <div className="card-body text-center">
-                <p className="mb-0">
-                    For transaction confirmation time statistics, please visit{' '}
-                    <a href="https://www.validators.app" target="_blank" rel="noopener noreferrer">
-                        validators.app
-                    </a>{' '}
-                    or{' '}
-                    <a href="https://solscan.io" target="_blank" rel="noopener noreferrer">
-                        solscan.io
-                    </a>
-                </p>
-            </div>
         </div>
     );
 }
@@ -71,6 +59,7 @@ const TPS_CHART_OPTIONS = (historyMaxTps: number): ChartOptions<'bar'> => {
             intersect: false,
             mode: 'index',
         },
+        maintainAspectRatio: false,
         plugins: {
             tooltip: {
                 enabled: false, // Disable the on-canvas tooltip
@@ -183,7 +172,7 @@ function TpsBarChart({ performanceInfo, series, setSeries }: TpsBarChartProps) {
     };
 
     return (
-        <>
+        <div className="d-flex flex-column flex-grow-1">
             <TableCardBody>
                 <tr>
                     <td className="w-100">Transaction count</td>
@@ -197,34 +186,43 @@ function TpsBarChart({ performanceInfo, series, setSeries }: TpsBarChartProps) {
 
             <hr className="my-0" />
 
-            <div className="card-body py-3">
-                <div className="align-box-row align-items-start justify-content-between">
-                    <div className="d-flex justify-content-between w-100">
-                        <span className="mb-0 font-size-sm">TPS history</span>
+            <div className="card-body py-3 d-flex flex-column flex-grow-1">
+                <div className="d-flex justify-content-between w-100">
+                    <span className="mb-0 font-size-sm">TPS history</span>
 
-                        <div className="font-size-sm">
-                            {SERIES.map(key => (
-                                <button
-                                    key={key}
-                                    onClick={() => setSeries(key)}
-                                    className={classNames('btn btn-sm btn-white ms-2', {
-                                        active: series === key,
-                                    })}
-                                >
-                                    {SERIES_INFO[key].interval}
-                                </button>
-                            ))}
-                        </div>
+                    <div className="font-size-sm">
+                        {SERIES.map(key => (
+                            <button
+                                key={key}
+                                onClick={() => setSeries(key)}
+                                className={classNames('btn btn-sm btn-white ms-2', {
+                                    active: series === key,
+                                })}
+                            >
+                                {SERIES_INFO[key].interval}
+                            </button>
+                        ))}
                     </div>
+                </div>
 
-                    <div id="perf-history" className="mt-3 d-flex justify-content-end flex-row w-100">
-                        <div className="w-100">
-                            <Bar data={chartData} options={chartOptions} height={80} />
-                        </div>
-                    </div>
+                <div id="perf-history" className="mt-3 flex-grow-1" style={{ minHeight: '200px' }}>
+                    <Bar data={chartData} options={chartOptions} style={{ height: '100%' }} />
+                </div>
+
+                <div className="text-center text-muted mt-3">
+                    <p className="mb-0">
+                        For transaction confirmation time statistics, please visit{' '}
+                        <a href="https://www.validators.app" target="_blank" rel="noopener noreferrer">
+                            validators.app
+                        </a>{' '}
+                        or{' '}
+                        <a href="https://solscan.io" target="_blank" rel="noopener noreferrer">
+                            solscan.io
+                        </a>
+                    </p>
                 </div>
             </div>
-        </>
+        </div>
     );
 }
 
diff --git a/app/components/common/TimestampToggle.tsx b/app/components/common/TimestampToggle.tsx
index bb3a14ee2..eb99664e6 100644
--- a/app/components/common/TimestampToggle.tsx
+++ b/app/components/common/TimestampToggle.tsx
@@ -19,7 +19,7 @@ function Tooltip({ state }: { state: State }) {
     );
 }
 
-export function TimestampToggle({ unixTimestamp }: { unixTimestamp: number }) {
+export function TimestampToggle({ unixTimestamp, shorter }: { unixTimestamp: number; shorter?: boolean }) {
     const [isTimestampTypeUtc, toggleTimestampType] = useState(true);
     const [showTooltip, toggleTooltip] = useState<State>('hide');
 
@@ -34,7 +34,9 @@ export function TimestampToggle({ unixTimestamp }: { unixTimestamp: number }) {
     return (
         <div className="popover-container w-100" style={tooltipContainer}>
             <span onClick={toggle} onMouseOver={() => toggleTooltip('show')} onMouseOut={() => toggleTooltip('hide')}>
-                {isTimestampTypeUtc === true ? displayTimestampUtc(unixTimestamp) : displayTimestamp(unixTimestamp)}
+                {isTimestampTypeUtc === true
+                    ? displayTimestampUtc(unixTimestamp, shorter)
+                    : displayTimestamp(unixTimestamp, shorter)}
             </span>
             <Tooltip state={showTooltip} />
         </div>
diff --git a/app/page.tsx b/app/page.tsx
index fef0b7bb8..0b5205cac 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -23,7 +23,8 @@ import { abbreviatedNumber, lamportsToSol, slotsToHumanString } from '@utils/ind
 import { percentage } from '@utils/math';
 import React from 'react';
 
-import { UpcomingFeatures } from './utils/feature-gate/featureGate';
+import { DeveloperResources } from './components/DeveloperResources';
+import { UpcomingFeatures } from './utils/feature-gate/UpcomingFeatures';
 
 export default function Page() {
     return (
@@ -31,17 +32,18 @@ export default function Page() {
             <SupplyProvider>
                 <div className="container mt-4">
                     <StakingComponent />
-                    <div className="card">
-                        <div className="card-header">
-                            <div className="row align-items-center">
-                                <div className="col">
-                                    <h4 className="card-header-title">Live Cluster Stats</h4>
-                                </div>
-                            </div>
+
+                    <div className="row d-flex">
+                        <div className="col-md-6 d-flex">
+                            <StatsCardBody />
+                        </div>
+                        <div className="col-md-6 d-flex">
+                            <LiveTransactionStatsCard />
                         </div>
-                        <StatsCardBody />
                     </div>
-                    <LiveTransactionStatsCard />
+
+                    <DeveloperResources />
+
                     <UpcomingFeatures />
                 </div>
             </SupplyProvider>
@@ -167,51 +169,60 @@ function StatsCardBody() {
     const { blockHeight, absoluteSlot } = epochInfo;
 
     return (
-        <TableCardBody>
-            <tr>
-                <td className="w-100">Slot</td>
-                <td className="text-lg-end font-monospace">
-                    <Slot slot={absoluteSlot} link />
-                </td>
-            </tr>
-            {blockHeight !== undefined && (
+        <div className="card flex-grow-1">
+            <div className="card-header">
+                <div className="row align-items-center">
+                    <div className="col">
+                        <h4 className="card-header-title">Live Cluster Stats</h4>
+                    </div>
+                </div>
+            </div>
+            <TableCardBody>
                 <tr>
-                    <td className="w-100">Block height</td>
+                    <td className="w-100">Slot</td>
                     <td className="text-lg-end font-monospace">
-                        <Slot slot={blockHeight} />
+                        <Slot slot={absoluteSlot} link />
                     </td>
                 </tr>
-            )}
-            {blockTime && (
+                {blockHeight !== undefined && (
+                    <tr>
+                        <td className="w-100">Block height</td>
+                        <td className="text-lg-end font-monospace">
+                            <Slot slot={blockHeight} />
+                        </td>
+                    </tr>
+                )}
+                {blockTime && (
+                    <tr>
+                        <td className="w-100">Cluster time</td>
+                        <td className="text-lg-end font-monospace">
+                            <TimestampToggle unixTimestamp={blockTime} shorter></TimestampToggle>
+                        </td>
+                    </tr>
+                )}
+                <tr>
+                    <td className="w-100">Slot time (1min average)</td>
+                    <td className="text-lg-end font-monospace">{averageSlotTime}ms</td>
+                </tr>
+                <tr>
+                    <td className="w-100">Slot time (1hr average)</td>
+                    <td className="text-lg-end font-monospace">{hourlySlotTime}ms</td>
+                </tr>
                 <tr>
-                    <td className="w-100">Cluster time</td>
+                    <td className="w-100">Epoch</td>
                     <td className="text-lg-end font-monospace">
-                        <TimestampToggle unixTimestamp={blockTime}></TimestampToggle>
+                        <Epoch epoch={epochInfo.epoch} link />
                     </td>
                 </tr>
-            )}
-            <tr>
-                <td className="w-100">Slot time (1min average)</td>
-                <td className="text-lg-end font-monospace">{averageSlotTime}ms</td>
-            </tr>
-            <tr>
-                <td className="w-100">Slot time (1hr average)</td>
-                <td className="text-lg-end font-monospace">{hourlySlotTime}ms</td>
-            </tr>
-            <tr>
-                <td className="w-100">Epoch</td>
-                <td className="text-lg-end font-monospace">
-                    <Epoch epoch={epochInfo.epoch} link />
-                </td>
-            </tr>
-            <tr>
-                <td className="w-100">Epoch progress</td>
-                <td className="text-lg-end font-monospace">{epochProgress}</td>
-            </tr>
-            <tr>
-                <td className="w-100">Epoch time remaining (approx.)</td>
-                <td className="text-lg-end font-monospace">~{epochTimeRemaining}</td>
-            </tr>
-        </TableCardBody>
+                <tr>
+                    <td className="w-100">Epoch progress</td>
+                    <td className="text-lg-end font-monospace">{epochProgress}</td>
+                </tr>
+                <tr>
+                    <td className="w-100">Epoch time remaining (approx.)</td>
+                    <td className="text-lg-end font-monospace">~{epochTimeRemaining}</td>
+                </tr>
+            </TableCardBody>
+        </div>
     );
 }
diff --git a/app/utils/feature-gate/featureGate.tsx b/app/utils/feature-gate/UpcomingFeatures.tsx
similarity index 100%
rename from app/utils/feature-gate/featureGate.tsx
rename to app/utils/feature-gate/UpcomingFeatures.tsx


Reviews:
user: login: ellipsis-dev[bot]
body: :x: Changes requested. Reviewed everything up to 4f401b3a2cdd25b1651f9e23e496e38e29856b46 in <ellipsistime>1 minute and 57 seconds</ellipsistime>

<details>
<summary>More details</summary>

 - Looked at `371` lines of code in `5` files
 - Skipped `0` files when reviewing.
 - Skipped posting `10` drafted comments based on config settings.


<details>
<summary>1. <code>app/components/DeveloperResources.tsx:1</code></summary>

- **Draft comment:** 
Good implementation of a simple developer resources card. Consider ensuring that the alt text (currently `${title} preview`) is sufficiently descriptive for accessibility if images fail to load.
- **Reason this comment was not posted:** 
Confidence changes required: `0%` <= threshold `50%`
None

</details>

<details>
<summary>2. <code>app/components/LiveTransactionStatsCard.tsx:62</code></summary>

- **Draft comment:** 
The addition of 'maintainAspectRatio: false' in chart options enhances layout responsiveness. Verify that the external tooltip element appended in the tooltip's external callback is cleaned up on unmount to avoid stale DOM nodes.
- **Reason this comment was not posted:** 
Comment did not seem useful. Confidence is useful = `0%` <= threshold `50%`
The comment is asking the author to verify a behavior, which is against the rules. It doesn't provide a specific suggestion or point out a clear issue with the code. It is more of a reminder or a suggestion to double-check something, which is not allowed.

</details>

<details>
<summary>3. <code>app/components/common/TimestampToggle.tsx:22</code></summary>

- **Draft comment:** 
TimestampToggle now supports a 'shorter' flag. The toggle functionality and tooltip setup appear correct.
- **Reason this comment was not posted:** 
Confidence changes required: `0%` <= threshold `50%`
None

</details>

<details>
<summary>4. <code>app/page.tsx:36</code></summary>

- **Draft comment:** 
The homepage layout is more compact, with Live Cluster Stats and Live Transaction Stats arranged side by side. Confirm that this layout remains user‐friendly on smaller screens.
- **Reason this comment was not posted:** 
Confidence changes required: `20%` <= threshold `50%`
None

</details>

<details>
<summary>5. <code>app/page.tsx:45</code></summary>

- **Draft comment:** 
DeveloperResources is included below the stats cards as intended. Ensure that the added developer content fits well with the existing UX.
- **Reason this comment was not posted:** 
Confidence changes required: `0%` <= threshold `50%`
None

</details>

<details>
<summary>6. <code>app/page.tsx:142</code></summary>

- **Draft comment:** 
Note: The PR description states that it resolves the issue with transaction history for deleted accounts, but the changes here focus solely on a compact homepage layout and developer resources. Please confirm that the transaction history issue is addressed elsewhere or adjust the PR description if needed.
- **Reason this comment was not posted:** 
Comment was not on a location in the diff, so it can't be submitted as a review comment.

</details>

<details>
<summary>7. <code>app/components/LiveTransactionStatsCard.tsx:66</code></summary>

- **Draft comment:** 
The custom tooltip implementation creates a DOM element if not present (lines 68–75). Consider cleaning up or removing the tooltip element during component unmount to avoid potential memory leaks.
- **Reason this comment was not posted:** 
Comment was not on a location in the diff, so it can't be submitted as a review comment.

</details>

<details>
<summary>8. <code>app/components/common/TimestampToggle.tsx:35</code></summary>

- **Draft comment:** 
For better accessibility, consider using a semantic interactive element (like a <button>) instead of a <span> for toggling the timestamp display.
- **Reason this comment was not posted:** 
Comment was on unchanged code.

</details>

<details>
<summary>9. <code>app/page.tsx:29</code></summary>

- **Draft comment:** 
The PR description mentions resolving the issue of transaction history for deleted accounts, but no changes related to transaction history are visible in this diff. Please confirm that the fix is included or address this functionality.
- **Reason this comment was not posted:** 
Comment did not seem useful. Confidence is useful = `0%` <= threshold `50%`
The comment is asking the PR author to confirm whether the fix mentioned in the PR description is included in the changes. This violates the rule against asking the author to confirm their intention or to update the PR description. The comment does not provide a specific code suggestion or point out a specific issue in the code.

</details>

<details>
<summary>10. <code>app/utils/feature-gate/UpcomingFeatures.tsx:14</code></summary>

- **Draft comment:** 
The comment on line 14 says "Don't show anything for localnet", but the subsequent condition checks for Cluster.Custom. For clarity and consistency, consider changing one of them so they match.
- **Reason this comment was not posted:** 
Comment was not on a location in the diff, so it can't be submitted as a review comment.

</details>


Workflow ID: <workflowid>`wflow_OLcrxTzaqM4zDr0x`</workflowid>

</details>


----
**Want Ellipsis to fix these issues?** Tag `@ellipsis-dev` in a comment. You can customize Ellipsis with :+1: / :-1: [feedback](https://docs.ellipsis.dev/review), review rules, user-specific overrides, `quiet` mode, and [more](https://docs.ellipsis.dev/config).

state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T16:50:51Z
user: login: ngundotra
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T16:51:58Z

Review comments:
diff_hunk: @@ -0,0 +1,83 @@
+'use client';
+
+export function DeveloperResources() {
+    return (
+        <div className="card">
+            <div className="card-body">
+                <div className="card-title d-flex justify-content-between border-bottom border-gray-300 pb-2">
+                    <div className="me-4">Kickstart your development journey on Solana</div>
+                    <div>
+                        Find more on{' '}
+                        <a href="https://solana.com/developers" target="_blank" rel="noreferrer">
+                            solana.com/developers
+                        </a>
+                    </div>
+                </div>
+                <div className="d-flex gap-4 pb-3 overflow-auto">
+                    <ResourceCard
+                        title="Setup Your Solana Environment"
+                        description="Get started in 5 minutes or less!"
+                        image="https://solana.com/opengraph/developers/docs/intro/installation"
+                        link="https://solana.com/docs/intro/installation"
+                    />
+                    <ResourceCard
+                        title="Quick Start Guide"
+                        description="Hands-on guide to the core concepts for building on Solana"
+                        image="https://solana.com/_next/image?url=%2Fassets%2Fdocs%2Fintro%2Fquickstart%2Fpg-not-connected.png&w=1920&q=75"
+                        link="https://solana.com/docs/intro/quick-start"
+                    />
+                    <ResourceCard
+                        title="Solana Developer Bootcamp"
+                        description="11 hours of video lessons on Solana Development"
+                        image="https://i.ytimg.com/vi/amAq-WHAFs8/maxresdefault.jpg"
+                        link="https://www.youtube.com/watch?v=amAq-WHAFs8"
+                    />
+                    <ResourceCard
+                        title="60 Days of Solana"
+                        description="A course designed for EVM developers to learn Solana"
+                        image="https://www.rareskills.io/wp-content/uploads/2024/08/og-image-rareskills.png"
+                        imageBackground="white"
+                        link="https://www.rareskills.io/solana-tutorial"
+                    />
+                </div>
+            </div>
+        </div>
+    );
+}
+
+function ResourceCard({
+    title,
+    description,
+    image,
+    link,
+    imageBackground,
+}: {
+    title: string;
+    description: string;
+    image: string;
+    imageBackground?: string;
+    link: string;
+}) {
+    return (
+        <div className="flex flex-col" style={{ height: '200px', width: '250px' }}>
path: app/components/DeveloperResources.tsx
user: login: ellipsis-dev[bot]
body: Consider using CSS classes (or Tailwind utilities) for fixed dimensions instead of inlined styles for consistency. For example, the inline style `{ height: '200px', width: '250px' }` could be replaced with proper utility classes.
created_at: 2025-04-12T16:50:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,83 @@
+'use client';
+
+export function DeveloperResources() {
+    return (
+        <div className="card">
+            <div className="card-body">
+                <div className="card-title d-flex justify-content-between border-bottom border-gray-300 pb-2">
+                    <div className="me-4">Kickstart your development journey on Solana</div>
+                    <div>
+                        Find more on{' '}
+                        <a href="https://solana.com/developers" target="_blank" rel="noreferrer">
+                            solana.com/developers
+                        </a>
+                    </div>
+                </div>
+                <div className="d-flex gap-4 pb-3 overflow-auto">
+                    <ResourceCard
+                        title="Setup Your Solana Environment"
+                        description="Get started in 5 minutes or less!"
+                        image="https://solana.com/opengraph/developers/docs/intro/installation"
+                        link="https://solana.com/docs/intro/installation"
+                    />
+                    <ResourceCard
+                        title="Quick Start Guide"
+                        description="Hands-on guide to the core concepts for building on Solana"
+                        image="https://solana.com/_next/image?url=%2Fassets%2Fdocs%2Fintro%2Fquickstart%2Fpg-not-connected.png&w=1920&q=75"
+                        link="https://solana.com/docs/intro/quick-start"
+                    />
+                    <ResourceCard
+                        title="Solana Developer Bootcamp"
+                        description="11 hours of video lessons on Solana Development"
+                        image="https://i.ytimg.com/vi/amAq-WHAFs8/maxresdefault.jpg"
+                        link="https://www.youtube.com/watch?v=amAq-WHAFs8"
+                    />
+                    <ResourceCard
+                        title="60 Days of Solana"
+                        description="A course designed for EVM developers to learn Solana"
+                        image="https://www.rareskills.io/wp-content/uploads/2024/08/og-image-rareskills.png"
+                        imageBackground="white"
+                        link="https://www.rareskills.io/solana-tutorial"
+                    />
+                </div>
+            </div>
+        </div>
+    );
+}
+
+function ResourceCard({
+    title,
+    description,
+    image,
+    link,
+    imageBackground,
+}: {
+    title: string;
+    description: string;
+    image: string;
+    imageBackground?: string;
+    link: string;
+}) {
+    return (
+        <div className="flex flex-col" style={{ height: '200px', width: '250px' }}>
path: app/components/DeveloperResources.tsx
user: login: ngundotra
body: tailwind props get overridden here
created_at: 2025-04-12T16:51:58Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-04-09T22:25:08Z
body: [vc]: #ZfFb083w5HGMURLzxfGltNIX1ZG4BvA4Oigpo29Osg4=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJleHBsb3JlciIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9zb2xhbmEtZm91bmRhdGlvbi9leHBsb3Jlci9BMlRvRGZjYXhjaXRxR0dnSDZ4aGpRVkdDcWp1IiwicHJldmlld1VybCI6ImV4cGxvcmVyLWdpdC1mZWF0LWNvbXBhY3QtaG9tZXBhZ2Utc29sYW5hLWZvdW5kYXRpb24udmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJleHBsb3Jlci1naXQtZmVhdC1jb21wYWN0LWhvbWVwYWdlLXNvbGFuYS1mb3VuZGF0aW9uLnZlcmNlbC5hcHAifSwicm9vdERpcmVjdG9yeSI6bnVsbH1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **explorer** | ✅ Ready ([Inspect](https://vercel.com/solana-foundation/explorer/A2ToDfcaxcitqGGgH6xhjQVGCqju)) | [Visit Preview](https://explorer-git-feat-compact-homepage-solana-foundation.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/explorer-git-feat-compact-homepage-solana-foundation.vercel.app?via=pr-comment-feedback-link) | Apr 12, 2025 4:48pm |


author_association: NONE
user: login: ngundotra
created_at: 2025-04-09T22:29:43Z
body: Still working on fixing these screens for custom urls:

![Screenshot 2025-04-09 at 6 29 12 PM](https://github.com/user-attachments/assets/0a0bb607-4f9f-49a8-8770-dc8c73a8299b)

![Screenshot 2025-04-09 at 6 29 25 PM](https://github.com/user-attachments/assets/7fc12958-89fd-450a-94ca-059adcca5e56)

author_association: CONTRIBUTOR
user: login: ngundotra
created_at: 2025-04-12T16:51:07Z
body: Regarding previous comment, I'll add a banner to homepage to detect issues with unresponsive custom cluster/dead custom urls
author_association: CONTRIBUTOR