Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 73 additions & 16 deletions registries/marketplace/react/registry.json
Original file line number Diff line number Diff line change
@@ -1,53 +1,110 @@
{
"$schema": "https://ui.shadcn.com/schema/registry.json",
"name": "sitecore marketplace",
"name": "Sitecore Marketplace",
"homepage": "https://blok.sitecore.com",
"items": [
{
"name": "quickstart",
"type": "registry:block",
"title": "Quickstart for React SPA Sitecore marketplace apps with marketplace sdk",
"description": "A quickstart for next.js Sitecore marketplace apps with marketplace sdk",
"title": "Quickstart for React/Vite Sitecore Marketplace apps",
"description": "A quickstart for React/Vite Sitecore Marketplace apps with the Marketplace SDK",
"dependencies": ["@sitecore-marketplace-sdk/client"],
"registryDependencies": [
"https://blok.sitecore.com/r/badge.json",
"https://blok.sitecore.com/r/card.json",
"https://blok.sitecore.com/r/collapsible.json"
],
"files": [
{
"path": "src/marketplace/react/components/providers/marketplace.tsx",
"type": "registry:file",
"target": "app/providers/marketplace.tsx"
"type": "registry:component",
"target": "components/providers/marketplace.tsx"
},
{
"path": "src/marketplace/react/components/examples/example.tsx",
"type": "registry:file",
"path": "src/marketplace/react/components/examples/built-in-auth/application-context.tsx",
"type": "registry:component",
"target": "components/examples/built-in-auth/application-context.tsx"
},
{
"path": "src/marketplace/react/components/examples/built-in-auth/example.tsx",
"type": "registry:page",
"target": "app/page.tsx"
}
]
},
{
"name": "quickstart-with-xmc",
"type": "registry:block",
"title": "Examples for React SPA Sitecore marketplace apps with marketplace sdk",
"description": "Examples for next.js Sitecore marketplace apps with marketplace sdk",
"title": "Quickstart for React/Vite with XMC API examples",
"description": "A quickstart for React/Vite Sitecore Marketplace apps with XMC client-side API examples",
"dependencies": ["@sitecore-marketplace-sdk/xmc"],
"registryDependencies": [
"https://blok.sitecore.com/r/marketplace/react/quickstart.json"
"https://blok.sitecore.com/r/marketplace/react/quickstart.json",
"https://blok.sitecore.com/r/button.json",
"https://blok.sitecore.com/r/alert.json",
"https://blok.sitecore.com/r/skeleton.json",
"https://blok.sitecore.com/r/separator.json"
],
"files": [
{
"path": "src/marketplace/react/components/providers/marketplace-w-xmc.tsx",
"type": "registry:file",
"type": "registry:component",
"target": "components/providers/marketplace.tsx"
},
{
"path": "src/marketplace/react/components/examples/with-xmc/list-languages.tsx",
"type": "registry:file",
"target": "components/examples/with-xmc/list-languages.tsx"
"path": "src/marketplace/react/components/examples/built-in-auth/with-xmc/list-languages.tsx",
"type": "registry:component",
"target": "components/examples/built-in-auth/with-xmc/list-languages.tsx"
},
{
"path": "src/marketplace/react/components/examples/with-xmc/example.tsx",
"type": "registry:file",
"path": "src/marketplace/react/components/examples/built-in-auth/with-xmc/example.tsx",
"type": "registry:page",
"target": "app/page.tsx"
}
]
},
{
"name": "quickstart-with-custom-auth",
"type": "registry:block",
"title": "Quickstart for React/Vite with Auth0 SPA",
"description": "Auth0 client-side authentication for Sitecore Marketplace apps on Vite. This is SPA auth only—no Next.js middleware, route handlers, or server sessions.",
"dependencies": ["@auth0/auth0-react"],
"registryDependencies": [
"https://blok.sitecore.com/r/marketplace/react/quickstart.json"
],
"files": [
{
"path": "src/marketplace/react/vite-env.d.ts",
"type": "registry:file",
"target": "vite-env.d.ts"
},
{
"path": "src/marketplace/react/lib/auth/env.ts",
"type": "registry:file",
"target": "lib/auth/env.ts"
},
{
"path": "src/marketplace/react/components/providers/auth.tsx",
"type": "registry:component",
"target": "components/providers/auth.tsx"
},
{
"path": "src/marketplace/react/components/providers/with-custom-auth.tsx",
"type": "registry:component",
"target": "components/providers/with-custom-auth.tsx"
}
],
"envVars": {
"VITE_AUTH0_DOMAIN": "https://auth.sitecorecloud.io",
"VITE_AUTH0_AUDIENCE": "https://api-webapp.sitecorecloud.io",
"VITE_AUTH0_SCOPE": "openid profile email offline_access",
"VITE_AUTH0_CLIENT_ID": "your-marketplace-client-id",
"VITE_SITECORE_APP_ID": "your-app-id",
"VITE_APP_BASE_URL": "https://localhost:5173",
"VITE_SITECORE_ORGANIZATION_ID": "your-organization-id",
"VITE_SITECORE_TENANT_ID": "marketplace-app-tenant-id-after-installation"
},
"docs": "Use HTTPS in development (e.g. vite-plugin-mkcert or a reverse proxy). Wrap your root with MarketplaceAppProvidersWithCustomAuth from components/providers/with-custom-auth instead of MarketplaceProvider alone. Set all VITE_* variables in .env. XMC examples in this registry use the Marketplace SDK from the browser only (quickstart-with-xmc); there is no server-side or backend-proxy block."
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useAppContext } from "@/components/providers/marketplace";
import { Badge } from "@/components/ui/badge";
import { CardTitle } from "@/components/ui/card";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { ChevronDown, ChevronRight } from "lucide-react";
import { useState } from "react";

export const ApplicationContext = () => {
const appContext = useAppContext();
const [isExpanded, setIsExpanded] = useState(false);
return (
<Collapsible
open={isExpanded}
onOpenChange={setIsExpanded}
className="border-[1px] rounded-lg"
>
<CollapsibleTrigger asChild>
<div className="flex items-center justify-between cursor-pointer hover:bg-muted/50 p-6 rounded-t-lg transition-colors">
<div className="flex items-center gap-2">
<CardTitle className="flex items-center gap-2">
Application Context
</CardTitle>
<Badge colorScheme="primary">Client-side</Badge>
<Badge colorScheme={"success"}>SDK Built-in Auth</Badge>
</div>
{isExpanded ? (
<ChevronDown className="h-4 w-4 transition-transform" />
) : (
<ChevronRight className="h-4 w-4 transition-transform" />
)}
</div>
</CollapsibleTrigger>
<CollapsibleContent>
<pre className="bg-muted p-4 rounded-md text-sm overflow-auto">
{JSON.stringify(appContext, null, 2)}
</pre>
</CollapsibleContent>
</Collapsible>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ApplicationContext } from "@/components/examples/built-in-auth/application-context";

function Examples() {
return (
<div className="container mx-auto p-6 space-y-8 max-w-3xl">
<div className="space-y-4">
<h1 className="text-3xl font-semibold tracking-tight">
Marketplace SDK Demo
</h1>
<p className="text-muted-foreground">
Marketplace SDK with built-in authentication
</p>
</div>

<ApplicationContext />
</div>
);
}

export default Examples;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ApplicationContext } from "@/components/examples/built-in-auth/application-context";
import { ListLanguagesFromClientSdk } from "@/components/examples/built-in-auth/with-xmc/list-languages";
import { Separator } from "@/components/ui/separator";

function Examples() {
return (
<div className="container mx-auto p-6 space-y-8 max-w-3xl">
<div className="space-y-4">
<h1 className="text-3xl font-semibold tracking-tight">
Marketplace SDK Demo
</h1>
<p className="text-muted-foreground">
Marketplace SDK with built-in authentication and XMC client-side
examples
</p>
</div>

<ApplicationContext />

<Separator />

<div className="space-y-6">
<h2 className="text-2xl font-semibold">Built-in Auth Examples</h2>
<div className="grid gap-6">
<ListLanguagesFromClientSdk />
</div>
</div>
</div>
);
}

export default Examples;
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
useAppContext,
useMarketplaceClient,
} from "@/components/providers/marketplace";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import type { Xmapp } from "@sitecore-marketplace-sdk/xmc";
import { useState } from "react";

export const ListLanguagesFromClientSdk = () => {
const client = useMarketplaceClient();
const appContext = useAppContext();
const [languages, setLanguages] = useState<Xmapp.Language[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

const fetchLanguages = async () => {
setLoading(true);
setError(null);

const contextId = appContext?.resourceAccess?.[0]?.context
?.preview as string;
if (!contextId) {
setError("No context ID available");
setLoading(false);
return;
}

const data = {
query: {
sitecoreContextId: contextId,
},
};

try {
const languagesResponse = await client.query("xmc.sites.listLanguages", {
params: data,
});
console.log("languages from client", languagesResponse);
setLanguages(languagesResponse.data?.data ?? []);
} catch (err) {
console.log("error from client", err);
setError(err instanceof Error ? err.message : "An error occurred");
} finally {
setLoading(false);
}
};

return (
<Card style={"outline"}>
<CardHeader>
<CardTitle className="flex items-center gap-2">
Client SDK Example
<Badge colorScheme={"primary"}>Client-side</Badge>
<Badge colorScheme={"success"}>SDK Built-in Auth</Badge>
</CardTitle>
<CardDescription>
Fetch languages using Sitecore Marketplace SDK from client component
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<Button
onClick={fetchLanguages}
disabled={loading}
className="w-full sm:w-auto"
>
{loading ? "Fetching..." : "Fetch Languages"}
</Button>

{error && (
<Alert variant="danger">
<AlertDescription>{error}</AlertDescription>
</Alert>
)}

<div className="space-y-2">
<div className="flex items-center gap-2">
<span className="text-sm font-medium">Languages found:</span>
{loading ? (
<Skeleton className="h-5 w-8" />
) : (
<Badge>{languages?.length || 0}</Badge>
)}
</div>

{languages.length > 0 && (
<div className="space-y-1">
<p className="text-sm text-muted-foreground">Language names:</p>
<div className="flex flex-wrap gap-1">
{languages.map((language, index) => (
<Badge key={index}>{language.name}</Badge>
))}
</div>
</div>
)}
</div>
</CardContent>
</Card>
);
};
14 changes: 1 addition & 13 deletions src/marketplace/react/components/examples/example.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1 @@
import { useAppContext } from "@/components/providers/marketplace";

function ClientSideExamples() {
const appContext = useAppContext();
return (
<div>
<div>Application Context</div>
<div>{JSON.stringify(appContext)}</div>
</div>
);
}

export default ClientSideExamples;
export { default } from "@/components/examples/built-in-auth/example";
18 changes: 1 addition & 17 deletions src/marketplace/react/components/examples/with-xmc/example.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1 @@
import { ListLanguagesFromClientSdk } from "@/components/examples/with-xmc/list-languages";
import { useAppContext } from "@/components/providers/marketplace";

function ClientSideExamples() {
const appContext = useAppContext();
return (
<div>
<div>Application Context</div>
<div>{JSON.stringify(appContext)}</div>
<br />
<div>Different ways to call XMC APIs from the browser</div>
<ListLanguagesFromClientSdk />
</div>
);
}

export default ClientSideExamples;
export { default } from "@/components/examples/built-in-auth/with-xmc/example";
Loading
Loading