From c735556726e75428550a3d28a2cf58e2c8490b7d Mon Sep 17 00:00:00 2001 From: Dawid Rycerz Date: Mon, 21 Jul 2025 21:56:55 +0300 Subject: Initial template --- src/assets/favicons/apple-touch-icon.png | Bin 0 -> 5498 bytes src/assets/favicons/favicon.ico | Bin 0 -> 15086 bytes src/assets/favicons/favicon.svg | 9 + src/assets/images/app-store.png | Bin 0 -> 11251 bytes src/assets/images/default.png | Bin 0 -> 405450 bytes src/assets/images/google-play.png | Bin 0 -> 13307 bytes src/assets/images/hero-image.png | Bin 0 -> 551662 bytes src/assets/styles/tailwind.css | 92 +++++ src/components/CustomStyles.astro | 63 ++++ src/components/Favicons.astro | 10 + src/components/Logo.astro | 9 + src/components/blog/Grid.astro | 14 + src/components/blog/GridItem.astro | 71 ++++ src/components/blog/Headline.astro | 12 + src/components/blog/List.astro | 20 + src/components/blog/ListItem.astro | 120 ++++++ src/components/blog/Pagination.astro | 36 ++ src/components/blog/RelatedPosts.astro | 31 ++ src/components/blog/SinglePost.astro | 103 ++++++ src/components/blog/Tags.astro | 43 +++ src/components/blog/ToBlogLink.astro | 20 + src/components/common/Analytics.astro | 13 + src/components/common/ApplyColorMode.astro | 33 ++ src/components/common/BasicScripts.astro | 255 +++++++++++++ src/components/common/CommonMeta.astro | 8 + src/components/common/Image.astro | 61 ++++ src/components/common/Metadata.astro | 68 ++++ src/components/common/SiteVerification.astro | 5 + src/components/common/SocialShare.astro | 65 ++++ src/components/common/SplitbeeAnalytics.astro | 6 + src/components/common/ToggleMenu.astro | 29 ++ src/components/common/ToggleTheme.astro | 28 ++ src/components/ui/Background.astro | 11 + src/components/ui/Button.astro | 40 ++ src/components/ui/DListItem.astro | 22 ++ src/components/ui/Form.astro | 87 +++++ src/components/ui/Headline.astro | 35 ++ src/components/ui/ItemGrid.astro | 65 ++++ src/components/ui/ItemGrid2.astro | 59 +++ src/components/ui/Timeline.astro | 60 +++ src/components/ui/WidgetWrapper.astro | 34 ++ src/components/widgets/Announcement.astro | 23 ++ src/components/widgets/BlogHighlightedPosts.astro | 64 ++++ src/components/widgets/BlogLatestPosts.astro | 63 ++++ src/components/widgets/Brands.astro | 38 ++ src/components/widgets/CallToAction.astro | 58 +++ src/components/widgets/Contact.astro | 40 ++ src/components/widgets/Content.astro | 94 +++++ src/components/widgets/FAQs.astro | 33 ++ src/components/widgets/Features.astro | 36 ++ src/components/widgets/Features2.astro | 38 ++ src/components/widgets/Features3.astro | 70 ++++ src/components/widgets/Footer.astro | 104 ++++++ src/components/widgets/Header.astro | 167 +++++++++ src/components/widgets/Hero.astro | 99 +++++ src/components/widgets/Hero2.astro | 98 +++++ src/components/widgets/HeroText.astro | 86 +++++ src/components/widgets/Note.astro | 23 ++ src/components/widgets/Pricing.astro | 83 +++++ src/components/widgets/Stats.astro | 46 +++ src/components/widgets/Steps.astro | 59 +++ src/components/widgets/Steps2.astro | 72 ++++ src/components/widgets/Testimonials.astro | 75 ++++ src/config.yaml | 72 ++++ src/content/config.ts | 70 ++++ src/data/post/astrowind-template-in-depth.mdx | 207 +++++++++++ .../get-started-website-with-astro-tailwind-css.md | 51 +++ .../how-to-customize-astrowind-to-your-brand.md | 64 ++++ src/data/post/landing.md | 152 ++++++++ src/data/post/markdown-elements-demo-post.mdx | 204 +++++++++++ .../post/useful-resources-to-create-websites.md | 62 ++++ src/env.d.ts | 5 + src/layouts/LandingLayout.astro | 35 ++ src/layouts/Layout.astro | 48 +++ src/layouts/MarkdownLayout.astro | 28 ++ src/layouts/PageLayout.astro | 31 ++ src/navigation.ts | 183 ++++++++++ src/pages/404.astro | 24 ++ src/pages/[...blog]/[...page].astro | 52 +++ src/pages/[...blog]/[category]/[...page].astro | 37 ++ src/pages/[...blog]/[tag]/[...page].astro | 37 ++ src/pages/[...blog]/index.astro | 54 +++ src/pages/about.astro | 228 ++++++++++++ src/pages/contact.astro | 79 ++++ src/pages/homes/mobile-app.astro | 297 +++++++++++++++ src/pages/homes/personal.astro | 405 +++++++++++++++++++++ src/pages/homes/saas.astro | 349 ++++++++++++++++++ src/pages/homes/startup.astro | 317 ++++++++++++++++ src/pages/index.astro | 399 ++++++++++++++++++++ src/pages/landing/click-through.astro | 41 +++ src/pages/landing/lead-generation.astro | 41 +++ src/pages/landing/pre-launch.astro | 41 +++ src/pages/landing/product.astro | 41 +++ src/pages/landing/sales.astro | 41 +++ src/pages/landing/subscription.astro | 41 +++ src/pages/pricing.astro | 244 +++++++++++++ src/pages/privacy.md | 185 ++++++++++ src/pages/rss.xml.ts | 37 ++ src/pages/services.astro | 224 ++++++++++++ src/pages/terms.md | 120 ++++++ src/types.d.ts | 281 ++++++++++++++ src/utils/blog.ts | 281 ++++++++++++++ src/utils/directories.ts | 18 + src/utils/frontmatter.ts | 50 +++ src/utils/images-optimization.ts | 351 ++++++++++++++++++ src/utils/images.ts | 111 ++++++ src/utils/permalinks.ts | 134 +++++++ src/utils/utils.ts | 52 +++ 108 files changed, 8930 insertions(+) create mode 100644 src/assets/favicons/apple-touch-icon.png create mode 100644 src/assets/favicons/favicon.ico create mode 100644 src/assets/favicons/favicon.svg create mode 100644 src/assets/images/app-store.png create mode 100644 src/assets/images/default.png create mode 100644 src/assets/images/google-play.png create mode 100644 src/assets/images/hero-image.png create mode 100644 src/assets/styles/tailwind.css create mode 100644 src/components/CustomStyles.astro create mode 100644 src/components/Favicons.astro create mode 100644 src/components/Logo.astro create mode 100644 src/components/blog/Grid.astro create mode 100644 src/components/blog/GridItem.astro create mode 100644 src/components/blog/Headline.astro create mode 100644 src/components/blog/List.astro create mode 100644 src/components/blog/ListItem.astro create mode 100644 src/components/blog/Pagination.astro create mode 100644 src/components/blog/RelatedPosts.astro create mode 100644 src/components/blog/SinglePost.astro create mode 100644 src/components/blog/Tags.astro create mode 100644 src/components/blog/ToBlogLink.astro create mode 100644 src/components/common/Analytics.astro create mode 100644 src/components/common/ApplyColorMode.astro create mode 100644 src/components/common/BasicScripts.astro create mode 100644 src/components/common/CommonMeta.astro create mode 100644 src/components/common/Image.astro create mode 100644 src/components/common/Metadata.astro create mode 100644 src/components/common/SiteVerification.astro create mode 100644 src/components/common/SocialShare.astro create mode 100644 src/components/common/SplitbeeAnalytics.astro create mode 100644 src/components/common/ToggleMenu.astro create mode 100644 src/components/common/ToggleTheme.astro create mode 100644 src/components/ui/Background.astro create mode 100644 src/components/ui/Button.astro create mode 100644 src/components/ui/DListItem.astro create mode 100644 src/components/ui/Form.astro create mode 100644 src/components/ui/Headline.astro create mode 100644 src/components/ui/ItemGrid.astro create mode 100644 src/components/ui/ItemGrid2.astro create mode 100644 src/components/ui/Timeline.astro create mode 100644 src/components/ui/WidgetWrapper.astro create mode 100644 src/components/widgets/Announcement.astro create mode 100644 src/components/widgets/BlogHighlightedPosts.astro create mode 100644 src/components/widgets/BlogLatestPosts.astro create mode 100644 src/components/widgets/Brands.astro create mode 100644 src/components/widgets/CallToAction.astro create mode 100644 src/components/widgets/Contact.astro create mode 100644 src/components/widgets/Content.astro create mode 100644 src/components/widgets/FAQs.astro create mode 100644 src/components/widgets/Features.astro create mode 100644 src/components/widgets/Features2.astro create mode 100644 src/components/widgets/Features3.astro create mode 100644 src/components/widgets/Footer.astro create mode 100644 src/components/widgets/Header.astro create mode 100644 src/components/widgets/Hero.astro create mode 100644 src/components/widgets/Hero2.astro create mode 100644 src/components/widgets/HeroText.astro create mode 100644 src/components/widgets/Note.astro create mode 100644 src/components/widgets/Pricing.astro create mode 100644 src/components/widgets/Stats.astro create mode 100644 src/components/widgets/Steps.astro create mode 100644 src/components/widgets/Steps2.astro create mode 100644 src/components/widgets/Testimonials.astro create mode 100644 src/config.yaml create mode 100644 src/content/config.ts create mode 100644 src/data/post/astrowind-template-in-depth.mdx create mode 100644 src/data/post/get-started-website-with-astro-tailwind-css.md create mode 100644 src/data/post/how-to-customize-astrowind-to-your-brand.md create mode 100644 src/data/post/landing.md create mode 100644 src/data/post/markdown-elements-demo-post.mdx create mode 100644 src/data/post/useful-resources-to-create-websites.md create mode 100644 src/env.d.ts create mode 100644 src/layouts/LandingLayout.astro create mode 100644 src/layouts/Layout.astro create mode 100644 src/layouts/MarkdownLayout.astro create mode 100644 src/layouts/PageLayout.astro create mode 100644 src/navigation.ts create mode 100644 src/pages/404.astro create mode 100644 src/pages/[...blog]/[...page].astro create mode 100644 src/pages/[...blog]/[category]/[...page].astro create mode 100644 src/pages/[...blog]/[tag]/[...page].astro create mode 100644 src/pages/[...blog]/index.astro create mode 100644 src/pages/about.astro create mode 100644 src/pages/contact.astro create mode 100644 src/pages/homes/mobile-app.astro create mode 100644 src/pages/homes/personal.astro create mode 100644 src/pages/homes/saas.astro create mode 100644 src/pages/homes/startup.astro create mode 100644 src/pages/index.astro create mode 100644 src/pages/landing/click-through.astro create mode 100644 src/pages/landing/lead-generation.astro create mode 100644 src/pages/landing/pre-launch.astro create mode 100644 src/pages/landing/product.astro create mode 100644 src/pages/landing/sales.astro create mode 100644 src/pages/landing/subscription.astro create mode 100644 src/pages/pricing.astro create mode 100644 src/pages/privacy.md create mode 100644 src/pages/rss.xml.ts create mode 100644 src/pages/services.astro create mode 100644 src/pages/terms.md create mode 100644 src/types.d.ts create mode 100644 src/utils/blog.ts create mode 100644 src/utils/directories.ts create mode 100644 src/utils/frontmatter.ts create mode 100644 src/utils/images-optimization.ts create mode 100644 src/utils/images.ts create mode 100644 src/utils/permalinks.ts create mode 100644 src/utils/utils.ts (limited to 'src') diff --git a/src/assets/favicons/apple-touch-icon.png b/src/assets/favicons/apple-touch-icon.png new file mode 100644 index 0000000..6262d06 Binary files /dev/null and b/src/assets/favicons/apple-touch-icon.png differ diff --git a/src/assets/favicons/favicon.ico b/src/assets/favicons/favicon.ico new file mode 100644 index 0000000..9f9502a Binary files /dev/null and b/src/assets/favicons/favicon.ico differ diff --git a/src/assets/favicons/favicon.svg b/src/assets/favicons/favicon.svg new file mode 100644 index 0000000..f157bd1 --- /dev/null +++ b/src/assets/favicons/favicon.svg @@ -0,0 +1,9 @@ + + + + diff --git a/src/assets/images/app-store.png b/src/assets/images/app-store.png new file mode 100644 index 0000000..8d634c0 Binary files /dev/null and b/src/assets/images/app-store.png differ diff --git a/src/assets/images/default.png b/src/assets/images/default.png new file mode 100644 index 0000000..fe60968 Binary files /dev/null and b/src/assets/images/default.png differ diff --git a/src/assets/images/google-play.png b/src/assets/images/google-play.png new file mode 100644 index 0000000..179f1ff Binary files /dev/null and b/src/assets/images/google-play.png differ diff --git a/src/assets/images/hero-image.png b/src/assets/images/hero-image.png new file mode 100644 index 0000000..5509924 Binary files /dev/null and b/src/assets/images/hero-image.png differ diff --git a/src/assets/styles/tailwind.css b/src/assets/styles/tailwind.css new file mode 100644 index 0000000..d36f8fa --- /dev/null +++ b/src/assets/styles/tailwind.css @@ -0,0 +1,92 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer utilities { + .bg-page { + background-color: var(--aw-color-bg-page); + } + .bg-dark { + background-color: var(--aw-color-bg-page-dark); + } + .bg-light { + background-color: var(--aw-color-bg-page); + } + .text-page { + color: var(--aw-color-text-page); + } + .text-muted { + color: var(--aw-color-text-muted); + } +} + +@layer components { + .btn { + @apply inline-flex items-center justify-center rounded-full border-gray-400 border bg-transparent font-medium text-center text-base text-page leading-snug transition py-3.5 px-6 md:px-8 ease-in duration-200 focus:ring-blue-500 focus:ring-offset-blue-200 focus:ring-2 focus:ring-offset-2 hover:bg-gray-100 hover:border-gray-600 dark:text-slate-300 dark:border-slate-500 dark:hover:bg-slate-800 dark:hover:border-slate-800 cursor-pointer; + } + + .btn-primary { + @apply btn font-semibold bg-primary text-white border-primary hover:bg-secondary hover:border-secondary hover:text-white dark:text-white dark:bg-primary dark:border-primary dark:hover:border-secondary dark:hover:bg-secondary; + } + + .btn-secondary { + @apply btn; + } + + .btn-tertiary { + @apply btn border-none shadow-none text-muted hover:text-gray-900 dark:text-gray-400 dark:hover:text-white; + } +} + +#header.scroll > div:first-child { + @apply bg-page md:bg-white/90 md:backdrop-blur-md; + box-shadow: 0 0.375rem 1.5rem 0 rgb(140 152 164 / 13%); +} +.dark #header.scroll > div:first-child, +#header.scroll.dark > div:first-child { + @apply bg-page md:bg-[#030621e6] border-b border-gray-500/20; + box-shadow: none; +} +/* #header.scroll > div:last-child { + @apply py-3; +} */ + +#header.expanded nav { + position: fixed; + top: 70px; + left: 0; + right: 0; + bottom: 70px !important; + padding: 0 5px; +} + +.dropdown:focus .dropdown-menu, +.dropdown:focus-within .dropdown-menu, +.dropdown:hover .dropdown-menu { + display: block; +} + +[astro-icon].icon-light > * { + stroke-width: 1.2; +} + +[astro-icon].icon-bold > * { + stroke-width: 2.4; +} + +[data-aw-toggle-menu] path { + @apply transition; +} +[data-aw-toggle-menu].expanded g > path:first-child { + @apply -rotate-45 translate-y-[15px] translate-x-[-3px]; +} + +[data-aw-toggle-menu].expanded g > path:last-child { + @apply rotate-45 translate-y-[-8px] translate-x-[14px]; +} + +/* To deprecated */ + +.dd *:first-child { + margin-top: 0; +} diff --git a/src/components/CustomStyles.astro b/src/components/CustomStyles.astro new file mode 100644 index 0000000..2b27954 --- /dev/null +++ b/src/components/CustomStyles.astro @@ -0,0 +1,63 @@ +--- +import '@fontsource-variable/inter'; + +// 'DM Sans' +// Nunito +// Dosis +// Outfit +// Roboto +// Literata +// 'IBM Plex Sans' +// Karla +// Poppins +// 'Fira Sans' +// 'Libre Franklin' +// Inconsolata +// Raleway +// Oswald +// 'Space Grotesk' +// Urbanist +--- + + diff --git a/src/components/Favicons.astro b/src/components/Favicons.astro new file mode 100644 index 0000000..fed6696 --- /dev/null +++ b/src/components/Favicons.astro @@ -0,0 +1,10 @@ +--- +import favIcon from '~/assets/favicons/favicon.ico'; +import favIconSvg from '~/assets/favicons/favicon.svg'; +import appleTouchIcon from '~/assets/favicons/apple-touch-icon.png'; +--- + + + + + diff --git a/src/components/Logo.astro b/src/components/Logo.astro new file mode 100644 index 0000000..8469792 --- /dev/null +++ b/src/components/Logo.astro @@ -0,0 +1,9 @@ +--- +import { SITE } from 'astrowind:config'; +--- + + + 🚀 {SITE?.name} + diff --git a/src/components/blog/Grid.astro b/src/components/blog/Grid.astro new file mode 100644 index 0000000..1b62be4 --- /dev/null +++ b/src/components/blog/Grid.astro @@ -0,0 +1,14 @@ +--- +import Item from '~/components/blog/GridItem.astro'; +import type { Post } from '~/types'; + +export interface Props { + posts: Array; +} + +const { posts } = Astro.props; +--- + +
+ {posts.map((post) => )} +
diff --git a/src/components/blog/GridItem.astro b/src/components/blog/GridItem.astro new file mode 100644 index 0000000..cd02fa8 --- /dev/null +++ b/src/components/blog/GridItem.astro @@ -0,0 +1,71 @@ +--- +import { APP_BLOG } from 'astrowind:config'; +import type { Post } from '~/types'; + +import Image from '~/components/common/Image.astro'; + +import { findImage } from '~/utils/images'; +import { getPermalink } from '~/utils/permalinks'; + +export interface Props { + post: Post; +} + +const { post } = Astro.props; +const image = await findImage(post.image); + +const link = APP_BLOG?.post?.isEnabled ? getPermalink(post.permalink, 'post') : ''; +--- + +
+
+ { + image && + (link ? ( + + {post.title} + + ) : ( + {post.title} + )) + } +
+ +

+ { + link ? ( + + {post.title} + + ) : ( + post.title + ) + } +

+ +

{post.excerpt}

+
diff --git a/src/components/blog/Headline.astro b/src/components/blog/Headline.astro new file mode 100644 index 0000000..5d3ccc6 --- /dev/null +++ b/src/components/blog/Headline.astro @@ -0,0 +1,12 @@ +--- +const { title = await Astro.slots.render('default'), subtitle = await Astro.slots.render('subtitle') } = Astro.props; +--- + +
+

+ { + subtitle && ( +
+ ) + } +

diff --git a/src/components/blog/List.astro b/src/components/blog/List.astro new file mode 100644 index 0000000..6a80ae3 --- /dev/null +++ b/src/components/blog/List.astro @@ -0,0 +1,20 @@ +--- +import Item from '~/components/blog/ListItem.astro'; +import type { Post } from '~/types'; + +export interface Props { + posts: Array; +} + +const { posts } = Astro.props; +--- + +
    + { + posts.map((post) => ( +
  • + +
  • + )) + } +
diff --git a/src/components/blog/ListItem.astro b/src/components/blog/ListItem.astro new file mode 100644 index 0000000..6a416d6 --- /dev/null +++ b/src/components/blog/ListItem.astro @@ -0,0 +1,120 @@ +--- +import type { ImageMetadata } from 'astro'; +import { Icon } from 'astro-icon/components'; +import Image from '~/components/common/Image.astro'; +import PostTags from '~/components/blog/Tags.astro'; + +import { APP_BLOG } from 'astrowind:config'; +import type { Post } from '~/types'; + +import { getPermalink } from '~/utils/permalinks'; +import { findImage } from '~/utils/images'; +import { getFormattedDate } from '~/utils/utils'; + +export interface Props { + post: Post; +} + +const { post } = Astro.props; +const image = (await findImage(post.image)) as ImageMetadata | undefined; + +const link = APP_BLOG?.post?.isEnabled ? getPermalink(post.permalink, 'post') : ''; +--- + +
+ { + image && + (link ? ( + + + + ) : ( + + )) + } +
+
+
+ + + + { + post.author && ( + <> + {' '} + · + {post.author.replaceAll('-', ' ')} + + ) + } + { + post.category && ( + <> + {' '} + ·{' '} + + {post.category.title} + + + ) + } + +
+

+ { + link ? ( + + {post.title} + + ) : ( + post.title + ) + } +

+
+ + {post.excerpt &&

{post.excerpt}

} + { + post.tags && Array.isArray(post.tags) ? ( +
+ +
+ ) : ( + + ) + } +
+
diff --git a/src/components/blog/Pagination.astro b/src/components/blog/Pagination.astro new file mode 100644 index 0000000..051587c --- /dev/null +++ b/src/components/blog/Pagination.astro @@ -0,0 +1,36 @@ +--- +import { Icon } from 'astro-icon/components'; +import { getPermalink } from '~/utils/permalinks'; +import Button from '~/components/ui/Button.astro'; + +export interface Props { + prevUrl?: string; + nextUrl?: string; + prevText?: string; + nextText?: string; +} + +const { prevUrl, nextUrl, prevText = 'Newer posts', nextText = 'Older posts' } = Astro.props; +--- + +{ + (prevUrl || nextUrl) && ( +
+
+ + + +
+
+ ) +} diff --git a/src/components/blog/RelatedPosts.astro b/src/components/blog/RelatedPosts.astro new file mode 100644 index 0000000..f4036e9 --- /dev/null +++ b/src/components/blog/RelatedPosts.astro @@ -0,0 +1,31 @@ +--- +import { APP_BLOG } from 'astrowind:config'; + +import { getRelatedPosts } from '~/utils/blog'; +import BlogHighlightedPosts from '../widgets/BlogHighlightedPosts.astro'; +import type { Post } from '~/types'; +import { getBlogPermalink } from '~/utils/permalinks'; + +export interface Props { + post: Post; +} + +const { post } = Astro.props; + +const relatedPosts = post.tags ? await getRelatedPosts(post, 4) : []; +--- + +{ + APP_BLOG.isRelatedPostsEnabled ? ( + post.id)} + /> + ) : null +} diff --git a/src/components/blog/SinglePost.astro b/src/components/blog/SinglePost.astro new file mode 100644 index 0000000..297cca9 --- /dev/null +++ b/src/components/blog/SinglePost.astro @@ -0,0 +1,103 @@ +--- +import { Icon } from 'astro-icon/components'; + +import Image from '~/components/common/Image.astro'; +import PostTags from '~/components/blog/Tags.astro'; +import SocialShare from '~/components/common/SocialShare.astro'; + +import { getPermalink } from '~/utils/permalinks'; +import { getFormattedDate } from '~/utils/utils'; + +import type { Post } from '~/types'; + +export interface Props { + post: Post; + url: string | URL; +} + +const { post, url } = Astro.props; +--- + +
+
+
+
+

+ + + { + post.author && ( + <> + {' '} + · + {post.author} + + ) + } + { + post.category && ( + <> + {' '} + ·{' '} + + {post.category.title} + + + ) + } + { + post.readingTime && ( + <> +  · {post.readingTime} min read + + ) + } +

+
+ +

+ {post.title} +

+

+ {post.excerpt} +

+ + { + post.image ? ( + {post?.excerpt + ) : ( +
+
+
+ ) + } +
+
+ +
+
+ + +
+
+
diff --git a/src/components/blog/Tags.astro b/src/components/blog/Tags.astro new file mode 100644 index 0000000..ae46a24 --- /dev/null +++ b/src/components/blog/Tags.astro @@ -0,0 +1,43 @@ +--- +import { getPermalink } from '~/utils/permalinks'; + +import { APP_BLOG } from 'astrowind:config'; +import type { Post } from '~/types'; + +export interface Props { + tags: Post['tags']; + class?: string; + title?: string | undefined; + isCategory?: boolean; +} + +const { tags, class: className = 'text-sm', title = undefined, isCategory = false } = Astro.props; +--- + +{ + tags && Array.isArray(tags) && ( + <> + {title !== undefined && ( + + {title} + + )} +
    + {tags.map((tag) => ( +
  • + {!APP_BLOG?.tag?.isEnabled ? ( + tag.title + ) : ( + + {tag.title} + + )} +
  • + ))} +
+ + ) +} diff --git a/src/components/blog/ToBlogLink.astro b/src/components/blog/ToBlogLink.astro new file mode 100644 index 0000000..7fb7a49 --- /dev/null +++ b/src/components/blog/ToBlogLink.astro @@ -0,0 +1,20 @@ +--- +import { Icon } from 'astro-icon/components'; +import { getBlogPermalink } from '~/utils/permalinks'; +import { I18N } from 'astrowind:config'; +import Button from '~/components/ui/Button.astro'; + +const { textDirection } = I18N; +--- + +
+ +
diff --git a/src/components/common/Analytics.astro b/src/components/common/Analytics.astro new file mode 100644 index 0000000..a1a553d --- /dev/null +++ b/src/components/common/Analytics.astro @@ -0,0 +1,13 @@ +--- +import { GoogleAnalytics } from '@astrolib/analytics'; +import { ANALYTICS } from 'astrowind:config'; +--- + +{ + ANALYTICS?.vendors?.googleAnalytics?.id ? ( + + ) : null +} diff --git a/src/components/common/ApplyColorMode.astro b/src/components/common/ApplyColorMode.astro new file mode 100644 index 0000000..d0d97fe --- /dev/null +++ b/src/components/common/ApplyColorMode.astro @@ -0,0 +1,33 @@ +--- +import { UI } from 'astrowind:config'; + +// TODO: This code is temporary +--- + + diff --git a/src/components/common/BasicScripts.astro b/src/components/common/BasicScripts.astro new file mode 100644 index 0000000..c7290b2 --- /dev/null +++ b/src/components/common/BasicScripts.astro @@ -0,0 +1,255 @@ +--- +import { UI } from 'astrowind:config'; +--- + + + + diff --git a/src/components/common/CommonMeta.astro b/src/components/common/CommonMeta.astro new file mode 100644 index 0000000..aab6dd4 --- /dev/null +++ b/src/components/common/CommonMeta.astro @@ -0,0 +1,8 @@ +--- +import { getAsset } from '~/utils/permalinks'; +--- + + + + + diff --git a/src/components/common/Image.astro b/src/components/common/Image.astro new file mode 100644 index 0000000..d113b68 --- /dev/null +++ b/src/components/common/Image.astro @@ -0,0 +1,61 @@ +--- +import type { HTMLAttributes } from 'astro/types'; +import { findImage } from '~/utils/images'; +import { + getImagesOptimized, + astroAssetsOptimizer, + unpicOptimizer, + isUnpicCompatible, + type ImageProps, +} from '~/utils/images-optimization'; + +type Props = ImageProps; +type ImageType = { + src: string; + attributes: HTMLAttributes<'img'>; +}; + +const props = Astro.props; + +if (props.alt === undefined || props.alt === null) { + throw new Error(); +} + +if (typeof props.width === 'string') { + props.width = parseInt(props.width); +} + +if (typeof props.height === 'string') { + props.height = parseInt(props.height); +} + +if (!props.loading) { + props.loading = 'lazy'; +} + +if (!props.decoding) { + props.decoding = 'async'; +} + +const _image = await findImage(props.src); + +let image: ImageType | undefined = undefined; + +if ( + typeof _image === 'string' && + (_image.startsWith('http://') || _image.startsWith('https://')) && + isUnpicCompatible(_image) +) { + image = await getImagesOptimized(_image, props, unpicOptimizer); +} else if (_image) { + image = await getImagesOptimized(_image, props, astroAssetsOptimizer); +} +--- + +{ + !image ? ( + + ) : ( + + ) +} diff --git a/src/components/common/Metadata.astro b/src/components/common/Metadata.astro new file mode 100644 index 0000000..a4c573e --- /dev/null +++ b/src/components/common/Metadata.astro @@ -0,0 +1,68 @@ +--- +import merge from 'lodash.merge'; +import { AstroSeo } from '@astrolib/seo'; + +import type { Props as AstroSeoProps } from '@astrolib/seo'; + +import { SITE, METADATA, I18N } from 'astrowind:config'; +import type { MetaData } from '~/types'; +import { getCanonical } from '~/utils/permalinks'; + +import { adaptOpenGraphImages } from '~/utils/images'; + +export interface Props extends MetaData { + dontUseTitleTemplate?: boolean; +} + +const { + title, + ignoreTitleTemplate = false, + canonical = String(getCanonical(String(Astro.url.pathname))), + robots = {}, + description, + openGraph = {}, + twitter = {}, +} = Astro.props; + +const seoProps: AstroSeoProps = merge( + { + title: '', + titleTemplate: '%s', + canonical: canonical, + noindex: true, + nofollow: true, + description: undefined, + openGraph: { + url: canonical, + site_name: SITE?.name, + images: [], + locale: I18N?.language || 'en', + type: 'website', + }, + twitter: { + cardType: openGraph?.images?.length ? 'summary_large_image' : 'summary', + }, + }, + { + title: METADATA?.title?.default, + titleTemplate: METADATA?.title?.template, + noindex: typeof METADATA?.robots?.index !== 'undefined' ? !METADATA.robots.index : undefined, + nofollow: typeof METADATA?.robots?.follow !== 'undefined' ? !METADATA.robots.follow : undefined, + description: METADATA?.description, + openGraph: METADATA?.openGraph, + twitter: METADATA?.twitter, + }, + { + title: title, + titleTemplate: ignoreTitleTemplate ? '%s' : undefined, + canonical: canonical, + noindex: typeof robots?.index !== 'undefined' ? !robots.index : undefined, + nofollow: typeof robots?.follow !== 'undefined' ? !robots.follow : undefined, + description: description, + openGraph: { url: canonical, ...openGraph }, + twitter: twitter, + } +); +--- + + diff --git a/src/components/common/SiteVerification.astro b/src/components/common/SiteVerification.astro new file mode 100644 index 0000000..000baad --- /dev/null +++ b/src/components/common/SiteVerification.astro @@ -0,0 +1,5 @@ +--- +import { SITE } from 'astrowind:config'; +--- + +{SITE.googleSiteVerificationId && } diff --git a/src/components/common/SocialShare.astro b/src/components/common/SocialShare.astro new file mode 100644 index 0000000..d035e8f --- /dev/null +++ b/src/components/common/SocialShare.astro @@ -0,0 +1,65 @@ +--- +import { Icon } from 'astro-icon/components'; + +export interface Props { + text: string; + url: string | URL; + class?: string; +} + +const { text, url, class: className = 'inline-block' } = Astro.props; +--- + +
+ Share: + + + + + +
diff --git a/src/components/common/SplitbeeAnalytics.astro b/src/components/common/SplitbeeAnalytics.astro new file mode 100644 index 0000000..66651db --- /dev/null +++ b/src/components/common/SplitbeeAnalytics.astro @@ -0,0 +1,6 @@ +--- +const { doNotTrack = true, noCookieMode = false, url = 'https://cdn.splitbee.io/sb.js' } = Astro.props; +--- + + + diff --git a/src/components/common/ToggleMenu.astro b/src/components/common/ToggleMenu.astro new file mode 100644 index 0000000..2d19b16 --- /dev/null +++ b/src/components/common/ToggleMenu.astro @@ -0,0 +1,29 @@ +--- +export interface Props { + label?: string; + class?: string; +} + +const { + label = 'Toggle Menu', + class: className = 'flex flex-col h-12 w-12 rounded justify-center items-center cursor-pointer group', +} = Astro.props; +--- + + diff --git a/src/components/common/ToggleTheme.astro b/src/components/common/ToggleTheme.astro new file mode 100644 index 0000000..8f3aafb --- /dev/null +++ b/src/components/common/ToggleTheme.astro @@ -0,0 +1,28 @@ +--- +import { Icon } from 'astro-icon/components'; + +import { UI } from 'astrowind:config'; + +export interface Props { + label?: string; + class?: string; + iconClass?: string; + iconName?: string; +} + +const { + label = 'Toggle between Dark and Light mode', + class: + className = 'text-muted dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center', + iconClass = 'w-6 h-6', + iconName = 'tabler:sun', +} = Astro.props; +--- + +{ + !(UI.theme && UI.theme.endsWith(':only')) && ( + + ) +} diff --git a/src/components/ui/Background.astro b/src/components/ui/Background.astro new file mode 100644 index 0000000..1093c17 --- /dev/null +++ b/src/components/ui/Background.astro @@ -0,0 +1,11 @@ +--- +export interface Props { + isDark?: boolean; +} + +const { isDark = false } = Astro.props; +--- + +
+ +
diff --git a/src/components/ui/Button.astro b/src/components/ui/Button.astro new file mode 100644 index 0000000..d3c2398 --- /dev/null +++ b/src/components/ui/Button.astro @@ -0,0 +1,40 @@ +--- +import { Icon } from 'astro-icon/components'; +import { twMerge } from 'tailwind-merge'; +import type { CallToAction as Props } from '~/types'; + +const { + variant = 'secondary', + target, + text = Astro.slots.render('default'), + icon = '', + class: className = '', + type, + ...rest +} = Astro.props; + +const variants = { + primary: 'btn-primary', + secondary: 'btn-secondary', + tertiary: 'btn btn-tertiary', + link: 'cursor-pointer hover:text-primary', +}; +--- + +{ + type === 'button' || type === 'submit' || type === 'reset' ? ( + + ) : ( + + + {icon && } + + ) +} diff --git a/src/components/ui/DListItem.astro b/src/components/ui/DListItem.astro new file mode 100644 index 0000000..36d4072 --- /dev/null +++ b/src/components/ui/DListItem.astro @@ -0,0 +1,22 @@ +--- +// component: DListItem +// +// Mimics the html 'dl' (description list) +// +// The 'dt' item is the item 'term' and is inserted into an 'h6' tag. +// Caller needs to style the 'h6' tag appropriately. +// +// You can put pretty much any content you want between the open and +// closing tags - it's simply contained in an enclosing div with a +// margin left. No need for 'dd' items. +// +const { dt } = Astro.props; +interface Props { + dt: string; +} + +const content: string = await Astro.slots.render('default'); +--- + +
+
diff --git a/src/components/ui/Form.astro b/src/components/ui/Form.astro new file mode 100644 index 0000000..276b39f --- /dev/null +++ b/src/components/ui/Form.astro @@ -0,0 +1,87 @@ +--- +import type { Form as Props } from '~/types'; +import Button from '~/components/ui/Button.astro'; + +const { inputs, textarea, disclaimer, button = 'Contact us', description = '' } = Astro.props; +--- + +
+ { + inputs && + inputs.map( + ({ type = 'text', name, label = '', autocomplete = 'on', placeholder = '' }) => + name && ( +
+ {label && ( + + )} + +
+ ) + ) + } + + { + textarea && ( +
+ +