Skip to content

Conversation

admirsaheta
Copy link
Contributor

@admirsaheta admirsaheta commented Aug 14, 2025

Description

Related Issues

Type of Change

This PR implements user experience and security improvements to the web client, focusing on enhanced error handling and security configurations:

Enhanced Error Page : Completely redesigned the error page ( _error.tsx ) with:

  • Modern, user-friendly design with proper Tailwind CSS styling
  • Specific error messages for different HTTP status codes (404, 500, 403, 401)
  • "Go back home" and "Try again" action buttons for better user recovery
  • Development-only error details section for debugging
  • Improved accessibility with semantic HTML structure
  • Proper TypeScript types with NextPageContext

Security Headers : Added essential security headers in Next.js config:

  • X-Frame-Options: DENY - Prevents clickjacking attacks
  • X-Content-Type-Options: nosniff - Prevents MIME type sniffing
  • Referrer-Policy: strict-origin-when-cross-origin - Controls referrer information
  • Image Optimization : Configured modern image formats (WebP, AVIF) with 60-second cache TTL
  • Package Import Optimization : Enabled experimental optimizations for @onlook/ui and lucide-react packages
  • Removed Deprecated Config : Cleaned up deprecated devIndicators.buildActivity setting
  • Bug fix
  • New feature
  • Documentation update
  • Release
  • Refactor
  • Other (please describe):

Testing

Tested with Bun runtime:

  • ✅ Development server starts successfully with bun run dev
  • ✅ Error page renders correctly with proper styling and functionality
  • ✅ Security headers are properly set in HTTP responses
  • ✅ Image optimization works with modern formats
  • ✅ No deprecation warnings in console output
  • ✅ All existing functionality remains intact

Screenshots (if applicable)

Additional Notes


Important

Improves error handling and security in the web client by redesigning the error page and adding security headers in next.config.ts.

  • Error Handling:
    • Redesigned error page in _error.tsx with Tailwind CSS styling, specific messages for HTTP status codes (404, 500, 403, 401), and action buttons.
    • Added development-only error details section for debugging.
    • Improved accessibility with semantic HTML.
    • Added TypeScript types with NextPageContext.
  • Security:
    • Added security headers in next.config.ts: X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin.
  • Optimizations:
    • Configured image formats (WebP, AVIF) with 60-second cache TTL in next.config.ts.
    • Enabled experimental package import optimizations for @onlook/ui and lucide-react in next.config.ts.
    • Removed deprecated devIndicators.buildActivity setting in next.config.ts.

This description was created by Ellipsis for 8652ec9. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • New Features
    • Revamped error page with clear status messages, helpful descriptions, and quick actions (“Go back home” and “Try again”).
    • Enhanced image optimization with AVIF/WebP support and smarter caching for faster loads.
  • Security
    • Applied stricter security headers across all routes (X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy).
  • Performance
    • Experimental optimization for package imports to reduce bundle size and improve load times.
  • Chores
    • Removed obsolete development indicator configuration; retained existing lint and internationalization settings.

Copy link

vercel bot commented Aug 14, 2025

@admirsaheta is attempting to deploy a commit to the Onlook Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

coderabbitai bot commented Aug 14, 2025

Walkthrough

Introduces security headers and image/experimental settings in Next.js config, removes devIndicators. Overhauls the custom error page to a typed, UI-rich component with status-aware messaging, server/client context handling, development-only details, and updated getInitialProps returning extended error metadata.

Changes

Cohort / File(s) Summary of changes
Next.js config
apps/web/client/next.config.ts
Added headers() applying X-Frame-Options, X-Content-Type-Options, and Referrer-Policy. Removed devIndicators. Configured images (webp, avif, minimumCacheTTL=60). Added experimental.optimizePackageImports for @onlook/ui and lucide-react. Retained eslint and NextIntl settings.
Error page UI & typing
apps/web/client/src/pages/_error.tsx
Replaced minimal error text with a card UI showing status code, mapped message, and actions. Added getErrorMessage. Introduced ErrorProps, expanded component props. Updated getInitialProps to typed NextPageContext, returning statusCode, hasGetInitialPropsRun, and err. Added dev-only error details.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant R as Router/Next.js
  participant S as Server
  participant E as Error Page (_error.tsx)

  U->>R: Navigate/request page
  alt Server-side error
    R->>S: Render request
    S-->>R: err/statusCode
    R->>E: getInitialProps({ res, err })
    E-->>R: { statusCode, hasGetInitialPropsRun, err }
    R-->>U: Render Error UI (SSR)
  else Client-side error
    R->>E: getInitialProps({ err })
    E-->>R: { statusCode, hasGetInitialPropsRun, err }
    R-->>U: Render Error UI (CSR)
  end
  U->>R: Click "Go back home" or "Try again"
  R-->>U: Navigate/reload
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15–20 minutes

Poem

Thump-thump goes my coder heart, so bright,
We tamed the headers, locked them tight.
Errors now wear friendly faces,
With gentle hops through broken places.
AVIF dreams, WebP light—
I nibble bugs and set them right.
Hop on home; all’s in sight. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
apps/web/client/next.config.ts (2)

14-35: Solid baseline headers; suggest adding HSTS (prod-only) and modern COOP/CORP/Permissions-Policy

Great start with X-Frame-Options, X-Content-Type-Options, and Referrer-Policy. To harden further without undue risk, consider:

  • Add Strict-Transport-Security in production only.
  • Add Cross-Origin-Opener-Policy and Cross-Origin-Resource-Policy to reduce XS-Leaks.
  • Add a conservative Permissions-Policy.

Apply this diff to extend your headers while keeping HSTS gated to production:

-    async headers() {
-        return [
-            {
-                source: '/(.*)',
-                headers: [
-                    {
-                        key: 'X-Frame-Options',
-                        value: 'DENY',
-                    },
-                    {
-                        key: 'X-Content-Type-Options',
-                        value: 'nosniff',
-                    },
-                    {
-                        key: 'Referrer-Policy',
-                        value: 'strict-origin-when-cross-origin',
-                    },
-                ],
-            },
-        ];
-    },
+    async headers() {
+        const securityHeaders: Array<{ key: string; value: string }> = [
+            { key: 'X-Frame-Options', value: 'DENY' },
+            { key: 'X-Content-Type-Options', value: 'nosniff' },
+            { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
+            { key: 'Cross-Origin-Opener-Policy', value: 'same-origin' },
+            { key: 'Cross-Origin-Resource-Policy', value: 'same-origin' },
+            { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
+        ];
+        if (process.env.NODE_ENV === 'production') {
+            securityHeaders.push({
+                key: 'Strict-Transport-Security',
+                value: 'max-age=63072000; includeSubDomains; preload',
+            });
+        }
+        return [
+            {
+                source: '/(.*)',
+                headers: securityHeaders,
+            },
+        ];
+    },

Please confirm that DENY framing won’t break any legitimate embedding use-cases (docs, admin portals, etc.). If embedding is needed, switch to a CSP with frame-ancestors instead.


42-44: Use of optimizePackageImports is fine; validate package compatibility

This experimental flag works well for lucide-react. For @onlook/ui, confirm it’s ESM-friendly and safe for import slicing (no unexpected side effects from the package’s barrel). If you see unexpected behavior, consider per-package modularizeImports instead.

apps/web/client/src/pages/_error.tsx (1)

27-41: Optional: Improve semantics by using

and ARIA where appropriate

For better semantics, consider:

  • Replace the outer container with .
  • Add role="alert" to the message block for assistive tech emphasis.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3e8dc10 and 8652ec9.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • apps/web/client/next.config.ts (1 hunks)
  • apps/web/client/src/pages/_error.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (2.1.2)
apps/web/client/src/pages/_error.tsx

[error] 10-10: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🔇 Additional comments (3)
apps/web/client/next.config.ts (1)

37-40: Images config LGTM; verify remote image sources are configured

Using AVIF/WebP and a modest TTL is good. If you serve remote images, ensure images.domains or images.remotePatterns cover them; otherwise Next/Image will error at runtime.

apps/web/client/src/pages/_error.tsx (2)

27-41: Nice UX and accessibility improvements

  • Clear status-aware messaging, prominent actions, and sensible defaults.
  • Button-only reload avoids SSR “window” pitfalls.
  • Tailwind usage is consistent and readable.

No changes requested.

Also applies to: 43-57, 68-69


58-67: Dev-only error details are appropriately gated

Good job constraining stack traces to development only, reducing PII leakage risk in production.

Comment on lines +4 to +9
interface ErrorProps {
statusCode: number;
hasGetInitialPropsRun?: boolean;
err?: Error;
}

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Type mismatch: err.statusCode access is not on the base Error type

Accessing err.statusCode is not valid on the standard Error interface and may fail TS checks depending on Next’s typings. Introduce a narrowed type and use it in getInitialProps.

 interface ErrorProps {
     statusCode: number;
     hasGetInitialPropsRun?: boolean;
-    err?: Error;
+    err?: Error & { statusCode?: number };
 }
-ErrorPage.getInitialProps = ({ res, err }: NextPageContext): ErrorProps => {
-    const statusCode = res?.statusCode ?? err?.statusCode ?? 404;
+ErrorPage.getInitialProps = ({ res, err }: NextPageContext): ErrorProps => {
+    const e = err as (Error & { statusCode?: number }) | undefined;
+    const statusCode = res?.statusCode ?? e?.statusCode ?? 404;
     return { 
         statusCode,
         hasGetInitialPropsRun: true,
-        err: err || undefined
+        err: e
     };

Also applies to: 73-79

🤖 Prompt for AI Agents
In apps/web/client/src/pages/_error.tsx around lines 4-9 (and also update lines
73-79), the code accesses err.statusCode but the base Error type doesn't include
statusCode; define a narrowed error type (e.g., interface NextError extends
Error { statusCode?: number }) and use that type for ErrorProps.err and in
getInitialProps cast or type-guard the incoming err to NextError before reading
statusCode; update all err usages to use the narrowed type (or optional
chaining) so TypeScript accepts accessing statusCode.

err?: Error;
}

function Error({ statusCode, hasGetInitialPropsRun, err }: ErrorProps) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Rename component to avoid shadowing global Error (linter error)
Biome flags shadowing of the global Error constructor. Rename the component and its static getInitialProps.

-function Error({ statusCode, hasGetInitialPropsRun, err }: ErrorProps) {
+function ErrorPage({ statusCode, hasGetInitialPropsRun, err }: ErrorProps) {
-Error.getInitialProps = ({ res, err }: NextPageContext): ErrorProps => {
+ErrorPage.getInitialProps = ({ res, err }: NextPageContext): ErrorProps => {
-export default Error;
+export default ErrorPage;

Also applies to: 73-79, 82-82

🧰 Tools
🪛 Biome (2.1.2)

[error] 10-10: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🤖 Prompt for AI Agents
In apps/web/client/src/pages/_error.tsx around line 10 (and also affecting lines
73-79 and 82), the component is named "Error" which shadows the global Error
constructor and triggers a linter flag; rename the component (for example to
"ErrorPage") and update the static getInitialProps method to attach to the new
component name, update the default export to the new name, and adjust any
internal references or prop types that reference the old name so all occurrences
(declaration, static method, and export) are consistently renamed.

Comment on lines +10 to +25
function Error({ statusCode, hasGetInitialPropsRun, err }: ErrorProps) {
const getErrorMessage = (code: number) => {
switch (code) {
case 404:
return 'This page could not be found';
case 500:
return 'Internal Server Error';
case 403:
return 'Access Forbidden';
case 401:
return 'Authentication Required';
default:
return 'An unexpected error has occurred';
}
};

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use hasGetInitialPropsRun to rethrow client-side errors (Next.js-recommended pattern)

The prop is defined but unused. Add the rethrow to ensure client-side errors get surfaced to the runtime/monitoring.

-function ErrorPage({ statusCode, hasGetInitialPropsRun, err }: ErrorProps) {
-    const getErrorMessage = (code: number) => {
+function ErrorPage({ statusCode, hasGetInitialPropsRun, err }: ErrorProps) {
+    if (!hasGetInitialPropsRun && err) {
+        // Let Next.js handle this (useful for error tracking integrations)
+        throw err;
+    }
+    const getErrorMessage = (code: number) => {

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (2.1.2)

[error] 10-10: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🤖 Prompt for AI Agents
In apps/web/client/src/pages/_error.tsx around lines 10 to 25, the
hasGetInitialPropsRun prop is defined but unused; implement the
Next.js-recommended client-side rethrow so runtime/monitoring surface client
errors: after computing or inside the component, if hasGetInitialPropsRun is
false and err is present, rethrow err (throw err) to let the error propagate on
the client; keep the existing error message logic intact so server-rendered
paths still return the friendly message.

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.

1 participant