Conversation
… improved user experience
… and editor support
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This pull request introduces comprehensive SEO improvements, error handling enhancements, and UI component additions to the ShellUI project. The changes focus on improving search engine visibility, user experience, and component library functionality.
Changes:
- Added SEO infrastructure including dynamic sitemap.xml, robots.txt, Google Analytics 4 integration, and structured data (JSON-LD) for better search engine understanding
- Introduced reusable error page component with consistent styling and not-found pages for improved error handling across the application
- Enhanced theming and accessibility in the InstallAnimation component by replacing hardcoded colors with semantic color classes
- Added Button component with comprehensive variants using class-variance-authority for consistent styling
- Created JSON schema for shellui.json configuration validation to improve CLI usability and editor integration
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| shellui/public/schema.json | Provides JSON schema for validating ShellUI configuration files, enabling better IDE support and validation |
| shellui/package.json | Adds radix-ui dependency for UI primitives support |
| shellui/lib/metadata.ts | Introduces metadata creation utility with Open Graph and Twitter card support for consistent SEO metadata |
| shellui/components/ui/error-page.tsx | Implements reusable error page component with illustration and call-to-action |
| shellui/components/ui/button.tsx | Adds fully-featured Button component with variants and asChild pattern support |
| shellui/components/install-animation.tsx | Improves theming with semantic color classes for better dark mode support |
| shellui/app/sitemap.ts | Implements dynamic sitemap generation for improved SEO and crawler support |
| shellui/app/robots.ts | Adds robots.txt configuration for search engine crawler control |
| shellui/app/not-found.tsx | Implements top-level not-found page using the new error component |
| shellui/app/layout.tsx | Enhances root layout with metadata, Google Analytics, and structured data |
| shellui/app/(home)/not-found.tsx | Adds route-specific not-found page |
| shellui/bun.lock | Updates lock file with new dependencies |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| title: | ||
| override.title ?? "ShellUI – CLI-first, shadcn-inspired Blazor components", |
There was a problem hiding this comment.
The same title extraction issue exists here. When override.title is an object with template and default properties, this will not work as expected.
| @@ -0,0 +1,30 @@ | |||
| import { Button } from "@/components/ui/button" | |||
|
|
|||
| const Error = () => { | |||
There was a problem hiding this comment.
The component name "Error" conflicts with the built-in JavaScript Error object. This could cause confusion and potential issues. Consider renaming the component to "ErrorPage" or "NotFoundError" to avoid this naming collision.
| @@ -0,0 +1,64 @@ | |||
| import * as React from "react" | |||
| import { cva, type VariantProps } from "class-variance-authority" | |||
There was a problem hiding this comment.
The button.tsx component imports and uses class-variance-authority (cva) but this package is not listed in package.json dependencies. This will cause a runtime error. Add "class-variance-authority" to the dependencies.
| <h2 className='mb-6 text-5xl font-semibold'>Whoops!</h2> | ||
| <h3 className='mb-1.5 text-3xl font-semibold'>Something went wrong</h3> |
There was a problem hiding this comment.
The heading hierarchy is incorrect. The page uses h2 followed by h3 without an h1. For proper document structure and accessibility, the main heading should be h1, not h2. Change the "Whoops!" heading to h1 and "Something went wrong" to h2.
| <h2 className='mb-6 text-5xl font-semibold'>Whoops!</h2> | |
| <h3 className='mb-1.5 text-3xl font-semibold'>Something went wrong</h3> | |
| <h1 className='mb-6 text-5xl font-semibold'>Whoops!</h1> | |
| <h2 className='mb-1.5 text-3xl font-semibold'>Something went wrong</h2> |
| import { Button } from "@/components/ui/button" | ||
|
|
||
| const Error = () => { | ||
| return ( | ||
| <div className='grid min-h-screen grid-cols-1 lg:grid-cols-2'> | ||
| <div className='flex flex-col items-center justify-center px-4 py-8 text-center'> | ||
| <h2 className='mb-6 text-5xl font-semibold'>Whoops!</h2> | ||
| <h3 className='mb-1.5 text-3xl font-semibold'>Something went wrong</h3> | ||
| <p className='text-muted-foreground mb-6 max-w-sm'> | ||
| The page you're looking for isn't found, we suggest you back to home. | ||
| </p> | ||
| <Button asChild size='lg' className='rounded-lg text-base'> | ||
| <a href='/'>Back to home page</a> | ||
| </Button> | ||
| </div> | ||
|
|
||
| {/* Right Section: Illustration */} | ||
| <div className='relative max-h-screen w-full p-2 max-lg:hidden'> | ||
| <div className='h-full w-full rounded-2xl bg-transparent'></div> | ||
| <img | ||
| src='https://cdn.shadcnstudio.com/ss-assets/blocks/marketing/error/image-1.png' | ||
| alt='404 illustration' | ||
| className='absolute top-1/2 left-1/2 h-[clamp(260px,25vw,406px)] -translate-x-1/2 -translate-y-1/2' | ||
| /> | ||
| </div> | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| export default Error |
There was a problem hiding this comment.
Inconsistent quote style: This file uses single quotes while the rest of the codebase uses double quotes. For consistency, use double quotes throughout.
| @@ -0,0 +1,7 @@ | |||
| import Error from '@/components/ui/error-page' | |||
There was a problem hiding this comment.
Inconsistent quote style: This file uses single quotes while the rest of the codebase (including app/(home)/not-found.tsx) uses double quotes. For consistency, use double quotes throughout.
| import Error from '@/components/ui/error-page' | |
| import Error from "@/components/ui/error-page" |
| title: | ||
| override.title ?? "ShellUI – CLI-first, shadcn-inspired Blazor components", |
There was a problem hiding this comment.
The title extraction logic may not work correctly. When override.title is an object (e.g., { template: "%s | ShellUI", default: "..." }), accessing it directly will not give the expected string. Consider using override.title?.default ?? override.title or handling the case where title is an object with a template property.
| @@ -0,0 +1,64 @@ | |||
| import * as React from "react" | |||
| import { cva, type VariantProps } from "class-variance-authority" | |||
| import { Slot } from "radix-ui" | |||
There was a problem hiding this comment.
The import statement should be import { Slot } from "@radix-ui/react-slot" instead of import { Slot } from "radix-ui". While the "radix-ui" meta-package re-exports all Radix components, using the specific package import is the recommended practice and ensures better tree-shaking and follows the patterns established in the codebase.
| import Error from '@/components/ui/error-page' | ||
|
|
||
| const ErrorPage = () => { | ||
| return <Error /> | ||
| } | ||
|
|
There was a problem hiding this comment.
Inconsistent naming: the component is imported as "Error" but the component in error-page.tsx is exported as default with the name "Error", while in the other not-found.tsx file it's imported as "ErrorPage". The export should be named consistently, preferably as "ErrorPage" to avoid confusion with the built-in Error object.
| import Error from '@/components/ui/error-page' | |
| const ErrorPage = () => { | |
| return <Error /> | |
| } | |
| import ErrorPage from '@/components/ui/error-page' |
| VariantProps<typeof buttonVariants> & { | ||
| asChild?: boolean | ||
| }) { | ||
| const Comp = asChild ? Slot.Root : "button" |
There was a problem hiding this comment.
The usage of Slot.Root is incorrect. When importing from @radix-ui/react-slot, the Slot component itself should be used directly, not Slot.Root. Change line 51 to const Comp = asChild ? Slot : "button".
| const Comp = asChild ? Slot.Root : "button" | |
| const Comp = asChild ? Slot : "button" |
…ges and simplifying the mapping process
This pull request introduces several improvements and new features to the ShellUI project, focusing on enhanced error handling, improved metadata and SEO support, better accessibility and theming for UI components, and the addition of configuration and schema support for the ShellUI CLI. Below are the most important changes grouped by theme:
Error Handling and User Experience:
ErrorPagecomponent (error-page.tsx) and updated bothapp/not-found.tsxandapp/(home)/not-found.tsxto use it, providing a consistent and user-friendly error page across the app. [1] [2] [3]Metadata, SEO, and Analytics:
createMetadatautility and updatingapp/layout.tsxto use it, including improved Open Graph and Twitter metadata, canonical URLs, and extensive keywords for SEO. [1] [2]robots.txtandsitemap.xmlendpoints for improved SEO and crawler support. [1] [2]UI Components and Theming:
InstallAnimationcomponent to usetext-foregroundanddark:text-whiteclasses for better accessibility and theme support, replacing hardcoded color classes. [1] [2] [3] [4] [5] [6] [7] [8]Buttoncomponent usingclass-variance-authorityfor consistent styling and variants.radix-uifor improved UI primitives.Configuration and Schema Support:
schema.json) for validatingshellui.jsonconfiguration files, enhancing CLI usability and editor integration.These changes collectively enhance the developer and user experience, improve SEO and analytics, and lay the groundwork for better customization and maintainability.