├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENCE.md ├── README.md ├── apps └── www │ ├── .eslintrc.json │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc │ ├── LICENCE.md │ ├── README.md │ ├── app │ ├── (categories) │ │ └── [...slug] │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── examples │ │ ├── about │ │ │ └── one │ │ │ │ └── page.tsx │ │ ├── contact │ │ │ └── one │ │ │ │ └── page.tsx │ │ ├── home │ │ │ └── one │ │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ └── pricing │ │ │ └── one │ │ │ └── page.tsx │ ├── globals.css │ ├── icon.svg │ ├── layout.tsx │ ├── mist │ │ ├── opengraph-image.png │ │ ├── page.tsx │ │ └── twitter-image.png │ ├── og │ │ └── route.tsx │ ├── opengraph-image.png │ ├── page.tsx │ ├── preview │ │ └── [[...slug]] │ │ │ ├── block-renderer.tsx │ │ │ └── page.tsx │ ├── robots.ts │ ├── sitemap.ts │ ├── snippets │ │ ├── button │ │ │ └── page.tsx │ │ └── layout.tsx │ └── twitter-image.png │ ├── components.json │ ├── components │ ├── active-category-links.tsx │ ├── block-preview │ │ ├── iframe-renderer.tsx │ │ ├── index.tsx │ │ ├── loading-spinner.tsx │ │ ├── mcp-logo.tsx │ │ ├── open-in-v0.tsx │ │ ├── state.ts │ │ ├── toolbar.tsx │ │ ├── tooltip-button.tsx │ │ └── useOptimizedIframe.ts │ ├── blocks-nav.tsx │ ├── category-not-found.tsx │ ├── category-scroll-manager.tsx │ ├── code-block.tsx │ ├── code-editor.tsx │ ├── dev │ │ └── CacheControl.tsx │ ├── ex-features.tsx │ ├── ex-footer.tsx │ ├── ex-header.tsx │ ├── kit-switcher.tsx │ ├── logo.tsx │ ├── service-worker-init.tsx │ ├── site-footer.tsx │ ├── site-header.tsx │ ├── snippet-preview.tsx │ ├── snippets │ │ └── buttons │ │ │ └── button.tsx │ ├── theme-provider.tsx │ ├── theme-toggle.tsx │ └── toolbar.tsx │ ├── data │ └── blocks.ts │ ├── eslint.config.mjs │ ├── hooks │ └── useClipboard.ts │ ├── lib │ ├── get-kits.ts │ ├── get-og-url.ts │ ├── serviceWorker.ts │ └── utils.ts │ ├── middleware.ts │ ├── mist-registry.json │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ ├── card.png │ ├── charts-light.png │ ├── charts.png │ ├── dark-card.webp │ ├── exercice-dark.png │ ├── exercice.png │ ├── mail-back-light.png │ ├── mail-back.png │ ├── mail-upper.png │ ├── mail2-light.png │ ├── mail2.png │ ├── mist │ │ ├── tailark-2.png │ │ ├── tailark-3.png │ │ └── tailark.png │ ├── music-light.png │ ├── music.png │ ├── origin-cal-dark.png │ ├── origin-cal.png │ ├── payments-light.png │ ├── payments.png │ ├── r │ │ ├── call-to-action-1.json │ │ ├── call-to-action-2.json │ │ ├── call-to-action-3.json │ │ ├── comparator-1.json │ │ ├── contact-1.json │ │ ├── contact-2.json │ │ ├── content-1.json │ │ ├── content-2.json │ │ ├── content-3.json │ │ ├── content-4.json │ │ ├── content-5.json │ │ ├── content-6.json │ │ ├── content-7.json │ │ ├── faqs-1.json │ │ ├── faqs-2.json │ │ ├── faqs-3.json │ │ ├── faqs-4.json │ │ ├── features-1.json │ │ ├── features-10.json │ │ ├── features-11.json │ │ ├── features-12.json │ │ ├── features-2.json │ │ ├── features-3.json │ │ ├── features-4.json │ │ ├── features-5.json │ │ ├── features-6.json │ │ ├── features-7.json │ │ ├── features-8.json │ │ ├── features-9.json │ │ ├── footer-1.json │ │ ├── footer-2.json │ │ ├── footer-3.json │ │ ├── footer-4.json │ │ ├── footer-5.json │ │ ├── forgot-password-1.json │ │ ├── forgot-password-2.json │ │ ├── hero-section-1.json │ │ ├── hero-section-2.json │ │ ├── hero-section-3.json │ │ ├── hero-section-4.json │ │ ├── hero-section-5.json │ │ ├── hero-section-6.json │ │ ├── hero-section-7.json │ │ ├── hero-section-8.json │ │ ├── hero-section-9.json │ │ ├── integrations-1.json │ │ ├── integrations-2.json │ │ ├── integrations-3.json │ │ ├── integrations-4.json │ │ ├── integrations-5.json │ │ ├── integrations-6.json │ │ ├── integrations-7.json │ │ ├── integrations-8.json │ │ ├── login-1.json │ │ ├── login-2.json │ │ ├── login-3.json │ │ ├── logo-cloud-1.json │ │ ├── logo-cloud-2.json │ │ ├── logo-cloud-3.json │ │ ├── mist-call-to-action-1.json │ │ ├── mist-call-to-action-2.json │ │ ├── mist-call-to-action-3.json │ │ ├── mist-comparator-1.json │ │ ├── mist-contact-1.json │ │ ├── mist-content-1.json │ │ ├── mist-content-2.json │ │ ├── mist-content-3.json │ │ ├── mist-content-4.json │ │ ├── mist-faqs-1.json │ │ ├── mist-faqs-2.json │ │ ├── mist-faqs-3.json │ │ ├── mist-features-1.json │ │ ├── mist-features-10.json │ │ ├── mist-features-11.json │ │ ├── mist-features-2.json │ │ ├── mist-features-3.json │ │ ├── mist-features-4.json │ │ ├── mist-features-5.json │ │ ├── mist-features-6.json │ │ ├── mist-features-7.json │ │ ├── mist-features-8.json │ │ ├── mist-features-9.json │ │ ├── mist-footer-1.json │ │ ├── mist-footer-2.json │ │ ├── mist-footer-3.json │ │ ├── mist-footer-4.json │ │ ├── mist-forgot-password-1.json │ │ ├── mist-hero-section-1.json │ │ ├── mist-hero-section-2.json │ │ ├── mist-hero-section-3.json │ │ ├── mist-hero-section-4.json │ │ ├── mist-hero-section-5.json │ │ ├── mist-hero-section-6.json │ │ ├── mist-integrations-1.json │ │ ├── mist-integrations-2.json │ │ ├── mist-integrations-3.json │ │ ├── mist-login-1.json │ │ ├── mist-logo-cloud-1.json │ │ ├── mist-logo-cloud-2.json │ │ ├── mist-pricing-1.json │ │ ├── mist-pricing-2.json │ │ ├── mist-sign-up-1.json │ │ ├── mist-stats-1.json │ │ ├── mist-stats-2.json │ │ ├── mist-stats-3.json │ │ ├── mist-stats-4.json │ │ ├── mist-team-1.json │ │ ├── mist-team-2.json │ │ ├── mist-testimonials-1.json │ │ ├── mist-testimonials-2.json │ │ ├── mist-testimonials-3.json │ │ ├── mist-testimonials-4.json │ │ ├── mist-testimonials-5.json │ │ ├── pricing-1.json │ │ ├── pricing-2.json │ │ ├── pricing-3.json │ │ ├── pricing-4.json │ │ ├── pricing-5.json │ │ ├── sign-up-1.json │ │ ├── sign-up-2.json │ │ ├── sign-up-3.json │ │ ├── stats-1.json │ │ ├── stats-2.json │ │ ├── stats-3.json │ │ ├── stats-4.json │ │ ├── team-1.json │ │ ├── team-2.json │ │ ├── testimonials-1.json │ │ ├── testimonials-2.json │ │ ├── testimonials-3.json │ │ ├── testimonials-4.json │ │ ├── testimonials-5.json │ │ └── testimonials-6.json │ └── sw.js │ ├── registry.json │ └── tsconfig.json ├── package.json ├── packages ├── core │ ├── .gitignore │ ├── README.md │ ├── components.json │ ├── eslint.config.js │ ├── index.html │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ ├── logo.tsx │ │ │ └── logos │ │ │ │ ├── Gemini.tsx │ │ │ │ ├── GooglePaLM.tsx │ │ │ │ ├── MagicUI.tsx │ │ │ │ ├── MediaWiki.tsx │ │ │ │ ├── Replit.tsx │ │ │ │ ├── VSCodium.tsx │ │ │ │ └── index.ts │ │ ├── index.css │ │ ├── lib │ │ │ └── utils.ts │ │ ├── magicui │ │ │ └── border-beam.tsx │ │ ├── main.tsx │ │ ├── motion-primitives │ │ │ ├── animated-group.tsx │ │ │ ├── infinite-slider.tsx │ │ │ ├── progressive-blur.tsx │ │ │ └── text-effect.tsx │ │ ├── ui │ │ │ ├── accordion.tsx │ │ │ ├── avatar.tsx │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── chart.tsx │ │ │ ├── dialog.tsx │ │ │ ├── input.tsx │ │ │ ├── label.tsx │ │ │ ├── radio-group.tsx │ │ │ ├── scroll-area.tsx │ │ │ ├── select.tsx │ │ │ ├── separator.tsx │ │ │ ├── textarea.tsx │ │ │ ├── toggle-group.tsx │ │ │ ├── toggle.tsx │ │ │ └── tooltip.tsx │ │ └── vite-env.d.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts ├── dusk-kit │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── layout.tsx │ │ └── page.tsx │ ├── blocks │ │ ├── call-to-action │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── comparator │ │ │ └── one │ │ │ │ └── index.tsx │ │ ├── contact │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── content │ │ │ ├── five │ │ │ │ └── index.tsx │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── seven │ │ │ │ └── index.tsx │ │ │ ├── six │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── faqs │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── features │ │ │ ├── eight │ │ │ │ └── index.tsx │ │ │ ├── eleven │ │ │ │ └── index.tsx │ │ │ ├── five │ │ │ │ └── index.tsx │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── nine │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── seven │ │ │ │ └── index.tsx │ │ │ ├── six │ │ │ │ └── index.tsx │ │ │ ├── ten │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ ├── twelve │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── footer │ │ │ ├── five │ │ │ │ └── index.tsx │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── forgot-password │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── hero-section │ │ │ ├── eight │ │ │ │ └── index.tsx │ │ │ ├── five │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ │ ├── four │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ │ ├── nine │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ │ ├── seven │ │ │ │ └── index.tsx │ │ │ ├── six │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ ├── header.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── logo-cloud.tsx │ │ │ └── two │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ ├── index.ts │ │ ├── integrations │ │ │ ├── eight │ │ │ │ └── index.tsx │ │ │ ├── five │ │ │ │ └── index.tsx │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── seven │ │ │ │ └── index.tsx │ │ │ ├── six │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── login │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── logo-cloud │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── pricing │ │ │ ├── five │ │ │ │ └── index.tsx │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── sign-up │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── stats │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── team │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ └── testimonials │ │ │ ├── five │ │ │ └── index.tsx │ │ │ ├── four │ │ │ └── index.tsx │ │ │ ├── one │ │ │ └── index.tsx │ │ │ ├── six │ │ │ └── index.tsx │ │ │ ├── three │ │ │ └── index.tsx │ │ │ └── two │ │ │ └── index.tsx │ ├── components.json │ ├── eslint.config.mjs │ ├── next.config.js │ ├── package.json │ ├── postcss.config.mjs │ └── tsconfig.json ├── mist-kit │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── layout.tsx │ │ └── page.tsx │ ├── blocks │ │ ├── call-to-action │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── comparator │ │ │ └── one │ │ │ │ └── index.tsx │ │ ├── contact │ │ │ └── one │ │ │ │ └── index.tsx │ │ ├── content │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── faqs │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── features │ │ │ ├── eight │ │ │ │ └── index.tsx │ │ │ ├── eleven │ │ │ │ └── index.tsx │ │ │ ├── five │ │ │ │ └── index.tsx │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── nine │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ ├── index.tsx │ │ │ │ └── table.tsx │ │ │ ├── seven │ │ │ │ └── index.tsx │ │ │ ├── six │ │ │ │ └── index.tsx │ │ │ ├── ten │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── footer │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── forgot-password │ │ │ └── one │ │ │ │ └── index.tsx │ │ ├── hero-section │ │ │ ├── five │ │ │ │ └── index.tsx │ │ │ ├── four │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ │ ├── six │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ ├── header.tsx │ │ │ │ └── index.tsx │ │ ├── index.ts │ │ ├── integrations │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── login │ │ │ └── one │ │ │ │ └── index.tsx │ │ ├── logo-cloud │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── pricing │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── sign-up │ │ │ └── one │ │ │ │ └── index.tsx │ │ ├── stats │ │ │ ├── four │ │ │ │ └── index.tsx │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ ├── three │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ ├── team │ │ │ ├── one │ │ │ │ └── index.tsx │ │ │ └── two │ │ │ │ └── index.tsx │ │ └── testimonials │ │ │ ├── five │ │ │ └── index.tsx │ │ │ ├── four │ │ │ └── index.tsx │ │ │ ├── one │ │ │ └── index.tsx │ │ │ ├── three │ │ │ └── index.tsx │ │ │ └── two │ │ │ └── index.tsx │ ├── components.json │ ├── components │ │ └── ui │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ └── hover-card.tsx │ ├── eslint.config.mjs │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.mjs │ └── tsconfig.json └── ts-config │ ├── base.json │ └── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── turbo.json /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | .turbo 20 | 21 | # production 22 | /build 23 | 24 | # misc 25 | .DS_Store 26 | *.pem 27 | 28 | # debug 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | .pnpm-debug.log* 33 | 34 | # env files (can opt-in for committing if needed) 35 | .env* 36 | 37 | # vercel 38 | .vercel 39 | 40 | # typescript 41 | *.tsbuildinfo 42 | next-env.d.ts 43 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | build 3 | coverage 4 | pnpm-workspace.yaml -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 500, 3 | "semi": false, 4 | "tabWidth": 4, 5 | "parser": "babel", 6 | "singleQuote": true, 7 | "trailingComma": "es5", 8 | "jsxBracketSameLine": true, 9 | "quoteProps": "as-needed", 10 | "jsxSingleQuote": false, 11 | "bracketSpacing": true, 12 | "bracketSameLine": false, 13 | "useTabs": false, 14 | "singleAttributePerLine": true, 15 | "plugins": [ 16 | "prettier-plugin-tailwindcss" 17 | ], 18 | "tailwindStylesheet": "./app/global.css", 19 | "overrides": [ 20 | { 21 | "files": "*.tsx", 22 | "options": { 23 | "parser": "babel-ts" 24 | } 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Irung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tailark 2 | 3 | Speed up your workflow with responsive, pre-built shadcn-UI and Tailwindcss blocks designed for marketing websites. 4 | 5 | [Tailark](https://tailark.com) 6 | 7 | ![Tailark Image](apps/www/app/opengraph-image.png) 8 | 9 | 10 | ## Getting Started 11 | 12 | First, run the development server: 13 | 14 | ```bash 15 | pnpm dev 16 | ``` 17 | 18 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -------------------------------------------------------------------------------- /apps/www/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "@next/next/no-html-link-for-pages": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /apps/www/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | .turbo 20 | 21 | # production 22 | /build 23 | 24 | # misc 25 | .DS_Store 26 | *.pem 27 | 28 | # debug 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | .pnpm-debug.log* 33 | 34 | # env files (can opt-in for committing if needed) 35 | .env* 36 | 37 | # vercel 38 | .vercel 39 | 40 | # typescript 41 | *.tsbuildinfo 42 | next-env.d.ts 43 | -------------------------------------------------------------------------------- /apps/www/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | build 3 | coverage 4 | pnpm-workspace.yaml -------------------------------------------------------------------------------- /apps/www/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 500, 3 | "semi": false, 4 | "tabWidth": 4, 5 | "parser": "babel", 6 | "singleQuote": true, 7 | "trailingComma": "es5", 8 | "jsxBracketSameLine": true, 9 | "quoteProps": "as-needed", 10 | "jsxSingleQuote": false, 11 | "bracketSpacing": true, 12 | "bracketSameLine": false, 13 | "useTabs": false, 14 | "singleAttributePerLine": true, 15 | "plugins": [ 16 | "prettier-plugin-tailwindcss" 17 | ], 18 | "tailwindStylesheet": "./app/global.css", 19 | "overrides": [ 20 | { 21 | "files": "*.tsx", 22 | "options": { 23 | "parser": "babel-ts" 24 | } 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /apps/www/LICENCE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Irung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /apps/www/README.md: -------------------------------------------------------------------------------- 1 | # Tailark 2 | 3 | Speed up your workflow with responsive, pre-built shadcn-UI and Tailwindcss blocks designed for marketing websites. 4 | 5 | [Tailark](https://tailark.com) 6 | 7 | ![Tailark Image](app/opengraph-image.png) 8 | 9 | 10 | ## Getting Started 11 | 12 | First, run the development server: 13 | 14 | ```bash 15 | pnpm dev 16 | ``` 17 | 18 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -------------------------------------------------------------------------------- /apps/www/app/(categories)/[...slug]/layout.tsx: -------------------------------------------------------------------------------- 1 | import React, { use } from 'react' 2 | import { blocks, categories } from '@/data/blocks' 3 | import BlocksNav from '@/components/blocks-nav' 4 | import { SiteFooter } from '@/components/site-footer' 5 | import { SiteHeader } from '@/components/site-header' 6 | 7 | interface LayoutProps { 8 | children: React.ReactNode 9 | params: Promise<{ slug: string[] }> 10 | } 11 | 12 | function getKitDetailsFromSlug(slug: string[]): { kitShortName: string; kitFullName: string } { 13 | let kitShortName: string 14 | let kitFullName: string 15 | 16 | if (!slug || slug.length === 0) { 17 | kitShortName = 'default' 18 | kitFullName = 'dusk-kit' 19 | } else if (slug.length === 1) { 20 | kitShortName = 'default' 21 | kitFullName = 'dusk-kit' 22 | } else { 23 | kitShortName = slug[0] 24 | kitFullName = `${kitShortName}-kit` 25 | } 26 | return { kitShortName, kitFullName } 27 | } 28 | 29 | export default function CategoryLayout({ children, params }: LayoutProps) { 30 | const { slug } = use(params) 31 | const { kitShortName, kitFullName } = getKitDetailsFromSlug(slug) 32 | 33 | const allCategories = categories 34 | 35 | return ( 36 | <> 37 | 38 | 44 |
{children}
45 | 46 | 47 | ) 48 | } 49 | -------------------------------------------------------------------------------- /apps/www/app/examples/layout.tsx: -------------------------------------------------------------------------------- 1 | import { ExampleFooter } from '@/components/ex-footer' 2 | import { ExampleHeeader } from '@/components/ex-header' 3 | 4 | export default function CategoryLayout({ 5 | children, 6 | }: Readonly<{ 7 | children: React.ReactNode 8 | }>) { 9 | return ( 10 | <> 11 | 12 | <>{children} 13 | 14 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /apps/www/app/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /apps/www/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next' 2 | import { Geist, Geist_Mono } from 'next/font/google' 3 | import './globals.css' 4 | import { ThemeProvider } from '@/components/theme-provider' 5 | import { GoogleAnalytics } from '@next/third-parties/google' 6 | import ServiceWorkerInit from '@/components/service-worker-init' 7 | 8 | const geistSans = Geist({ 9 | variable: '--font-geist-sans', 10 | subsets: ['latin'], 11 | }) 12 | 13 | const geistMono = Geist_Mono({ 14 | variable: '--font-geist-mono', 15 | subsets: ['latin'], 16 | }) 17 | 18 | export const metadata: Metadata = { 19 | title: 'Shadcn Marketing Blocks | Tailark', 20 | description: 'Speed up your workflow with responsive, pre-built UI blocks designed for marketing websites.', 21 | keywords: 'shadcn, ui, blocks, marketing, components, tailwind, react, nextjs, tailark, responsive, design system, templates, template, hero section, features, footers, contact forms, Bento, Call To Action, Testimonials, logo cloud, integrations, content, team, pricing, login, sign in, logout, stats FAQ sections', 22 | } 23 | 24 | export default function RootLayout({ 25 | children, 26 | }: Readonly<{ 27 | children: React.ReactNode 28 | }>) { 29 | return ( 30 | 33 | 34 | 39 | {children} 40 | 41 | 42 | 43 | 44 | 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /apps/www/app/mist/opengraph-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tailark/blocks/400ffc53437acad8023e39aaac8a2d9da9aa86a2/apps/www/app/mist/opengraph-image.png -------------------------------------------------------------------------------- /apps/www/app/mist/twitter-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tailark/blocks/400ffc53437acad8023e39aaac8a2d9da9aa86a2/apps/www/app/mist/twitter-image.png -------------------------------------------------------------------------------- /apps/www/app/opengraph-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tailark/blocks/400ffc53437acad8023e39aaac8a2d9da9aa86a2/apps/www/app/opengraph-image.png -------------------------------------------------------------------------------- /apps/www/app/preview/[[...slug]]/block-renderer.tsx: -------------------------------------------------------------------------------- 1 | import dynamic from 'next/dynamic' 2 | import { duskKitBlockMap } from '@tailark/dusk/blocks' 3 | import { mistKitBlockMap } from '@tailark/mist/blocks' 4 | import React from 'react' 5 | import { Suspense } from 'react' 6 | 7 | interface BlockRendererProps { 8 | kitShortName: string 9 | category: string 10 | variant: string 11 | } 12 | 13 | type SpecificBlockLoaderComponentType = React.ComponentType> 14 | type BlockLoaderFunctionType = () => Promise 15 | 16 | const kitBlockMaps = { 17 | dusk: duskKitBlockMap, 18 | mist: mistKitBlockMap, 19 | } 20 | 21 | const BlockRenderer: React.FC = ({ kitShortName, category, variant }) => { 22 | const kitMapKey = kitShortName as keyof typeof kitBlockMaps 23 | 24 | if (!(kitMapKey in kitBlockMaps)) { 25 | console.error(`Unknown kit: ${kitShortName}`) 26 | return
Error: Unknown kit.
27 | } 28 | 29 | const kitBlockMap = kitBlockMaps[kitMapKey] 30 | 31 | const categoryKey = category as keyof typeof kitBlockMap 32 | if (!(categoryKey in kitBlockMap)) { 33 | console.error(`Block not found: ${kitShortName}/${category}/${variant} (category '${category}' not found in kit '${kitShortName}')`) 34 | return
Error: Category not found in {kitShortName}.
35 | } 36 | 37 | const variantsMap = kitBlockMap[categoryKey]! 38 | const variantKey = variant as keyof typeof variantsMap 39 | if (!(variantKey in variantsMap)) { 40 | console.error(`Block not found: ${kitShortName}/${category}/${variant} (variant '${variant}' not found in category '${category}' of kit '${kitShortName}')`) 41 | return
Error: Variant not found in {kitShortName}.
42 | } 43 | 44 | const blockLoader: BlockLoaderFunctionType = variantsMap[variantKey]! as BlockLoaderFunctionType 45 | 46 | const LazyBlock = dynamic(blockLoader, { 47 | loading: () =>
Loading block...
, 48 | }) 49 | 50 | return ( 51 | Loading block...}> 52 | 53 | 54 | ) 55 | } 56 | 57 | export default BlockRenderer 58 | -------------------------------------------------------------------------------- /apps/www/app/preview/[[...slug]]/page.tsx: -------------------------------------------------------------------------------- 1 | import BlockRenderer from './block-renderer' 2 | import { cn } from '@tailark/core/lib/utils' 3 | import { use } from 'react' 4 | import { Metadata } from 'next' 5 | 6 | export async function generateMetadata({ params }: { params: Promise<{ slug: string[] }> }): Promise { 7 | const { slug } = await params 8 | 9 | if (!slug || slug.length < 3) { 10 | return { title: 'Preview | Tailark' } 11 | } 12 | 13 | const [kitShortName, category, variant] = slug 14 | const categoryDisplay = category 15 | .split('-') 16 | .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) 17 | .join(' ') 18 | const variantDisplay = variant 19 | .split('-') 20 | .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) 21 | .join(' ') 22 | 23 | return { 24 | title: `${categoryDisplay} ${variantDisplay} | Tailark ${kitShortName.charAt(0).toUpperCase() + kitShortName.slice(1)}`, 25 | metadataBase: new URL(process.env.NEXT_PUBLIC_APP_URL || 'https://tailark.com'), 26 | openGraph: { 27 | title: `${kitShortName} - ${category} ${variant}`, 28 | images: [`/og?type=preview&slug=${slug.join(',')}`], 29 | }, 30 | twitter: { 31 | card: 'summary_large_image', 32 | images: [`/og?type=preview&slug=${slug.join(',')}`], 33 | }, 34 | } 35 | } 36 | 37 | export default function PreviewPage({ params }: { params: Promise<{ slug: string[] }> }) { 38 | const { slug } = use(params) 39 | 40 | if (!slug || slug.length < 3) { 41 | return
Invalid path. Please use the format /preview/kit-name/category/variant.
42 | } 43 | 44 | const [kitShortName, category, variant] = slug 45 | 46 | return ( 47 |
50 | 55 |
56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /apps/www/app/robots.ts: -------------------------------------------------------------------------------- 1 | import { MetadataRoute } from 'next' 2 | 3 | export default function robots(): MetadataRoute.Robots { 4 | return { 5 | rules: { 6 | userAgent: '*', 7 | allow: '/', 8 | disallow: ['/api/'], 9 | }, 10 | sitemap: 'https://tailark.com/sitemap.xml', 11 | } 12 | } -------------------------------------------------------------------------------- /apps/www/app/sitemap.ts: -------------------------------------------------------------------------------- 1 | import { MetadataRoute } from 'next' 2 | import { blocks, categories } from '@/data/blocks' 3 | 4 | export default function sitemap(): MetadataRoute.Sitemap { 5 | const baseUrl = 'https://tailark.com' 6 | 7 | const routes = [ 8 | { 9 | url: baseUrl, 10 | lastModified: new Date(), 11 | changefrequency: 'daily', 12 | priority: 1, 13 | }, 14 | ] 15 | 16 | const categoryRoutes = categories.map((category) => ({ 17 | url: `${baseUrl}/${category}`, 18 | lastModified: new Date(), 19 | changefrequency: 'weekly', 20 | priority: 0.8, 21 | })) 22 | 23 | const blockRoutes = blocks.map((block) => ({ 24 | url: `${baseUrl}/preview/${block.category}/${block.title}`, 25 | lastModified: new Date(), 26 | changefrequency: 'monthly', 27 | priority: 0.5, 28 | })) 29 | 30 | return [...routes, ...categoryRoutes, ...blockRoutes] 31 | } -------------------------------------------------------------------------------- /apps/www/app/snippets/layout.tsx: -------------------------------------------------------------------------------- 1 | import { SiteFooter } from '@/components/site-footer' 2 | import { SiteHeader } from '@/components/site-header' 3 | 4 | export default function CategoryLayout({ 5 | children, 6 | }: Readonly<{ 7 | children: React.ReactNode 8 | }>) { 9 | return ( 10 | <> 11 | 12 |
{children}
13 | 14 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /apps/www/app/twitter-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tailark/blocks/400ffc53437acad8023e39aaac8a2d9da9aa86a2/apps/www/app/twitter-image.png -------------------------------------------------------------------------------- /apps/www/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@tailark/core/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks", 19 | "data": "@/data" 20 | }, 21 | "iconLibrary": "lucide" 22 | } -------------------------------------------------------------------------------- /apps/www/components/active-category-links.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import Link from 'next/link' 4 | import { usePathname } from 'next/navigation' 5 | import { cn } from '@tailark/core/lib/utils' 6 | import type { Block } from '@/data/blocks' 7 | 8 | interface ActiveCategoryLinksProps { 9 | currentKitFullName: string 10 | currentKitShortName: string 11 | allCategories: string[] 12 | blocks: Block[] 13 | } 14 | 15 | export function ActiveCategoryLinks({ currentKitFullName, currentKitShortName, allCategories, blocks }: ActiveCategoryLinksProps) { 16 | const pathname = usePathname() 17 | 18 | return ( 19 |
    22 | {allCategories.map((category) => { 23 | const hasBlocksInKit = blocks.some((block) => block.kit === currentKitFullName && block.category === category) 24 | 25 | const href = currentKitShortName === 'default' ? `/${category}` : `/${currentKitShortName}/${category}` 26 | 27 | const isActive = pathname === href 28 | 29 | return ( 30 |
  • 33 | !hasBlocksInKit && e.preventDefault()}> 43 | {category.replace(/-/g, ' ')} 44 | 45 |
  • 46 | ) 47 | })} 48 |
49 | ) 50 | } 51 | -------------------------------------------------------------------------------- /apps/www/components/block-preview/iframe-renderer.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import React, { CSSProperties, RefObject, useMemo } from 'react' 3 | import { cn } from '@tailark/core/lib/utils' 4 | import { clearIframeCache } from '@/lib/serviceWorker' 5 | 6 | interface IframeRendererProps { 7 | src: string 8 | title: string 9 | ariaLabel?: string 10 | id: string 11 | iframeRef: RefObject 12 | height: number 13 | isCached: boolean 14 | className?: string 15 | style?: React.CSSProperties 16 | } 17 | 18 | const IframeRenderer: React.FC = ({ src, title, ariaLabel, id, iframeRef, height, isCached, className, style }) => { 19 | const handleLoad = () => { 20 | clearIframeCache(src) 21 | } 22 | 23 | const urlWithCacheBusting = useMemo(() => { 24 | try { 25 | const url = new URL(src, window.location.origin) 26 | url.searchParams.set('_', Date.now().toString()) 27 | return url.toString() 28 | } catch { 29 | return src 30 | } 31 | }, [src]) 32 | 33 | return ( 34 |