Building a Sitecore XM Cloud Component Creator: My Second Hackathon Experience
A few weeks ago, I participated in my second Sitecore Hackathon with team "404 Bugs Not Found". Our mission? Create a VSCode extension that streamlines component creation and deployment in Sitecore XM Cloud. Here's a deep dive into our technical solution.
The Technical Challenge
Sitecore XM Cloud development involves several manual steps when creating components:
- Creating the component's TSX/JSX file
- Setting up the component's template in Sitecore
- Creating placeholder settings
- Configuring the component rendering
- Linking everything together
We aimed to automate this entire process through a VSCode extension.
Core Technical Features
1. Interactive UI with WebView
We created a sophisticated form interface using VSCode's WebView API. Here's a snippet of our form structure:
<div class="form-group">
<label for="componentName">Component Name</label>
<input required type="text" id="componentName" placeholder="Enter component name">
</div>
<div class="form-group">
<label for="componentType">Component Type</label>
<select id="componentType">
<option value="none">None</option>
<option value="withDatasourceCheck">With Datasource Check</option>
<option value="withDatasourceRendering">With Datasource Rendering</option>
</select>
</div>
2. Dynamic Field Management
One of our most interesting features is the dynamic field management system:
function addField() {
const fieldsContainer = document.getElementById('fields');
const fieldRow = document.createElement('div');
fieldRow.className = 'field-row';
fieldRow.innerHTML = `
<input type="text" placeholder="Field name" required>
<select>
<option value="SingleLineText">Single Line Text</option>
<option value="RichText">Rich Text Field</option>
<option value="LinkField">Link Field</option>
<option value="ImageField">Image Field</option>
<option value="Checkbox">Checkbox</option>
<option value="MultilineText">Multiline Text</option>
</select>
<div class="checkbox-wrapper">
<input type="checkbox" id="required-${fieldCount}">
<label for="required-${fieldCount}">Required</label>
</div>
<button onclick="this.parentElement.remove()" title="Remove field">×</button>
`;
fieldsContainer.appendChild(fieldRow);
}
3. GraphQL Integration
The most challenging part was integrating with Sitecore's GraphQL API. Here's our template creation mutation:
mutation {
createItemTemplate(
input: {
name: "${templateName}",
parent: "${templateParent}",
createStandardValuesItem: true,
sections: {
name: "Content",
fields: [
{
name: "${field.label}",
type: "${field.value === "RichText" ? "Rich Text" : field.value}",
required: ${field.isRequired}
}
]
}
}
) {
itemTemplate {
templateId
name
ownFields {
nodes {
name
type
}
}
}
}
}
4. Placeholder Management
We implemented a sophisticated placeholder system that handles both static and dynamic placeholders:
function updatePlaceholderKey(select) {
const row = select.closest('.placeholder-row');
const keyInput = row.querySelectorAll('input[type="text"]')[1];
const currentKey = keyInput.value;
if (select.value === 'dynamic') {
if (!currentKey.endsWith('-{*}')) {
keyInput.value = currentKey + '-{*}';
}
} else {
if (currentKey.endsWith('-{*}')) {
keyInput.value = currentKey.slice(0, -4);
}
}
}
5. Rendering Creation
The final piece was creating the rendering with proper placeholder references:
const renderingQuery = `
mutation {
createItem(
input: {
name: "${sitecoreName}",
templateId: "{04646A89-996F-4EE7-878A-FFDBF1F0EF0D}",
parent: "${renderingParent}",
language: "en",
fields: [
{ name: "componentName", value: "${codeName}" }
${placeholderIds.length > 0
? `, { name: "Placeholders", value: "${placeholderIds.join("|")}" }`
: ""
}
]
}
) {
item {
itemId
name
path
}
}
}`;
Technical Challenges Overcome
- Field Type Mapping: We had to carefully map our field types to Sitecore's expected formats:
switch (field.value) {
case "RichText":
return "Rich Text";
case "SingleLineText":
return "Single-Line Text";
case "MultilineText":
return "Multi-Line Text";
case "ImageField":
return "Image";
case "LinkField":
return "General Link";
case "Checkbox":
return "Checkbox";
default:
return field.value;
}
Placeholder Reference Management: Ensuring proper linking between placeholders and renderings required careful handling of IDs and proper mutation ordering.
Type Safety: Implementing proper TypeScript interfaces and type checking throughout the extension.
Future Technical Enhancements
- Support for more complex field types and configurations
- Enhanced template inheritance capabilities
- Integration with Sitecore CLI
- Support for component variants
- Automated testing infrastructure
Conclusion
This hackathon pushed us to create a solution that not only works but is also maintainable and extensible. The combination of VSCode's WebView API, TypeScript's type safety, and Sitecore's GraphQL API allowed us to create a tool that significantly improves the developer experience.
The code is open source and available for the community to use and enhance. We're looking forward to seeing how it evolves and helps other Sitecore developers streamline their workflow.
Are you interested in contributing to this project? Check out our repository and let's make Sitecore development even better together!
Top comments (0)