feat: update blog structure and content for balodeplao.com

This commit is contained in:
2026-03-10 12:36:58 +09:00
committed by Thuan Bui
parent a300564d0a
commit e14ce351e1
17 changed files with 132 additions and 763 deletions
+54 -26
View File
@@ -1,39 +1,67 @@
# 🚀 Astro Starter Pro # Balodeplao.com — Family Travel Blog
**Astro Starter Pro** is a professional, open-source template for building fast websites using **[Astro 5](https://astro.build/) + [Tailwind CSS 4](https://tailwindcss.com/)**. Designed with industry best practices, optimized SEO, and a modern development experience. Welcome to the codebase for [balodeplao.com](https://balodeplao.com) — our family travel blog! Here, we share stories, tips, and experiences from our journeys around the world. This site is built to inspire, inform, and connect with fellow travelers and families who love to explore.
<br> ---
[![GitHub stars](https://badgen.net/github/stars/devgelo-labs/astro-starter-pro?icon=github&label=Star)](https://github.com/devgelo-labs/astro-starter-pro) ## About
[![Clones](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fangelop47%2Fastro-starter-template%2Fmain%2F.github%2Fdata%2Fclones.json&query=%24.count&label=Clones&color=brightgreen&style=flat-square&logo=github)](https://github.com/devgelo-labs/astro-starter-pro)
[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](./LICENSE)
[![Astro](https://img.shields.io/badge/Astro-5.0-orange?style=flat-square&logo=astro)](https://astro.build/)
[![Tailwind](https://img.shields.io/badge/Tailwind-4.0-38B2AC?style=flat-square&logo=tailwind-css)](https://tailwindcss.com/)
[![Maintainer](https://img.shields.io/badge/maintainer-devgelo-purple?style=flat-square)](https://github.com/devgelo-labs)
<br> This repository hosts the source code for our family travel blog, [balodeplao.com](https://balodeplao.com). The blog features:
<details open> - ✈️ Personal travel stories and guides
<summary>Table of Contents</summary> - 🏝️ Family-friendly destinations and tips
- 📸 Photo galleries and travel inspiration
- 📝 Practical advice for traveling with kids
- [Demo](#demo) ---
- [Features](#features)
- [Tech Stack](#tech-stack)
- [Project Structure](#project-structure)
- [Quick Start](#quick-start)
- [Configuration](#configuration)
- [Content Management](#content-management)
- [Commands](#commands)
- [Support the Project](#support-the-project)
- [License](#license)
</details> ## Tech Stack
<br> This blog is built with modern, high-performance technologies:
## Demo - **[Astro](https://astro.build/)** (based on Astro Starter Theme)
- **[Tailwind CSS](https://tailwindcss.com/)**
- **TypeScript**
- **MDX/Markdown** for content
📌 [https://astrostarterpro.com/](https://astrostarterpro.com/) ---
## Features
- Responsive, fast, and SEO-optimized
- Dark & Light mode
- Content collections for easy blog management
- Reusable components and layouts
- RSS feed, sitemap, and meta tags for discoverability
---
## Getting Started
To run the blog locally:
```bash
git clone https://github.com/10h30/blog-balodeplao.git
cd blog-balodeplao
npm install
npm run dev
```
---
## Contributing
This is a personal/family project, but suggestions and improvements are welcome! Feel free to open an issue or pull request.
---
## License
This project is licensed under the **MIT** license. See the [LICENSE](./LICENSE) file for details.
---
> _Originally based on Astro Starter Theme. Customized and expanded for our family travel blog._
## Features ## Features
+1 -1
View File
@@ -6,7 +6,7 @@ import icon from "astro-icon";
import remarkReadingTime from "remark-reading-time"; import remarkReadingTime from "remark-reading-time";
export default defineConfig({ export default defineConfig({
site: "https://astrostarterpro.com/", site: "https://balodeplao.com/",
integrations: [sitemap(), icon(), mdx()], integrations: [sitemap(), icon(), mdx()],
markdown: { markdown: {
remarkPlugins: [ remarkPlugins: [
-14
View File
@@ -35,14 +35,6 @@ import ThemeToggle from "@/components/ui/ThemeToggle.astro";
</div> </div>
<div class="hidden md:flex items-center gap-4"> <div class="hidden md:flex items-center gap-4">
<a
href={siteConfig.socialLinks.github}
target="_blank"
rel="noopener noreferrer"
class="rounded-full bg-foreground/10 px-4 py-2 text-sm font-semibold text-foreground transition-all hover:bg-foreground/20"
>
GitHub
</a>
<ThemeToggle /> <ThemeToggle />
</div> </div>
@@ -107,12 +99,6 @@ import ThemeToggle from "@/components/ui/ThemeToggle.astro";
</a> </a>
)) ))
} }
<a
href={siteConfig.socialLinks.github}
target="_blank"
class="block rounded-md px-3 py-2 text-base font-medium text-blue-400 transition-colors hover:cursor-pointer hover:bg-blue-500/10 hover:text-blue-300"
>GitHub</a
>
</div> </div>
</div> </div>
</nav> </nav>
-56
View File
@@ -1,56 +0,0 @@
---
import WidgetWrapper from "./WidgetWrapper.astro";
import type { FeaturesProps } from "@/types/types";
import { Icon } from "astro-icon/components";
import Card from "@/components/ui/Card.astro";
import Headline from "@/components/ui/Headline.astro";
const {
features = [],
title,
subtitle,
tagline,
id,
isDark = false,
classes = {},
bg = await Astro.slots.render("bg"),
} = Astro.props as FeaturesProps;
const { container: containerClassProp = "", ...otherClasses } = classes;
---
<WidgetWrapper
id={id}
isDark={isDark}
containerClass={` ${containerClassProp}`}
bg={bg}
classes={otherClasses}
>
<Headline
title={title}
subtitle={subtitle}
tagline={tagline}
classes={{
container: "max-w-3xl mx-auto text-center",
}}
/>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
{
features.map((feature) => (
<Card>
{feature.icon && (
<div
class={`w-12 h-12 rounded-lg flex items-center justify-center mb-6 ${feature.iconClass ? feature.iconClass : "bg-primary/10 text-primary"}`}
>
<Icon name={feature.icon} class="w-6 h-6" />
</div>
)}
<h3 class="text-xl font-bold text-foreground mb-3">
{feature.title}
</h3>
<p class="text-muted-foreground text-sm">{feature.description}</p>
</Card>
))
}
</div>
</WidgetWrapper>
+18 -5
View File
@@ -15,6 +15,7 @@ const {
classes = {}, classes = {},
bg = await Astro.slots.render("bg"), bg = await Astro.slots.render("bg"),
animate = false, animate = false,
bgImage,
} = Astro.props as HeroProps; } = Astro.props as HeroProps;
const { container: containerClassProp = "" } = classes; const { container: containerClassProp = "" } = classes;
@@ -23,11 +24,24 @@ const { container: containerClassProp = "" } = classes;
<WidgetWrapper <WidgetWrapper
id={id} id={id}
isDark={isDark} isDark={isDark}
containerClass={`min-h-[calc(100vh-72px)] flex flex-col justify-center ${containerClassProp}`} containerClass={`min-h-[60vh] flex flex-col justify-center ${containerClassProp}`}
bg={bg} bg={bg}
animate={animate} animate={animate}
> >
<div class="text-center"> {
bgImage && (
<Fragment slot="bg">
<img
src={bgImage}
alt=""
aria-hidden="true"
class="absolute inset-0 h-full w-full object-cover"
/>
<div class="absolute inset-0 bg-black/55" aria-hidden="true" />
</Fragment>
)
}
<div class:list={["text-center", { "relative z-10": bgImage }]}>
{ {
tagline && ( tagline && (
<div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10 border border-primary/20 text-primary text-xs font-semibold mb-6"> <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10 border border-primary/20 text-primary text-xs font-semibold mb-6">
@@ -47,9 +61,8 @@ const { container: containerClassProp = "" } = classes;
titleAs="h1" titleAs="h1"
classes={{ classes={{
container: "mb-0 max-w-none", container: "mb-0 max-w-none",
title: title: `text-5xl md:text-7xl font-extrabold tracking-tight mb-6 ${bgImage ? "text-white" : "text-foreground"}`,
"text-5xl md:text-7xl font-extrabold tracking-tight text-foreground mb-6", subtitle: `max-w-2xl mx-auto text-xl mb-10 ${bgImage ? "text-white/80" : "text-muted-foreground"}`,
subtitle: "max-w-2xl mx-auto text-xl text-muted-foreground mb-10",
}} }}
/> />
) )
-61
View File
@@ -1,61 +0,0 @@
---
import WidgetWrapper from "./WidgetWrapper.astro";
import type { ServiceListProps } from "@/types/types";
import Card from "@/components/ui/Card.astro";
import Headline from "@/components/ui/Headline.astro";
import { Icon } from "astro-icon/components";
const {
services = [],
title = "",
subtitle = "",
tagline = "",
id,
isDark = false,
classes = {},
bg = await Astro.slots.render("bg"),
} = Astro.props as ServiceListProps;
const { container: containerClassProp = "", ...otherClasses } = classes;
---
<WidgetWrapper
id={id}
isDark={isDark}
containerClass={` ${containerClassProp}`}
bg={bg}
classes={otherClasses}
>
<Headline
title={title}
subtitle={subtitle}
tagline={tagline}
classes={{
container: "max-w-3xl mx-auto text-center",
}}
/>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
{
services.map((s) => (
<Card class="group relative overflow-hidden hover:bg-muted/50 hover:shadow-md">
<div class="absolute -right-4 -top-4 text-8xl opacity-10 transition-transform group-hover:scale-110 group-hover:rotate-12 select-none">
<Icon name={s.icon} class="w-32 h-32" />
</div>
<div class="text-left relative z-10">
<div class="text-4xl mb-6 text-primary">
<Icon name={s.icon} class="w-12 h-12" />
</div>
<h3 class="text-2xl font-bold text-foreground mb-4">{s.title}</h3>
<p class="text-muted-foreground leading-relaxed">{s.description}</p>
<button class="mt-8 text-primary font-semibold flex items-center gap-2 group/btn hover:underline transition-all">
View details
<span class="transition-transform group-hover/btn:translate-x-1">
</span>
</button>
</div>
</Card>
))
}
</div>
</WidgetWrapper>
-60
View File
@@ -1,60 +0,0 @@
---
import WidgetWrapper from "./WidgetWrapper.astro";
import type { ValuesProps } from "@/types/types";
import Card from "@/components/ui/Card.astro";
import Headline from "@/components/ui/Headline.astro";
import { Icon } from "astro-icon/components";
const {
items = [],
columns = 2,
title,
subtitle,
tagline,
id,
isDark = false,
classes = {},
bg = await Astro.slots.render("bg"),
} = Astro.props as ValuesProps;
const { container: containerClassProp = "", ...otherClasses } = classes;
const gridCols = {
1: "grid-cols-1",
2: "grid-cols-1 md:grid-cols-2",
3: "grid-cols-1 md:grid-cols-3",
4: "grid-cols-1 md:grid-cols-4",
};
---
<WidgetWrapper
id={id}
isDark={isDark}
containerClass={` ${containerClassProp}`}
bg={bg}
classes={otherClasses}
>
<Headline
title={title}
subtitle={subtitle}
tagline={tagline}
classes={{
container: "max-w-3xl mx-auto text-center",
}}
/>
<div class={`grid ${gridCols[columns]} gap-8 text-left`}>
{
items.map((item) => (
<Card>
{item.icon && (
<div class="mb-4 text-primary text-4xl">
<Icon name={item.icon} class="w-12 h-12" />
</div>
)}
<h3 class="text-xl font-bold text-foreground mb-2">{item.title}</h3>
<p class="text-sm text-muted-foreground">{item.description}</p>
</Card>
))
}
</div>
</WidgetWrapper>
+2 -1
View File
@@ -19,12 +19,13 @@ const wrapperClasses = {
<div <div
id={id} id={id}
class:list={[ class:list={[
"relative not-prose scroll-mt-[72px]", "relative not-prose scroll-mt-18 overflow-hidden",
bg, bg,
{ dark: isDark }, { dark: isDark },
{ reveal: animate }, { reveal: animate },
]} ]}
> >
<slot name="bg" />
<div <div
class:list={[ class:list={[
"relative mx-auto max-w-7xl px-4 md:px-6 text-default py-8 md:py-12", "relative mx-auto max-w-7xl px-4 md:px-6 text-default py-8 md:py-12",
+3 -4
View File
@@ -1,9 +1,9 @@
import ogImage from "@/assets/og-image.png"; import ogImage from "@/assets/og-image.png";
export const siteConfig = { export const siteConfig = {
name: "Astro Starter Pro", name: "Ba Lô & Dép Lào",
description: "Just another Astro blog", description: "You only live once. Make it count!",
url: "https://thuanbui.me", url: "https://balodeplao.com",
lang: "vi", lang: "vi",
locale: "vi_VN", locale: "vi_VN",
author: "Thuan Bui", author: "Thuan Bui",
@@ -15,7 +15,6 @@ export const siteConfig = {
}, },
navLinks: [ navLinks: [
{ text: "Home", href: "/" }, { text: "Home", href: "/" },
{ text: "About", href: "/about" },
{ text: "Blog", href: "/blog" }, { text: "Blog", href: "/blog" },
{ text: "Contact", href: "/contact" }, { text: "Contact", href: "/contact" },
], ],
+1 -1
View File
@@ -101,7 +101,7 @@ const finalIgnoreTitleTemplate = metadata?.ignoreTitleTemplate || false;
</div> </div>
<Navbar /> <Navbar />
<main id="main-content" class="relative z-10 grow pt-[72px]"> <main id="main-content" class="relative z-10 grow pt-18">
<slot /> <slot />
</main> </main>
<Footer /> <Footer />
-8
View File
@@ -2,7 +2,6 @@
import BaseLayout from "@/layouts/BaseLayout.astro"; import BaseLayout from "@/layouts/BaseLayout.astro";
import { getImage } from "astro:assets"; import { getImage } from "astro:assets";
import Content2 from "@/components/widgets/Content2.astro"; import Content2 from "@/components/widgets/Content2.astro";
import Values from "@/components/widgets/Values.astro";
import aboutImage from "@/assets/images/about-office.webp"; import aboutImage from "@/assets/images/about-office.webp";
const metadata = { const metadata = {
@@ -76,11 +75,4 @@ const optimizedImage = await getImage({
}, },
]} ]}
/> />
<Values
items={values}
columns={3}
tagline="Our Values"
title="What Defines Us"
subtitle="Principles that guide our daily work"
/>
</BaseLayout> </BaseLayout>
+1 -2
View File
@@ -35,8 +35,7 @@ const metadata = {
<div class="relative mx-auto max-w-5xl"> <div class="relative mx-auto max-w-5xl">
<Headline <Headline
tagline="Blog" tagline="Blog"
title="Our Publications" title="Our Journey and Adventures"
subtitle="Explore the latest news, tutorials, and articles from our team."
classes={{ classes={{
container: "reveal mb-12 text-center", container: "reveal mb-12 text-center",
title: title:
-45
View File
@@ -1,6 +1,5 @@
--- ---
import BaseLayout from "@/layouts/BaseLayout.astro"; import BaseLayout from "@/layouts/BaseLayout.astro";
import Features from "@/components/widgets/Features.astro";
import Content from "@/components/widgets/Content.astro"; import Content from "@/components/widgets/Content.astro";
import Form from "@/components/ui/Form.astro"; import Form from "@/components/ui/Form.astro";
@@ -19,48 +18,4 @@ const visionText = ["Get in touch with us to discuss your next project."];
> >
<Form /> <Form />
</div> </div>
<Features
tagline="Contact Means"
title="We are here to help you"
subtitle="Choose the communication channel you prefer. We respond in less than 24 hours."
classes={{ container: "pt-0 md:pt-0" }}
features={[
{
title: "Phone",
description: "+123 456 7890",
icon: "lucide:phone",
iconClass: "bg-green-500/10 text-green-400",
},
{
title: "Email",
description: "contact@company.com",
icon: "lucide:mail",
iconClass: "bg-yellow-500/10 text-yellow-400",
},
{
title: "Location",
description: "City, Country",
icon: "lucide:map-pin",
iconClass: "bg-red-500/10 text-red-400",
},
{
title: "Personalized Attention",
description: "We understand your needs to offer tailored solutions.",
icon: "lucide:user-check",
iconClass: "bg-blue-500/10 text-blue-400",
},
{
title: "Technical Support",
description: "We resolve any doubt or technical incident quickly.",
icon: "lucide:wrench",
iconClass: "bg-purple-500/10 text-purple-400",
},
{
title: "Strategic Consulting",
description: "We advise you to ensure the success of your project.",
icon: "lucide:briefcase",
iconClass: "bg-pink-500/10 text-pink-400",
},
]}
/>
</BaseLayout> </BaseLayout>
+51 -120
View File
@@ -2,133 +2,64 @@
import BaseLayout from "@/layouts/BaseLayout.astro"; import BaseLayout from "@/layouts/BaseLayout.astro";
import { siteConfig } from "@/config/site"; import { siteConfig } from "@/config/site";
import Hero from "@/components/widgets/Hero.astro"; import Hero from "@/components/widgets/Hero.astro";
import Features from "@/components/widgets/Features.astro"; import PostItem from "@/components/blog/PostItem.astro";
import devImg from "@/assets/images/dev_balanced.png"; import { getCollection } from "astro:content";
import openSourceImg from "@/assets/images/open-source.png";
import Content2 from "@/components/widgets/Content2.astro";
const metadata = { const metadata = {
title: `${siteConfig.name} — The next step for your project`, title: `${siteConfig.name} — You Only Live Once`,
description: description:
"A modern and professional template for your web projects with Astro and Tailwind CSS. Boost your development with a solid foundation.", "Chào mừng bạn đến với blog của chúng tôi, nơi chúng tôi chia sẻ những câu chuyện, kiến thức và trải nghiệm về cuộc sống. Hãy cùng khám phá và tận hưởng hành trình này nhé!",
ignoreTitleTemplate: true, ignoreTitleTemplate: true,
}; };
const blogEntries = await getCollection("blog");
const latestPosts = blogEntries
.filter((post) => post.data && post.data.pubDate)
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf())
.slice(0, 5);
const firstRow = latestPosts.slice(0, 2);
const secondRow = latestPosts.slice(2, 5);
--- ---
<BaseLayout {metadata}> <BaseLayout {metadata}>
<Hero <Hero
title={`Starter Template for <br class="hidden md:block" /> <span class="bg-linear-to-r from-blue-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">Web Developers</span>`} title={`You Only Live Once`}
tagline="Astro v5 + Tailwind v4" tagline=""
description={`${siteConfig.description}`} description=""
actions={[ bgImage="https://images.balodeplao.com/460cc863-81ff-44b4-811f-422558bd2078.jpg"
{
text: "Get Started",
href: "https://github.com/devgelo-labs/astro-starter-pro",
variant: "primary",
icon: "lucide:github",
},
{
text: "Our Services",
href: "/services",
variant: "secondary",
icon: "lucide:arrow-right",
ariaLabel: "Learn more about our services",
},
]}
/> />
<Features
tagline="Features" <section class="relative px-4 py-12 sm:px-6 lg:px-8 md:py-36">
title="What's Included" <div class="mx-auto max-w-5xl">
subtitle="A selection of tools and configurations to streamline your workflow." <div class="grid gap-8 md:grid-cols-2 mb-8">
features={[ {firstRow.map((post) => <PostItem post={post} />)}
{ </div>
title: "Optimized SEO",
description: <div class="grid gap-8 md:grid-cols-3 mb-12">
"Base configuration for Meta tags, Open Graph, and Sitemap generation.", {secondRow.map((post) => <PostItem post={post} />)}
icon: "lucide:scan-search", </div>
iconClass: "bg-blue-500/10 text-blue-400",
}, <div class="text-center">
{ <a
title: "High Performance", href="/blog"
description: "Lightweight structure for fast load times.", class="inline-flex items-center gap-2 rounded-xl border border-border bg-card px-6 py-3 text-sm font-medium text-foreground transition-colors hover:bg-muted"
icon: "lucide:zap", >
iconClass: "bg-purple-500/10 text-purple-400", Xem tất cả bài viết
}, <svg
{ xmlns="http://www.w3.org/2000/svg"
title: "Tailwind v4", class="h-4 w-4"
description: viewBox="0 0 24 24"
"Integrated configuration with the latest version of Tailwind CSS.", fill="none"
icon: "lucide:palette", stroke="currentColor"
iconClass: "bg-pink-500/10 text-pink-400", stroke-width="2"
}, stroke-linecap="round"
]} stroke-linejoin="round"
/> >
<Content2 <path d="M5 12h14M12 5l7 7-7 7"></path>
items={[ </svg>
{ </a>
title: "Responsive Design", </div>
description: </div>
"Base configuration for Meta tags, Open Graph, and Sitemap generation.", </section>
icon: "lucide:scan-search",
iconClass: "bg-blue-500/10 text-blue-400",
},
{
title: "High Performance",
description: "Lightweight structure for fast load times.",
icon: "lucide:zap",
iconClass: "bg-purple-500/10 text-purple-400",
},
{
title: "Tailwind v4",
description:
"Integrated configuration with the latest version of Tailwind CSS.",
icon: "lucide:palette",
iconClass: "bg-pink-500/10 text-pink-400",
},
]}
image={devImg}
imageAlt="Development"
>
<Fragment>
<h3 class="text-2xl font-bold tracking-tight sm:text-3xl mb-2">
Development
</h3>
We provide a solid foundation to start your projects with best practices.
</Fragment>
</Content2>
<Content2
items={[
{
title: "Open Source",
description:
"Developed under the MIT license, free for personal and commercial use.",
icon: "lucide:github",
iconClass: "bg-indigo-500/10 text-indigo-400",
},
{
title: "Community Driven",
description:
"Built with the feedback and contributions of the developer community.",
icon: "lucide:users",
iconClass: "bg-orange-500/10 text-orange-400",
},
{
title: "Regular Updates",
description:
"Continuously improved with the latest technologies and best practices.",
icon: "lucide:refresh-cw",
iconClass: "bg-teal-500/10 text-teal-400",
},
]}
image={openSourceImg}
imageAlt="Community and Open Source"
isReversed={true}
>
<Fragment>
<h3 class="text-2xl font-bold tracking-tight sm:text-3xl mb-2">
Open Source & Community
</h3>
Join the revolution of modern web development. This project is open for everyone
to use, learn from, and contribute to.
</Fragment>
</Content2>
</BaseLayout> </BaseLayout>
-128
View File
@@ -1,128 +0,0 @@
---
import BaseLayout from "@/layouts/BaseLayout.astro";
import ServiceList from "@/components/widgets/ServiceList.astro";
import Content from "@/components/widgets/Content.astro";
import Content2 from "@/components/widgets/Content2.astro";
import webDevImg from "@/assets/images/services/web-dev.webp";
import seoImg from "@/assets/images/services/seo.webp";
import consultingImg from "@/assets/images/services/consulting.webp";
const services = [
{
title: "Web Development",
description: "Static and dynamic sites built for the modern era.",
icon: "lucide:globe",
},
{
title: "SEO Optimization",
description: "We ensure your content is found by those looking for it.",
icon: "lucide:search",
},
{
title: "IT Consulting",
description: "Technical advice to scale your projects to the next level.",
icon: "lucide:rocket",
},
];
const metadata = {
title: "Services",
description:
"Discover our web development, SEO optimization, and technology consulting services.",
};
---
<BaseLayout {metadata}>
<Content
tagline="Services"
title="Our Services"
description={[
"Comprehensive solutions designed to maximize the potential of your digital presence.",
]}
/>
<ServiceList services={services} classes={{ container: "pt-0 md:pt-0" }} />
<Content
tagline="Web Development"
title="Modern Web Development"
description={[
"We specialize in building fast, secure, and scalable websites using the latest technologies. We transform your vision into an impactful digital experience.",
]}
classes={{ container: "pb-0 md:pb-0" }}
/>
<Content2
items={[
{
title: "Responsive Design",
description:
"Your site will look perfect on any device, from mobiles to desktop screens.",
},
{
title: "Optimized Performance",
description:
"Fast loading to improve user experience and SEO positioning.",
},
]}
image={webDevImg}
imageAlt="Modern Web Development"
classes={{ container: "pt-0 md:pt-0" }}
>
<Fragment>
<h3 class="text-2xl font-bold tracking-tight sm:text-3xl mb-2">
Modern Web Development
</h3>
We specialize in building fast, secure, and scalable websites using the latest
technologies. We transform your vision into an impactful digital experience.
</Fragment>
</Content2>
<Content2
isReversed={true}
items={[
{
title: "SEO Audit",
description:
"We deeply analyze your website to identify technical and content improvement opportunities.",
},
{
title: "Content Strategy",
description:
"We create relevant content plans that attract and retain your target audience.",
},
]}
image={seoImg}
imageAlt="SEO Strategies"
>
<Fragment>
<h3 class="text-2xl font-bold tracking-tight sm:text-3xl mb-2">
SEO Optimization
</h3>
We help your business get found by the right people. Our organic positioning
strategies are designed to improve your organic visibility.
</Fragment>
</Content2>
<Content2
items={[
{
title: "Digital Transformation",
description:
"We guide you in adopting new technologies to optimize your business processes.",
},
{
title: "Software Architecture",
description:
"We design robust and scalable systems prepared for future growth.",
},
]}
image={consultingImg}
imageAlt="Technology Consulting"
>
<Fragment>
<h3 class="text-2xl font-bold tracking-tight sm:text-3xl mb-2">
Technology Consulting
</h3>
We accompany you in critical decision-making. We evaluate your current infrastructure
and design personalized roadmaps to take your company to the next technological
level.
</Fragment>
</Content2>
</BaseLayout>
-231
View File
@@ -1,231 +0,0 @@
---
import BaseLayout from "@/layouts/BaseLayout.astro";
import Hero from "@/components/widgets/Hero.astro";
import Features from "@/components/widgets/Features.astro";
import Content from "@/components/widgets/Content.astro";
import Content2 from "@/components/widgets/Content2.astro";
import ServiceList from "@/components/widgets/ServiceList.astro";
import Values from "@/components/widgets/Values.astro";
import aboutImage from "@/assets/images/about-office.webp";
const heroProps = {
title: "Lorem Ipsum Dolor Sit Amet",
tagline: "Hero",
description:
"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
actions: [
{
text: "Get Started",
href: "https://github.com/devgelo-labs/astro-starter-pro",
variant: "primary",
icon: "lucide:github",
},
{
text: "View Details",
href: "#",
variant: "secondary",
icon: "lucide:arrow-right",
},
],
};
const featuresProps = {
title: "Quis Nostrud Exercitation",
subtitle: "Ullamco laboris nisi ut aliquip ex ea commodo",
tagline: "Features",
features: [
{
title: "Lorem Ipsum",
description: "Dolor sit amet, consectetur adipiscing elit.",
icon: "lucide:box",
},
{
title: "Sed Do Eiusmod",
description: "Tempor incididunt ut labore et dolore magna aliqua.",
icon: "lucide:check",
},
{
title: "Ut Enim Ad",
description: "Minim veniam, quis nostrud exercitation ullamco.",
icon: "lucide:eye",
},
],
};
const contentProps = {
title: "Duis Aute Irure Dolor",
description: [
"In reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.",
],
tagline: "Content",
image: aboutImage,
imageAlt: "Placeholder image",
isReversed: false,
actions: [
{
text: "Call to Action",
href: "#",
variant: "primary",
icon: "lucide:github",
},
{
text: "View details",
href: "#",
variant: "secondary",
icon: "lucide:arrow-right",
},
],
};
const content2Props = {
title: "Duis Aute Irure Dolor",
description: [
"In reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.",
],
tagline: "Content2",
image: aboutImage,
imageAlt: "Placeholder image",
isReversed: false,
actions: [
{
text: "Call to Action",
href: "#",
variant: "primary",
icon: "lucide:github",
},
{
text: "View details",
href: "#",
variant: "secondary",
icon: "lucide:arrow-right",
},
],
};
const content2InvertedProps = {
items: [
{
title: "Open Source",
description:
"Developed under the MIT license, free for personal and commercial use.",
icon: "lucide:github",
iconClass: "bg-indigo-500/10 text-indigo-400",
},
{
title: "Community Driven",
description:
"Built with the feedback and contributions of the developer community.",
icon: "lucide:users",
iconClass: "bg-orange-500/10 text-orange-400",
},
{
title: "Regular Updates",
description:
"Continuously improved with the latest technologies and best practices.",
icon: "lucide:refresh-cw",
iconClass: "bg-teal-500/10 text-teal-400",
},
],
image: aboutImage,
imageAlt: "Community and Open Source",
isReversed: true,
actions: [
{
text: "Call to Action",
href: "#",
variant: "primary",
icon: "lucide:github",
},
{
text: "View details",
href: "#",
variant: "secondary",
icon: "lucide:arrow-right",
},
],
title: "Open Source",
subtitle:
"Built with the feedback and contributions of the developer community.",
tagline: "Content2",
};
const serviceListProps = {
services: [
{
title: "Voluptatem Accusantium",
description: "Doloremque laudantium, totam rem aperiam.",
icon: "lucide:rocket",
},
{
title: "Ipsa Quae Ab",
description: "Illo inventore veritatis et quasi architecto.",
icon: "lucide:lightbulb",
},
{
title: "Beatae Vitae Dicta",
description: "Sunt explicabo. Nemo enim ipsam voluptatem.",
icon: "lucide:wrench",
},
],
title: "Services that will help you achieve your goals",
subtitle: "What we offer",
tagline: "Services",
};
const valuesProps = {
items: [
{
title: "Corporate",
description:
"Curabitur dignissim, felis non sollicitudin molestie, urna mauris pellentesque velit, ut eleifend.",
},
{
title: "Creative",
description:
"Aenean condimentum finibus mauris, a fermentum justo pan eget. Sed ultricies, neque quis.",
},
{
title: "Startups",
description:
"Donec sed orci tincidunt, aliquam nisl a, condimentum nunc. Nulla varius ex nec ante feugiat.",
},
{
title: "SaaS",
description:
"Phasellus tristique, elit dapibus cursus facilisis, lorem augue fringilla nunc, vitae fermentum.",
},
{
title: "Education",
description:
"In hac habitasse platea dictumst. Vivamus adipiscing fermentum quam volutpat aliquam. Integer et.",
},
{
title: "Real Estate",
description:
"Fusce at massa nec sapien auctor gravida in in tellus. Vivamus a tristique metus, et molestie.",
},
],
columns: 3 as const,
tagline: "Values",
title: "What defines us",
subtitle: "Principles that guide our daily work",
};
const metadata = {
title: "Widgets - Astro Starter Pro",
description: "Showcase of available components and widgets.",
ignoreTitleTemplate: true,
};
---
<BaseLayout {metadata}>
<Hero {...heroProps} />
<Features {...featuresProps} />
<Content {...contentProps} />
<Content2 {...content2Props} />
<Content2 {...content2InvertedProps} />
<ServiceList {...serviceListProps} />
<Values {...valuesProps} />
</BaseLayout>
+1
View File
@@ -46,6 +46,7 @@ export interface HeroProps extends HeadlineProps {
description?: string; // override or additional? Hero has description, Headline has subtitle. Hero has actions. description?: string; // override or additional? Hero has description, Headline has subtitle. Hero has actions.
actions?: string | CallToAction[]; actions?: string | CallToAction[];
image?: ImageMetadata | string; // Just in case, though checked Hero.astro and it uses slots mostly or props. image?: ImageMetadata | string; // Just in case, though checked Hero.astro and it uses slots mostly or props.
bgImage?: string;
} }
export interface FeaturesProps extends HeadlineProps { export interface FeaturesProps extends HeadlineProps {