Repository: creativetimofficial/ui Branch: main Commit: 20eb87b1f671 Files: 577 Total size: 4.1 MB Directory structure: gitextract_1snzxphn/ ├── .commitlintrc.json ├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .kodiak.toml ├── .prettierignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── apps/ │ └── www/ │ ├── .env.example │ ├── .gitignore │ ├── .prettierignore │ ├── app/ │ │ ├── (app)/ │ │ │ ├── (root)/ │ │ │ │ └── page.tsx │ │ │ ├── blocks/ │ │ │ │ ├── [...categories]/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── docs/ │ │ │ │ ├── [[...slug]]/ │ │ │ │ │ └── page.tsx │ │ │ │ └── layout.tsx │ │ │ ├── layout.tsx │ │ │ └── llm/ │ │ │ └── [[...slug]]/ │ │ │ └── route.ts │ │ ├── (view)/ │ │ │ └── view/ │ │ │ └── [name]/ │ │ │ └── page.tsx │ │ ├── api/ │ │ │ └── r/ │ │ │ └── [name]/ │ │ │ └── route.ts │ │ ├── layout.tsx │ │ ├── llms.txt/ │ │ │ └── route.ts │ │ └── og/ │ │ ├── geist-regular-otf.json │ │ ├── geist-semibold-otf.json │ │ ├── geistmono-regular-otf.json │ │ └── route.tsx │ ├── components/ │ │ ├── active-theme.tsx │ │ ├── analytics.tsx │ │ ├── announcement.tsx │ │ ├── block-display.tsx │ │ ├── block-image.tsx │ │ ├── block-viewer.tsx │ │ ├── blocks-nav.tsx │ │ ├── blur-vignette.tsx │ │ ├── callout.tsx │ │ ├── cards/ │ │ │ ├── activity-goal.tsx │ │ │ ├── calendar.tsx │ │ │ ├── cookie-settings.tsx │ │ │ ├── create-account.tsx │ │ │ ├── forms.tsx │ │ │ ├── index.tsx │ │ │ ├── payment-method.tsx │ │ │ ├── payments.tsx │ │ │ ├── report-issue.tsx │ │ │ ├── share.tsx │ │ │ └── software-purchase.tsx │ │ ├── chart-code-viewer.tsx │ │ ├── chart-copy-button.tsx │ │ ├── chart-display.tsx │ │ ├── chart-toolbar.tsx │ │ ├── charts-nav.tsx │ │ ├── code-block-command.tsx │ │ ├── code-collapsible-wrapper.tsx │ │ ├── code-tabs.tsx │ │ ├── command-menu.tsx │ │ ├── component-preview-tabs.tsx │ │ ├── component-preview.tsx │ │ ├── component-source.tsx │ │ ├── component-wrapper.tsx │ │ ├── components-list.tsx │ │ ├── copy-button.tsx │ │ ├── docs-breadcrumb.tsx │ │ ├── docs-copy-page.tsx │ │ ├── docs-sidebar-cta.tsx │ │ ├── docs-sidebar.tsx │ │ ├── docs-toc.tsx │ │ ├── examples-nav.tsx │ │ ├── examples-preview.tsx │ │ ├── github-link.tsx │ │ ├── icons.tsx │ │ ├── main-nav.tsx │ │ ├── mobile-nav.tsx │ │ ├── mode-switcher.tsx │ │ ├── nav-header.tsx │ │ ├── nav-user.tsx │ │ ├── open-in-v0-button.tsx │ │ ├── page-header.tsx │ │ ├── page-nav.tsx │ │ ├── showcase-masonry.tsx │ │ ├── site-config.tsx │ │ ├── site-footer.tsx │ │ ├── site-header.tsx │ │ ├── tailwind-indicator.tsx │ │ ├── testimonials-section.tsx │ │ ├── theme-provider.tsx │ │ ├── theme-selector.tsx │ │ └── ui/ │ │ ├── accordion.tsx │ │ ├── alert-dialog.tsx │ │ ├── alert.tsx │ │ ├── aspect-ratio.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── calendar.tsx │ │ ├── card.tsx │ │ ├── carousel.tsx │ │ ├── chart.tsx │ │ ├── checkbox.tsx │ │ ├── collapsible.tsx │ │ ├── command.tsx │ │ ├── context-menu.tsx │ │ ├── dialog.tsx │ │ ├── drawer.tsx │ │ ├── dropdown-menu.tsx │ │ ├── form.tsx │ │ ├── hover-card.tsx │ │ ├── input-otp.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── menubar.tsx │ │ ├── navigation-menu.tsx │ │ ├── pagination.tsx │ │ ├── popover.tsx │ │ ├── progress.tsx │ │ ├── radio-group.tsx │ │ ├── resizable.tsx │ │ ├── scroll-area.tsx │ │ ├── select.tsx │ │ ├── separator.tsx │ │ ├── sheet.tsx │ │ ├── sidebar.tsx │ │ ├── skeleton.tsx │ │ ├── slider.tsx │ │ ├── software-purchase-card.tsx │ │ ├── sonner.tsx │ │ ├── switch.tsx │ │ ├── table.tsx │ │ ├── tabs.tsx │ │ ├── textarea.tsx │ │ ├── toggle-group.tsx │ │ ├── toggle.tsx │ │ └── tooltip.tsx │ ├── components.json │ ├── content/ │ │ └── docs/ │ │ ├── (root)/ │ │ │ ├── components.mdx │ │ │ ├── debug-logs.mdx │ │ │ ├── how-it-works.mdx │ │ │ ├── index.mdx │ │ │ ├── meta.json │ │ │ └── registry.mdx │ │ ├── components/ │ │ │ ├── card.mdx │ │ │ ├── index.mdx │ │ │ └── software-purchase-card.mdx │ │ └── meta.json │ ├── docs/ │ │ └── private-registry.md │ ├── eslint.config.mjs │ ├── hooks/ │ │ ├── use-config.ts │ │ ├── use-copy-to-clipboard.ts │ │ ├── use-is-mac.ts │ │ ├── use-layout.tsx │ │ ├── use-media-query.tsx │ │ ├── use-meta-color.ts │ │ ├── use-mobile.ts │ │ ├── use-mounted.ts │ │ └── use-mutation-observer.ts │ ├── lib/ │ │ ├── analytics.ts │ │ ├── auth.ts │ │ ├── blocks.ts │ │ ├── config.ts │ │ ├── events.ts │ │ ├── fonts.ts │ │ ├── highlight-code.ts │ │ ├── registry.ts │ │ ├── rehype.ts │ │ ├── session.ts │ │ ├── source.ts │ │ ├── themes.ts │ │ └── utils.ts │ ├── mdx-components.tsx │ ├── middleware.ts │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.mjs │ ├── public/ │ │ ├── r/ │ │ │ ├── accordion.json │ │ │ ├── account-2fa-01.json │ │ │ ├── account-avatar-upload-01.json │ │ │ ├── account-basic-info-01.json │ │ │ ├── account-change-password-01.json │ │ │ ├── account-integrations-01.json │ │ │ ├── account-notifications-01.json │ │ │ ├── account-sessions-01.json │ │ │ ├── ai-chat-streaming-01.json │ │ │ ├── ai-image-generator-01.json │ │ │ ├── ai-video-generator-01.json │ │ │ ├── alert-dialog.json │ │ │ ├── alert.json │ │ │ ├── all.json │ │ │ ├── aspect-ratio.json │ │ │ ├── avatar.json │ │ │ ├── badge.json │ │ │ ├── billing-information-01.json │ │ │ ├── blocks.json │ │ │ ├── blog-cards-layout-01.json │ │ │ ├── blog-post-preview-tags-01.json │ │ │ ├── blog-rectangular-images-01.json │ │ │ ├── breadcrumb.json │ │ │ ├── button.json │ │ │ ├── calendar.json │ │ │ ├── card-blog.json │ │ │ ├── card-demo.json │ │ │ ├── card-display-01.json │ │ │ ├── card-ecommerce.json │ │ │ ├── card-plain.json │ │ │ ├── card-with-button.json │ │ │ ├── card.json │ │ │ ├── carousel.json │ │ │ ├── chart.json │ │ │ ├── checkbox.json │ │ │ ├── checkout-01.json │ │ │ ├── collapsible.json │ │ │ ├── command.json │ │ │ ├── complex-product-description-01.json │ │ │ ├── contact-sections-01.json │ │ │ ├── contact-sections-02.json │ │ │ ├── contact-sections-03.json │ │ │ ├── contact-sections-04.json │ │ │ ├── contact-sections-05.json │ │ │ ├── contact-sections-06.json │ │ │ ├── contact-sections-07.json │ │ │ ├── contact-sections-08.json │ │ │ ├── contact-sections-09.json │ │ │ ├── contact-sections-10.json │ │ │ ├── contact-sections-11.json │ │ │ ├── contact-sections-12.json │ │ │ ├── contact-sections-13.json │ │ │ ├── contact-sections-14.json │ │ │ ├── contact-sections-15.json │ │ │ ├── context-menu.json │ │ │ ├── cruds-01.json │ │ │ ├── cruds-02.json │ │ │ ├── cruds-03.json │ │ │ ├── dark-product-overview-01.json │ │ │ ├── dialog.json │ │ │ ├── digital-product-overview-01.json │ │ │ ├── drawer.json │ │ │ ├── dropdown-menu.json │ │ │ ├── ecommerce-sections-01.json │ │ │ ├── ecommerce-sections-02.json │ │ │ ├── empty-shopping-cart-01.json │ │ │ ├── faq-left-title-01.json │ │ │ ├── faqs-cards-icons-01.json │ │ │ ├── faqs-grid-01.json │ │ │ ├── faqs-grid-cta-01.json │ │ │ ├── faqs-list-01.json │ │ │ ├── footers-01.json │ │ │ ├── footers-02.json │ │ │ ├── footers-03.json │ │ │ ├── footers-04.json │ │ │ ├── footers-05.json │ │ │ ├── footers-06.json │ │ │ ├── footers-07.json │ │ │ ├── footers-08.json │ │ │ ├── footers-09.json │ │ │ ├── footers-10.json │ │ │ ├── footers-11.json │ │ │ ├── footers-12.json │ │ │ ├── footers-13.json │ │ │ ├── footers-14.json │ │ │ ├── footers-15.json │ │ │ ├── form-card-demo.json │ │ │ ├── form.json │ │ │ ├── grid-ecommerce-01.json │ │ │ ├── highlighted-blog-posts-01.json │ │ │ ├── hover-card.json │ │ │ ├── index.json │ │ │ ├── input-otp.json │ │ │ ├── input.json │ │ │ ├── interactive-product-preview-01.json │ │ │ ├── invoices-01.json │ │ │ ├── label.json │ │ │ ├── large-blog-preview-01.json │ │ │ ├── menubar.json │ │ │ ├── modals-01.json │ │ │ ├── modals-02.json │ │ │ ├── modals-03.json │ │ │ ├── modals-04.json │ │ │ ├── modals-05.json │ │ │ ├── modals-06.json │ │ │ ├── modals-07.json │ │ │ ├── modals-08.json │ │ │ ├── modals-09.json │ │ │ ├── modals-10.json │ │ │ ├── modals-11.json │ │ │ ├── navigation-menu.json │ │ │ ├── order-details-01.json │ │ │ ├── order-history-01.json │ │ │ ├── pagination.json │ │ │ ├── payment-method-01.json │ │ │ ├── popover.json │ │ │ ├── product-description-01.json │ │ │ ├── product-details-01.json │ │ │ ├── product-listing-filters-01.json │ │ │ ├── progress.json │ │ │ ├── promotional-cards-01.json │ │ │ ├── radio-group.json │ │ │ ├── registry.json │ │ │ ├── resizable.json │ │ │ ├── scroll-area.json │ │ │ ├── select.json │ │ │ ├── separator.json │ │ │ ├── sheet.json │ │ │ ├── shopping-cart-01.json │ │ │ ├── sidebar.json │ │ │ ├── simple-blog-content-01.json │ │ │ ├── simple-faq-01.json │ │ │ ├── simple-product-details-01.json │ │ │ ├── skeleton.json │ │ │ ├── slider.json │ │ │ ├── software-purchase-01.json │ │ │ ├── software-purchase-card-demo.json │ │ │ ├── software-purchase-card.json │ │ │ ├── sonner.json │ │ │ ├── style.json │ │ │ ├── styles/ │ │ │ │ └── creative-tim/ │ │ │ │ └── registry.json │ │ │ ├── switch.json │ │ │ ├── table.json │ │ │ ├── tabs.json │ │ │ ├── testimonials-01.json │ │ │ ├── testimonials-02.json │ │ │ ├── testimonials-03.json │ │ │ ├── testimonials-04.json │ │ │ ├── testimonials-05.json │ │ │ ├── testimonials-06.json │ │ │ ├── testimonials-07.json │ │ │ ├── testimonials-08.json │ │ │ ├── testimonials-09.json │ │ │ ├── testimonials-10.json │ │ │ ├── testimonials-11.json │ │ │ ├── testimonials-12.json │ │ │ ├── testimonials-13.json │ │ │ ├── testimonials-14.json │ │ │ ├── testimonials-15.json │ │ │ ├── testimonials-16.json │ │ │ ├── testimonials-17.json │ │ │ ├── textarea.json │ │ │ ├── toggle-group.json │ │ │ ├── toggle.json │ │ │ ├── tooltip.json │ │ │ ├── transaction-history-01.json │ │ │ ├── ui.json │ │ │ ├── use-mobile.json │ │ │ ├── web3-01.json │ │ │ ├── web3-02.json │ │ │ ├── web3-03.json │ │ │ ├── web3-04.json │ │ │ └── web3-05.json │ │ ├── schema/ │ │ │ ├── registry-item.json │ │ │ └── registry.json │ │ ├── schema.json │ │ └── site.webmanifest │ ├── registry/ │ │ ├── __blocks__.json │ │ ├── __index__.tsx │ │ ├── creative-tim/ │ │ │ ├── blocks/ │ │ │ │ ├── account-2fa-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── account-avatar-upload-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── account-basic-info-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── account-change-password-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── account-integrations-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── account-notifications-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── account-sessions-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── ai-chat-streaming-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── ai-image-generator-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── ai-video-generator-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── billing-information-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── blog-cards-layout-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── blog-post-preview-tags-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── blog-rectangular-images-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── card-display-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── checkout-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── complex-product-description-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-02/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-03/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-04/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-05/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-06/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-07/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-08/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-09/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-10/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-11/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-12/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-13/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-14/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── contact-sections-15/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── cruds-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── cruds-02/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── cruds-03/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── dark-product-overview-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── digital-product-overview-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── ecommerce-sections-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── ecommerce-sections-02/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── empty-shopping-cart-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── faq-left-title-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── faqs-cards-icons-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── faqs-grid-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── faqs-grid-cta-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── faqs-list-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-02/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-03/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-04/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-05/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-06/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-07/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-08/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-09/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-10/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-11/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-12/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-13/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-14/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── footers-15/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── grid-ecommerce-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── highlighted-blog-posts-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── interactive-product-preview-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── invoices-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── large-blog-preview-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-02/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-03/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-04/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-05/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-06/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-07/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-08/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-09/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-10/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── modals-11/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── order-details-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── order-history-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── payment-method-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── product-description-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── product-details-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── product-listing-filters-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── promotional-cards-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── shopping-cart-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── simple-blog-content-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── simple-faq-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── simple-product-details-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── software-purchase-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-02/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-03/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-04/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-05/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-06/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-07/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-08/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-09/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-10/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-11/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-12/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-13/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-14/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-15/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-16/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── testimonials-17/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── transaction-history-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── web3-01/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── web3-02/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── web3-03/ │ │ │ │ │ └── page.tsx │ │ │ │ ├── web3-04/ │ │ │ │ │ └── page.tsx │ │ │ │ └── web3-05/ │ │ │ │ └── page.tsx │ │ │ ├── examples/ │ │ │ │ ├── card-blog.tsx │ │ │ │ ├── card-demo.tsx │ │ │ │ ├── card-ecommerce.tsx │ │ │ │ ├── card-plain.tsx │ │ │ │ ├── card-with-button.tsx │ │ │ │ ├── form-card-demo.tsx │ │ │ │ └── software-purchase-card-demo.tsx │ │ │ ├── hooks/ │ │ │ │ └── use-mobile.ts │ │ │ ├── lib/ │ │ │ │ └── utils.ts │ │ │ └── ui/ │ │ │ ├── accordion.tsx │ │ │ ├── alert-dialog.tsx │ │ │ ├── alert.tsx │ │ │ ├── aspect-ratio.tsx │ │ │ ├── avatar.tsx │ │ │ ├── badge.tsx │ │ │ ├── breadcrumb.tsx │ │ │ ├── button-group.tsx │ │ │ ├── button.tsx │ │ │ ├── calendar.tsx │ │ │ ├── card.tsx │ │ │ ├── carousel.tsx │ │ │ ├── chart.tsx │ │ │ ├── checkbox.tsx │ │ │ ├── chip.tsx │ │ │ ├── collapse.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── command.tsx │ │ │ ├── context-menu.tsx │ │ │ ├── dialog.tsx │ │ │ ├── drawer.tsx │ │ │ ├── dropdown-menu.tsx │ │ │ ├── form.tsx │ │ │ ├── hover-card.tsx │ │ │ ├── input-otp.tsx │ │ │ ├── input.tsx │ │ │ ├── label.tsx │ │ │ ├── list.tsx │ │ │ ├── map.tsx │ │ │ ├── menubar.tsx │ │ │ ├── navigation-menu.tsx │ │ │ ├── pagination.tsx │ │ │ ├── popover.tsx │ │ │ ├── progress.tsx │ │ │ ├── radio-group.tsx │ │ │ ├── rating.tsx │ │ │ ├── resizable.tsx │ │ │ ├── scroll-area.tsx │ │ │ ├── select.tsx │ │ │ ├── separator.tsx │ │ │ ├── sheet.tsx │ │ │ ├── sidebar.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── slider.tsx │ │ │ ├── software-purchase-card.tsx │ │ │ ├── sonner.tsx │ │ │ ├── spinner.tsx │ │ │ ├── stepper.tsx │ │ │ ├── switch.tsx │ │ │ ├── table.tsx │ │ │ ├── tabs.tsx │ │ │ ├── textarea.tsx │ │ │ ├── timeline.tsx │ │ │ ├── toggle-group.tsx │ │ │ ├── toggle.tsx │ │ │ └── tooltip.tsx │ │ ├── index.ts │ │ ├── registry-blocks.ts │ │ ├── registry-categories.ts │ │ ├── registry-examples.ts │ │ ├── registry-hooks.ts │ │ ├── registry-lib.ts │ │ └── registry-ui.ts │ ├── registry.json │ ├── scripts/ │ │ ├── build-registry.mts │ │ ├── capture-registry.mts │ │ └── validate-registries.mts │ ├── source.config.ts │ ├── styles/ │ │ ├── globals.css │ │ └── themes.css │ ├── tsconfig.json │ └── tsconfig.scripts.json ├── e2e/ │ ├── auth.login.spec.ts │ ├── auth.logout.spec.ts │ ├── auth.password.spec.ts │ ├── auth.redirects.spec.ts │ ├── auth.refresh-singleton.spec.ts │ ├── auth.register.spec.ts │ └── helpers.ts ├── mock-api/ │ ├── db.json │ ├── package.json │ ├── routes.json │ └── server.js ├── package.json ├── playwright.config.ts ├── pnpm-workspace.yaml ├── postcss.config.cjs ├── prettier.config.cjs ├── skills/ │ ├── README.md │ └── creative-tim-ui/ │ ├── AGENTS.md │ ├── SKILL.md │ └── rules/ │ ├── brand-philosophy.md │ ├── component-patterns.md │ ├── design-brand.md │ ├── hydration-safety.md │ ├── install-blocks.md │ ├── pro-api-key.md │ └── tailwind-rules.md ├── tsconfig.json ├── turbo.json ├── vitest.config.ts └── vitest.workspace.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .commitlintrc.json ================================================ { "extends": ["@commitlint/config-conventional"] } ================================================ FILE: .editorconfig ================================================ # editorconfig.org root = true [*] charset = utf-8 end_of_line = lf indent_size = 2 indent_style = space insert_final_newline = true trim_trailing_whitespace = true ================================================ FILE: .eslintignore ================================================ node_modules/ target/ .next/ build/ dist/ /templates/ /fixtures/ ================================================ FILE: .eslintrc.json ================================================ { "$schema": "https://json.schemastore.org/eslintrc", "root": true, "extends": [ "next/core-web-vitals", "turbo", "prettier", "plugin:tailwindcss/recommended" ], "plugins": ["tailwindcss"], "ignorePatterns": ["**/fixtures/**"], "rules": { "@next/next/no-html-link-for-pages": "off", "tailwindcss/no-custom-classname": "off", "tailwindcss/classnames-order": "error" }, "settings": { "tailwindcss": { "callees": ["cn", "cva"], "config": "tailwind.config.cjs" }, "next": { "rootDir": ["apps/*/"] } }, "overrides": [ { "files": ["*.ts", "*.tsx"], "parser": "@typescript-eslint/parser" } ] } ================================================ FILE: .gitignore ================================================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies node_modules .pnpm-store .pnp .pnp.js # testing coverage # next.js .next/ out/ build # misc .DS_Store *.pem .bmad-core/ .claude/ .cursor/ web-bundles/ .replit replit.md # debug npm-debug.log* yarn-debug.log* yarn-error.log* .pnpm-debug.log* # local env files .env.local .env.development.local .env.test.local .env.production.local # turbo .turbo .contentlayer tsconfig.tsbuildinfo # ide .idea .fleet .vscode REGISTRY_STRUCTURE.md packages/* ================================================ FILE: .kodiak.toml ================================================ # .kodiak.toml version = 1 [merge] automerge_label = "automerge" require_automerge_label = true method = "squash" delete_branch_on_merge = true optimistic_updates = false prioritize_ready_to_merge = true notify_on_conflict = true [merge.message] title = "pull_request_title" body = "pull_request_body" include_pr_number = true body_type = "markdown" strip_html_comments = true ================================================ FILE: .prettierignore ================================================ dist node_modules .next build .contentlayer apps/www/pages/api/registry.json **/fixtures ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing Thanks for your interest in contributing to ui.creative-tim.com. Please take a moment to review this document before submitting your first pull request. We also strongly recommend that you check for open issues and pull requests to see if someone else is working on something similar. If you need any help, feel free to reach out to [Creative Tim](https://creative-tim.com/contact). ## About this repository This repository is a monorepo. - We use [pnpm](https://pnpm.io) and [`workspaces`](https://pnpm.io/workspaces) for development. - We use [Turborepo](https://turbo.build/repo) as our build system. ## Structure This repository is structured as follows: ``` apps └── www ├── app ├── components ├── content └── registry └── creative-tim-ui ├── example └── ui ``` | Path | Description | | --------------------- | ---------------------------------------- | | `apps/www/app` | The Next.js application for the website. | | `apps/www/components` | The React components for the website. | | `apps/www/content` | The content for the website. | | `apps/www/registry` | The registry for the components. | ## Development ### Fork this repo You can fork this repo by clicking the fork button in the top right corner of this page. ### Clone on your local machine ```bash git clone https://github.com/creative-tim/ui.git ``` ### Navigate to project directory ```bash cd ui ``` ### Create a new Branch ```bash git checkout -b my-new-branch ``` ### Install dependencies ```bash pnpm install ``` ### Run a workspace You can use the `pnpm --filter=[WORKSPACE]` command to start the development process for a workspace. #### Examples 1. To run the `creative-tim.com/ui` website: ```bash pnpm dev ``` ## Documentation The documentation for this project is located in the `www` workspace. You can run the documentation locally by running the following command: ```bash pnpm dev ``` Documentation is written using [MDX](https://mdxjs.com). You can find the documentation files in the `apps/www/content/docs` directory. ## Components We use a registry system for developing components. You can find the source code for the components under `apps/www/registry`. The components are organized by styles. ```bash apps └── www └── registry └── creative-tim ├── blocks └── ui ``` When adding or modifying components, please ensure that: 1. You make the changes for every style. 2. You update the documentation. 3. You run `pnpm build:registry` to update the registry. ## Commit Convention Before you create a Pull Request, please check whether your commits comply with the commit conventions used in this repository. When you create a commit we kindly ask you to follow the convention `category(scope or module): message` in your commit message while using one of the following categories: - `feat / feature`: all changes that introduce completely new code or new features - `fix`: changes that fix a bug (ideally you will additionally reference an issue if present) - `refactor`: any code related change that is not a fix nor a feature - `docs`: changing existing or creating new documentation (i.e. README, docs for usage of a lib or cli usage) - `build`: all changes regarding the build of the software, changes to dependencies or the addition of new dependencies - `test`: all changes regarding tests (adding new tests or changing existing ones) - `ci`: all changes regarding the configuration of continuous integration (i.e. github actions, ci system) - `chore`: all changes to the repository that do not fit into any of the above categories e.g. `feat(components): add new prop to the avatar component` If you are interested in the detailed specification you can visit https://www.conventionalcommits.org/ or check out the [Angular Commit Message Guidelines](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines). ## Requests for new components If you have a request for a new component, please open a discussion on GitHub. We'll be happy to help you out. Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests. ================================================ FILE: LICENSE.md ================================================ MIT License Copyright (c) 2025 [Creative Tim](https://www.creative-tim.com/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software "), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ [![Creative Tim UI](https://raw.githubusercontent.com/creativetimofficial/ui/refs/heads/main/apps/www/public/opengraph-image.png)](https://creative-tim.com/ui) # Creative Tim UI [Creative Tim UI](https://creative-tim.com/ui) is a comprehensive component library built on top of [shadcn/ui](https://ui.shadcn.com/) to help you build modern web applications faster. ## Overview Creative Tim UI provides pre-built, customizable React components and blocks designed for building beautiful, production-ready web applications. The CLI makes it easy to add these components to your Next.js project. ## Installation You can use the Creative Tim UI CLI directly with npx, or install it globally: ```bash # Use directly (recommended) npx @creative-tim/ui@latest add # Or using shadcn cli npx shadcn@latest add https://creative-tim.com/ui/r/all.json ``` ## Prerequisites Before using Creative Tim UI, ensure your Next.js project meets these requirements: - **Node.js 18** or later - **shadcn/ui** initialized in your project (npx shadcn@latest init) - **Tailwind CSS** configured ## Usage ### Install All Components Install all available Creative Tim UI components at once: ```bash npx @creative-tim/ui@latest add all ``` This command will: - Set up shadcn/ui if not already configured - Install all Creative Tim UI components to your configured components directory - Add necessary dependencies to your project ### Install Specific Components Install individual components using the `components add` command: ```bash npx @creative-tim/ui@latest add ``` Examples: ```bash # Install the orb component npx @creative-tim/ui@latest add card ``` ### Alternative: Use with shadcn CLI You can also install components using the standard shadcn/ui CLI: ```bash # Install all components npx shadcn@latest add https://creative-tim.com/ui/r/all.json # Install a specific component npx shadcn@latest add https://creative-tim.com/ui/r/button.json ``` All available components can be found [here](https://creative-tim.com/ui/docs/components) or explore a list of example blocks [here](https://creative-tim.com/ui/blocks). ## Blocks Explore our collection of ready-to-use blocks organized by category. Each block is fully customizable and can be added to your project with a single command. ### Application UI
Modals
Modals
5 Blocks
Account
Account
7 Blocks
Billing
Billing
5 Blocks
### Marketing
Testimonial Sections
Testimonial Sections
17 Blocks
Contact Sections
Contact Sections
15 Blocks
Footers
Footers
16 Blocks
FAQs
FAQs
6 Blocks
Blog
Blog
15 Blocks
### Ecommerce UI Ready-to-use blocks for product listings, shopping carts, and checkout flows.
Ecommerce Sections
Ecommerce Sections
14 Blocks
### Web 3.0 Innovative sections built for decentralized applications, blockchain projects, and crypto platforms.
Web 3.0 Cards
Web 3.0 Cards
5 Blocks
## Contributing If you'd like to contribute to Creative Tim UI, please follow these steps: 1. Fork the repository 2. Create a new branch 3. Make your changes to the components in the registry. 4. Open a PR to the main branch. Please read the [contributing guide](/CONTRIBUTING.md). ## Copyrights and Licenses Creative Tim UI is built upon the incredible work of the open source community: - **[shadcn/ui](https://ui.shadcn.com/)** - The documentation structure, registry system, and foundational (atomic) components are from the open source work in shadcn/ui. [MIT License](https://github.com/shadcn-ui/ui/blob/main/LICENSE.md) - **[Material Tailwind](https://material-tailwind.com/v3)** by Creative Tim - The blocks and component designs are inspired by and based on Material Tailwind Framework. [MIT License](https://github.com/creativetimofficial/material-tailwind/blob/main/LICENSE.md) - **[Eleven Labs UI](https://github.com/elevenlabs/elevenlabs-ui)** - General inspiration for the documentation structure and approach of blocks. [MIT License](https://github.com/elevenlabs/ui/blob/main/LICENSE.md) - **[Geist Font](https://vercel.com/font)** by Vercel - The beautiful typeface used throughout the interface. [SIL Open Font License 1.1](https://github.com/vercel/geist-font/blob/main/LICENSE.txt) We are grateful to these projects for making their work available under open source licenses. ## License Licensed under the [MIT license](https://github.com/creativetimofficial/ui/blob/main/LICENSE.md). Made with love by [Creative Tim](https://creative-tim.com). ================================================ FILE: apps/www/.env.example ================================================ # Private Registry Authentication # Set your API key to access private components (testimonials-03, testimonials-04) # Get your API key from: https://creative-tim.com/ui API_KEY=your_api_key_here NEXT_PUBLIC_V0_URL=https://v0.app NEXT_PUBLIC_APP_URL=http://localhost:5000 NEXT_PUBLIC_ASSET_PREFIX = "/ui" NEXT_PUBLIC_VIEW_PATH = "/ui/view" ================================================ FILE: apps/www/.gitignore ================================================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies /node_modules /.pnp .pnp.* .yarn/* !.yarn/patches !.yarn/plugins !.yarn/releases !.yarn/versions # testing /coverage # next.js /.next/ /out/ # production /build # misc .DS_Store *.pem # debug npm-debug.log* yarn-debug.log* yarn-error.log* .pnpm-debug.log* # env files (can opt-in for committing if needed) .env* !.env.example # vercel .vercel # typescript *.tsbuildinfo next-env.d.ts # generated content .contentlayer .content-collections .source ================================================ FILE: apps/www/.prettierignore ================================================ dist node_modules .next build .contentlayer registry/__index__.tsx content/docs/components/calendar.mdx ================================================ FILE: apps/www/app/(app)/(root)/page.tsx ================================================ import { Metadata } from "next" import Link from "next/link" import { Download, Package, Star, Users } from "lucide-react" import { ExamplesNav } from "@/components/examples-nav" import { ExamplesPreview } from "@/components/examples-preview" import { ShowcaseMasonry } from "@/components/showcase-masonry" import { TestimonialsSection } from "@/components/testimonials-section" import { PageActions, PageHeader, PageHeaderDescription, PageHeaderHeading, } from "@/components/page-header" import { PageNav } from "@/components/page-nav" import { ThemeSelector } from "@/components/theme-selector" import { Button } from "@/components/ui/button" import { Card } from "@/components/ui/card" const title = "Creative Tim UI" const description = "Open-source components, blocks, and AI agents designed to speed up your workflow. Import them seamlessly into your favorite tools through Registry and MCPs." export const dynamic = "force-static" export const revalidate = false export const metadata: Metadata = { title, description, openGraph: { images: [ { url: `/og?title=${encodeURIComponent( title )}&description=${encodeURIComponent(description)}`, }, ], }, twitter: { card: "summary_large_image", images: [ { url: `/og?title=${encodeURIComponent( title )}&description=${encodeURIComponent(description)}`, }, ], }, } export default function IndexPage() { const assetPrefix = process.env.NEXT_PUBLIC_ASSET_PREFIX return (
Creative Tim UI {description} {/* Logo Section */}
{/* OpenAI */}
OpenAI
{/* Claude */}
Claude
{/* v0 */}
v0
{/* Replit */}
Replit
{/* Bolt */}
Bolt
{/* Lovable */}
Lovable
{/* Achievements Section */}

Remarkable Achievements

Discover how our UI Tools have transformed web development. These achievements showcase our dedication to innovation and our community's growth.

2.6M+
Community Members

Join our community of developers and designers

8.6M+
Cumulative Downloads

Based on Material Tailwind and Creative Tim Products

48,000+
Github Cumulative Stars

On 100+ Open Source Repositories and Projects

280,000+
Monthly NPM Downloads

Including React, HTML, Tailwind CSS and more.

{/* Examples Preview Section */} {/* Testimonials Section */}
) } ================================================ FILE: apps/www/app/(app)/blocks/[...categories]/page.tsx ================================================ import { getAllBlockIds } from "@/lib/blocks" import { BlockDisplay } from "@/components/block-display" import { registryCategories } from "@/registry/registry-categories" export const revalidate = false export const dynamic = "force-static" export const dynamicParams = false export async function generateStaticParams() { return registryCategories.map((category) => ({ categories: [category.slug], })) } export default async function BlocksPage({ params, }: { params: Promise<{ categories?: string[] }> }) { const { categories = [] } = await params const blocks = await getAllBlockIds(["registry:block"], categories) return (
{blocks.map((name) => ( ))}
) } ================================================ FILE: apps/www/app/(app)/blocks/layout.tsx ================================================ import { Metadata } from "next" import Link from "next/link" import { BlocksNav } from "@/components/blocks-nav" import { PageActions, PageHeader, PageHeaderDescription, PageHeaderHeading, } from "@/components/page-header" import { PageNav } from "@/components/page-nav" import { Button } from "@/components/ui/button" const title = "Blocks" const description = "A collection of building blocks and components made by Creative Tim on top of shadcn/ui." export const metadata: Metadata = { title, description, openGraph: { images: [ { url: `/og?title=${encodeURIComponent( title )}&description=${encodeURIComponent(description)}`, }, ], }, twitter: { card: "summary_large_image", images: [ { url: `/og?title=${encodeURIComponent( title )}&description=${encodeURIComponent(description)}`, }, ], }, } export default function BlocksLayout({ children, }: { children: React.ReactNode }) { return ( <> {title} {description}
{children}
) } ================================================ FILE: apps/www/app/(app)/blocks/page.tsx ================================================ import { BlockDisplay } from "@/components/block-display" export const dynamic = "force-static" export const revalidate = false const FEATURED_BLOCKS = [ "software-purchase-01", "dark-product-overview-01", "web3-04", "account-basic-info-01", "cruds-01", "testimonials-03", ] export default async function BlocksPage() { return (
{FEATURED_BLOCKS.map((name) => ( ))}
) } ================================================ FILE: apps/www/app/(app)/docs/[[...slug]]/page.tsx ================================================ import Link from "next/link" import { notFound } from "next/navigation" import { mdxComponents } from "@/mdx-components" import { IconArrowLeft, IconArrowRight, IconArrowUpRight, } from "@tabler/icons-react" import { findNeighbour } from "fumadocs-core/server" import { source } from "@/lib/source" import { absoluteUrl } from "@/lib/utils" import { DocsCopyPage } from "@/components/docs-copy-page" import { DocsSidebarCta } from "@/components/docs-sidebar-cta" import { DocsTableOfContents } from "@/components/docs-toc" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" export const revalidate = false export const dynamic = "force-static" export const dynamicParams = false export function generateStaticParams() { return source.generateParams() } export async function generateMetadata(props: { params: Promise<{ slug?: string[] }> }) { const params = await props.params const page = source.getPage(params.slug) if (!page) { notFound() } const doc = page.data if (!doc.title || !doc.description) { notFound() } return { title: doc.title, description: doc.description, openGraph: { title: doc.title, description: doc.description, type: "article", url: absoluteUrl(page.url), images: [ { url: `/og?title=${encodeURIComponent( doc.title )}&description=${encodeURIComponent(doc.description)}`, }, ], }, twitter: { card: "summary_large_image", title: doc.title, description: doc.description, images: [ { url: `/og?title=${encodeURIComponent( doc.title )}&description=${encodeURIComponent(doc.description)}`, }, ], creator: "@creativetim", }, } } export default async function Page(props: { params: Promise<{ slug?: string[] }> }) { const params = await props.params const page = source.getPage(params.slug) if (!page) { notFound() } const doc = page.data // @ts-expect-error - revisit fumadocs types. const MDX = doc.body const neighbours = await findNeighbour(source.pageTree, page.url) // @ts-expect-error - revisit fumadocs types. const links = doc.links return (

{doc.title}

{neighbours.previous && ( )} {neighbours.next && ( )}
{doc.description && (

{doc.description}

)}
{links ? (
{links?.doc && ( Docs )} {links?.api && ( API Reference )}
) : null}
{neighbours.previous && ( )} {neighbours.next && ( )}
{/* @ts-expect-error - revisit fumadocs types. */} {doc.toc?.length ? (
{/* @ts-expect-error - revisit fumadocs types. */}
) : null}
) } ================================================ FILE: apps/www/app/(app)/docs/layout.tsx ================================================ import { source } from "@/lib/source" import { DocsSidebar } from "@/components/docs-sidebar" import { SidebarProvider } from "@/components/ui/sidebar" export default function DocsLayout({ children, }: { children: React.ReactNode }) { return (
{children}
) } ================================================ FILE: apps/www/app/(app)/layout.tsx ================================================ import { SiteFooter } from "@/components/site-footer" import { SiteHeader } from "@/components/site-header" export default function AppLayout({ children }: { children: React.ReactNode }) { return (
{children}
) } ================================================ FILE: apps/www/app/(app)/llm/[[...slug]]/route.ts ================================================ import { notFound } from "next/navigation" import { NextResponse, type NextRequest } from "next/server" import { source } from "@/lib/source" export const revalidate = false export async function GET( _req: NextRequest, { params }: { params: Promise<{ slug: string[] }> } ) { const slug = (await params).slug const page = source.getPage(slug) if (!page) { notFound() } // @ts-expect-error - revisit fumadocs types. return new NextResponse(page.data.content, { headers: { "Content-Type": "text/markdown; charset=utf-8", }, }) } export function generateStaticParams() { return source.generateParams() } ================================================ FILE: apps/www/app/(view)/view/[name]/page.tsx ================================================ import * as React from "react" import { Metadata } from "next" import { notFound } from "next/navigation" import { registryItemSchema } from "shadcn/schema" import { z } from "zod" import { siteConfig } from "@/lib/config" import { getRegistryComponent, getRegistryItem } from "@/lib/registry" import { absoluteUrl, cn } from "@/lib/utils" export const revalidate = false export const dynamic = "force-static" export const dynamicParams = false const getCachedRegistryItem = React.cache(async (name: string) => { return await getRegistryItem(name) }) export async function generateMetadata({ params, }: { params: Promise<{ name: string }> }): Promise { const { name } = await params const item = await getCachedRegistryItem(name) if (!item) { return {} } const title = item.name const description = item.description return { title: item.description, description, openGraph: { title, description, type: "article", url: absoluteUrl(`/view/${item.name}`), images: [ { url: siteConfig.ogImage, width: 1200, height: 630, alt: siteConfig.name, }, ], }, twitter: { card: "summary_large_image", title, description, images: [siteConfig.ogImage], creator: "@creativetim", }, } } export async function generateStaticParams() { const { Index } = await import("@/registry/__index__") const index = z.record(registryItemSchema).parse(Index) return Object.values(index) .filter((block) => [ "registry:block", "registry:component", "registry:example", "registry:internal", ].includes(block.type) ) .map((block) => ({ name: block.name, })) } export default async function BlockPage({ params, }: { params: Promise<{ name: string }> }) { const { name } = await params const item = await getCachedRegistryItem(name) const Component = getRegistryComponent(name) if (!item || !Component) { return notFound() } return ( <>
) } ================================================ FILE: apps/www/app/api/r/[name]/route.ts ================================================ import { existsSync, readFileSync } from "fs" import path from "path" import { NextRequest, NextResponse } from "next/server" const PRIVATE_COMPONENTS = ["testimonials-03", "testimonials-04"] export async function GET( request: NextRequest, { params }: { params: Promise<{ name: string }> } ) { const { name: componentName } = await params if (!PRIVATE_COMPONENTS.includes(componentName)) { return NextResponse.json( { error: "Component not found or not private" }, { status: 404 } ) } const authHeader = request.headers.get("authorization") const token = authHeader?.replace("Bearer ", "") const queryToken = request.nextUrl.searchParams.get("token") const apiKey = request.headers.get("x-api-key") const providedToken = token || queryToken || apiKey if (!isValidToken(providedToken)) { return NextResponse.json( { error: "Unauthorized", message: "Authentication required for private components. Set API_KEY in your .env.local file or provide it via Authorization header, X-API-Key header, or ?token= query parameter.", }, { status: 401 } ) } try { const componentPath = path.join( process.cwd(), "public", "r", `${componentName}.json` ) if (!existsSync(componentPath)) { return NextResponse.json( { error: "Component not found" }, { status: 404 } ) } const componentData = readFileSync(componentPath, "utf-8") const component = JSON.parse(componentData) return NextResponse.json(component, { headers: { "Content-Type": "application/json", "Cache-Control": "private, max-age=3600", }, }) } catch (error) { console.error(`Error serving private component ${componentName}:`, error) return NextResponse.json( { error: "Internal server error" }, { status: 500 } ) } } function isValidToken(token: string | null): boolean { if (!token) { return false } const validApiKey = process.env.API_KEY if (!validApiKey) { console.warn( "API_KEY not set in environment variables. Private components will be inaccessible." ) return false } return token === validApiKey } ================================================ FILE: apps/www/app/layout.tsx ================================================ import type { Metadata } from "next" import { META_THEME_COLORS, siteConfig } from "@/lib/config" import { fontVariables } from "@/lib/fonts" import { cn } from "@/lib/utils" import { LayoutProvider } from "@/hooks/use-layout" import { ActiveThemeProvider } from "@/components/active-theme" import { Analytics } from "@/components/analytics" import { TailwindIndicator } from "@/components/tailwind-indicator" import { ThemeProvider } from "@/components/theme-provider" import { Toaster } from "@/components/ui/sonner" import "@/styles/globals.css" export const metadata: Metadata = { title: { default: siteConfig.name, template: `%s | ${siteConfig.name}`, }, metadataBase: new URL(process.env.NEXT_PUBLIC_APP_URL!), description: siteConfig.description, keywords: ["Creative Tim", "UI", "shadcn", "Components", "agents"], authors: [ { name: "Creative Tim", url: "https://creative-tim.com", }, ], creator: "creative-tim", openGraph: { type: "website", locale: "en_US", url: process.env.NEXT_PUBLIC_APP_URL! + process.env.NEXT_PUBLIC_ASSET_PREFIX, title: siteConfig.name, description: siteConfig.description, siteName: siteConfig.name, images: [ { url: `${process.env.NEXT_PUBLIC_APP_URL}${process.env.NEXT_PUBLIC_ASSET_PREFIX}/opengraph-image.png`, width: 1200, height: 630, alt: siteConfig.name, }, ], }, twitter: { card: "summary_large_image", title: siteConfig.name, description: siteConfig.description, images: [ `${process.env.NEXT_PUBLIC_APP_URL}${process.env.NEXT_PUBLIC_ASSET_PREFIX}/opengraph-image.png`, ], creator: "@creativetim", }, icons: { icon: `${process.env.NEXT_PUBLIC_APP_URL}${process.env.NEXT_PUBLIC_ASSET_PREFIX}/favicon.ico`, shortcut: `${process.env.NEXT_PUBLIC_APP_URL}${process.env.NEXT_PUBLIC_ASSET_PREFIX}/favicon-16x16.png`, apple: `${process.env.NEXT_PUBLIC_APP_URL}${process.env.NEXT_PUBLIC_ASSET_PREFIX}/apple-touch-icon.png`, }, manifest: `${process.env.NEXT_PUBLIC_APP_URL}${process.env.NEXT_PUBLIC_ASSET_PREFIX}/site.webmanifest`, } export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode }>) { return ( )} {/* If you also want Vercel Analytics, uncomment the import above and add here. */} ) } ================================================ FILE: apps/www/components/announcement.tsx ================================================ import Link from "next/link" import { ArrowRightIcon } from "lucide-react" import { Badge } from "@/components/ui/badge" export function Announcement() { return ( Insert Announcement here ) } ================================================ FILE: apps/www/components/block-display.tsx ================================================ import * as React from "react" import { registryItemFileSchema } from "shadcn/schema" import { z } from "zod" import { highlightCode } from "@/lib/highlight-code" import { createFileTreeForRegistryItemFiles, getRegistryItem, } from "@/lib/registry" import { cn } from "@/lib/utils" import { BlockViewer } from "@/components/block-viewer" import { ComponentPreview } from "@/components/component-preview" export async function BlockDisplay({ name }: { name: string }) { const item = await getCachedRegistryItem(name) if (!item?.files) { return null } const [tree, highlightedFiles] = await Promise.all([ getCachedFileTree(item.files), getCachedHighlightedFiles(item.files), ]) return ( .p-6]:p-0", item.meta?.containerClassName )} /> ) } const getCachedRegistryItem = React.cache(async (name: string) => { return await getRegistryItem(name) }) const getCachedFileTree = React.cache( async (files: Array<{ path: string; target?: string }>) => { if (!files) { return null } return await createFileTreeForRegistryItemFiles(files) } ) const getCachedHighlightedFiles = React.cache( async (files: z.infer[]) => { return await Promise.all( files.map(async (file) => ({ ...file, highlightedContent: await highlightCode(file.content ?? ""), })) ) } ) ================================================ FILE: apps/www/components/block-image.tsx ================================================ import Image from "next/image" import { cn } from "@/lib/utils" export function BlockImage({ name, width = 1440, height = 900, className, }: Omit, "src" | "alt"> & { name: string }) { return (
{name} {name}
) } ================================================ FILE: apps/www/components/block-viewer.tsx ================================================ "use client" import * as React from "react" import Image from "next/image" import Link from "next/link" import { Check, ChevronRight, Clipboard, File, Folder, Fullscreen, Monitor, RotateCw, Smartphone, Tablet, Terminal, } from "lucide-react" import { ImperativePanelHandle } from "react-resizable-panels" import { registryItemFileSchema, registryItemSchema } from "shadcn/schema" import { z } from "zod" import { trackEvent } from "@/lib/events" import { createFileTreeForRegistryItemFiles, FileTree } from "@/lib/registry" import { cn } from "@/lib/utils" import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard" import { getIconForLanguageExtension } from "@/components/icons" import { OpenInV0Button } from "@/components/open-in-v0-button" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible" import { ResizableHandle, ResizablePanel, ResizablePanelGroup, } from "@/components/ui/resizable" import { Separator } from "@/components/ui/separator" import { Sidebar, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarProvider, } from "@/components/ui/sidebar" import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs" import { ToggleGroup, ToggleGroupItem, } from "@/components/ui/toggle-group" type BlockViewerContext = { item: z.infer view: "code" | "preview" setView: (view: "code" | "preview") => void activeFile: string | null setActiveFile: (file: string) => void resizablePanelRef: React.RefObject | null tree: ReturnType | null highlightedFiles: | (z.infer & { highlightedContent: string })[] | null iframeKey?: number setIframeKey?: React.Dispatch> } const BlockViewerContext = React.createContext(null) function useBlockViewer() { const context = React.useContext(BlockViewerContext) if (!context) { throw new Error("useBlockViewer must be used within a BlockViewerProvider.") } return context } function BlockViewerProvider({ item, tree, highlightedFiles, children, }: Pick & { children: React.ReactNode }) { const [view, setView] = React.useState("preview") const [activeFile, setActiveFile] = React.useState< BlockViewerContext["activeFile"] >(highlightedFiles?.[0].target ?? null) const resizablePanelRef = React.useRef(null) const [iframeKey, setIframeKey] = React.useState(0) return (
{children}
) } function BlockViewerToolbar() { const { setView, view, item, resizablePanelRef, setIframeKey } = useBlockViewer() const { copyToClipboard, isCopied } = useCopyToClipboard() // const viewPath = process.env.NEXT_PUBLIC_VIEW_PATH || "/view" return (
{/* Title and Description Section */}
{item.meta?.details && (

{item.meta.details}

)}
{/* Controllers Section */}
{/* {isPro && !hasAccess ? ( ) : ( */} {/* )} */}
{ setView("preview") if (resizablePanelRef?.current) { resizablePanelRef.current.resize(parseInt(value)) } }} className="gap-1 *:data-[slot=toggle-group-item]:!size-6 *:data-[slot=toggle-group-item]:!rounded-sm" >
setView(value as "preview" | "code")} > Preview {/* */} Code
) } function BlockViewerIframe({ className }: { className?: string }) { const { item, iframeKey } = useBlockViewer() const viewPath = process.env.NEXT_PUBLIC_VIEW_PATH || "/view" return (