Skip to content

Conversation

@TRomesh
Copy link
Contributor

@TRomesh TRomesh commented Oct 16, 2025

This template is 75% complete. The remaining features can be implemented once the tasks in CMS-46339 are resolved.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds a new alloy-template to the templates directory, providing a Next.js-based starter template for Optimizely CMS projects. The template includes pre-configured components, TypeScript configuration, and Tailwind CSS styling.

  • Adds a complete Next.js 15.5.4 template with React 19.1.0
  • Includes various reusable CMS components (Teaser, Notice, Contact, etc.)
  • Configures TypeScript, Tailwind CSS v4, and PostCSS
  • Updates workspace configuration to include the templates directory

Reviewed Changes

Copilot reviewed 28 out of 36 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
templates/alloy-template/package.json Defines project dependencies including Next.js, React 19, and Tailwind CSS v4
templates/alloy-template/tsconfig.json TypeScript configuration with Next.js and bundler module resolution
templates/alloy-template/src/components/*.tsx Component files for Teaser, Notice, Contact, Editorial, Article, and other CMS content types
templates/alloy-template/src/components/Start.tsx Start page component with composition support
templates/alloy-template/src/app/*.tsx Next.js app router pages including layout, dynamic routes, and preview
templates/alloy-template/next.config.ts Next.js configuration for remote image patterns
pnpm-workspace.yaml Updated to include templates directory in workspace
pnpm-lock.yaml Lock file updated with new template dependencies
Files not reviewed (2)
  • pnpm-lock.yaml: Language not supported
  • templates/alloy-template/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

type: 'string',
displayName: 'Page Description',
},
disable_indexing: {
Copy link
Contributor

Choose a reason for hiding this comment

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

SEO properties should probably be grouped into a block/component. Then use the block as a property on page types. Might make more sense to define them in a contract when we have that support, but until then a block property makes sense.

We have both title and site_title. Same with description.

displayName: 'Button Link',
group: 'Information',
},
button_text: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this button really needed? If yes, then define it as a block/compontent and use it as a block property rather than two separate properties here.

@CLAassistant
Copy link

CLAassistant commented Nov 11, 2025

CLA assistant check
All committers have signed the CLA.

@TRomesh TRomesh requested a review from Copilot November 11, 2025 07:56
Copilot finished reviewing on behalf of TRomesh November 11, 2025 07:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 28 out of 36 changed files in this pull request and generated 5 comments.

Files not reviewed (2)
  • pnpm-lock.yaml: Language not supported
  • templates/alloy-template/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,52 @@
import { contentType } from '@optimizely/cms-sdk';

const PageList = contentType({
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The PageList component only defines the content type but doesn't export a React component for rendering. Either export the content type definition or add a corresponding React component that renders the page list.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +9
interface HeaderProps {
currentPath: any;
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The currentPath prop uses any type which defeats TypeScript's type safety. Define a proper interface for the currentPath structure, e.g., currentPath: { children?: any[]; ancestors?: Array<{ _metadata: { displayName: string; url: { hierarchical: string } } }> }.

Copilot uses AI. Check for mistakes.
<div className="md:w-1/2 h-64 md:h-auto overflow-hidden">
<img
src={opti.image?.url.default}
alt="teaser_image"
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The alt text 'teaser_image' is not descriptive. Use the heading or text content as alt text for better accessibility, e.g., alt={opti.heading || 'Teaser image'}.

Copilot uses AI. Check for mistakes.
{/* Heading and Description */}
<div className="space-y-4">
<h1
{...pa('title')}
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The preview attribute is set to 'title' but the actual property being displayed is opti.heading. This should be {...pa('heading')} to match the property name defined in the content type.

Suggested change
{...pa('title')}
{...pa('heading')}

Copilot uses AI. Check for mistakes.
Comment on lines +111 to +115
<OptimizelyExperience
nodes={opti.composition.nodes ?? []}
ComponentWrapper={ComponentWrapper}
/>
</div>
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The OptimizelyExperience component is placed inside the sidebar div but appears after the closing tag of the sidebar. It should be moved outside the grid container or properly nested within the layout structure.

Suggested change
<OptimizelyExperience
nodes={opti.composition.nodes ?? []}
ComponentWrapper={ComponentWrapper}
/>
</div>
</div>
<OptimizelyExperience
nodes={opti.composition.nodes ?? []}
ComponentWrapper={ComponentWrapper}
/>

Copilot uses AI. Check for mistakes.
graphUrl: process.env.OPTIMIZELY_GRAPH_URL,
});
const path = `/${slug.join('/')}/`;
const c = await client.getContentByPath(path);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const c = await client.getContentByPath(path);
const pages = await client.getContentByPath(path);


return (
<>
<Header currentPath={{ children, ancestors }} />
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it make more sense to let this component load its own data?

currentPath?: string;
}

const defaultSections: FooterSection[] = [
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have a follow-up story to implement these as link lists in CMS?

logoText?: string;
}

const defaultNavigationItems: NavigationItem[] = [
Copy link
Contributor

Choose a reason for hiding this comment

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

Now when we have getItems() we should be able to load these items from the CMS.

type: 'richText',
displayName: 'Main Body',
},
// SEO group
Copy link
Contributor

Choose a reason for hiding this comment

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

Move these SEO properties to component/block and re-use them as a property on each page type.

displayName: 'Main Body',
},
// SEO group
site_title: {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the difference between this property and title?

displayName: 'Keywords',
group: 'SEO',
},
page_description: {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the difference between this property and discription?

displayName: 'Content Area',
},
// SEO group
site_title: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here...

displayName: 'Main Body',
},
// SEO group
site_title: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here...

key: 'Standard',
displayName: 'Standard Page',
baseType: '_experience',
mayContainTypes: ['_self', 'News'], // Passed 'News' as a string to avoid circular dependency
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the comment still true?

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