first commit

This commit is contained in:
EFEELE
2025-04-07 15:50:13 -06:00
commit c2421d79c5
124 changed files with 12129 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
---
import Layout from "../../layouts/Layout.astro";
import Hero from "../../components/blog/Hero.astro";
import Tags from "../../components/blog/Tags.astro";
import ListPosts from "../../components/blog/ListPosts.astro";
const pageTitle = "Web Development and Technology Blog | Fernando López | EFEELE";
const description = "Welcome to my blog, where I share my passion for frontend development, web design, and the latest technology trends.";
const ogimage = {
url: "/images/blogimage.webp",
alt: "EFEELE.dev logo with green background and light effect. Text: 'Web Development and Technology Blog' and URL 'www.efeele.dev'.",
};
const currentUrl = `https://efeele.dev${Astro.url.pathname}`;
const tweetText = encodeURIComponent(`"${pageTitle}"`);
import Heading from "../../components/ui/Heading.astro";
import Share from "../../components/ui/Share.astro";
import Languages from "../../components/blog/Languages.astro";
---
<Layout pageTitle={pageTitle} description={description} ogimage={ogimage}>
<div class="relative mx-auto max-w-7xl px-8 max-sm:px-4 gap-6">
<div
class="grid my-8 grid-cols-3 grid-rows-1 max-lg:grid-cols-1 max-lg:grid-rows-[1fr_auto] gap-12 max-md:gap-4"
>
<div class="lg:col-span-2">
<ListPosts all={true} />
</div>
<div class="lg:col-start-3">
<div
class="bg-white dark:bg-transparent w-full mt-0 rounded-2xl dark:border-0 border border-neutral-100 top-14 px-6 pt-8 pb-12"
>
<div class="flex flex-col gap-4 pl-0">
<Heading textGradient="Categories" />
<Tags variant="compact" />
</div>
</div>
<div
class="bg-white dark:bg-transparent w-full mt-8 rounded-2xl dark:border-0 border border-neutral-100 top-14 px-6 pt-8 pb-12"
>
<div class="flex flex-col gap-4 pl-0">
<Heading textGradient="Technologies" level={2} />
<Languages level={2} />
</div>
</div>
<div class="my-8 flex justify-end">
<Share currentUrl={currentUrl} tweetText={tweetText} />
</div>
</div>
</div>
</div>
</Layout>

View File

@@ -0,0 +1,22 @@
---
import Layout from "../../layouts/Layout.astro";
import Hero from "../../components/blog/Hero.astro";
import Tags from "../../components/blog/Tags.astro";
import ListPosts from "../../components/blog/ListPosts.astro";
const pageTitle = "Web Development and Technology Blog | Fernando López | EFEELE";
const description = "Welcome to my blog, where I share my passion for frontend development, web design, and the latest technology trends.";
const ogimage ={
url: "/images/blogimage.webp",
alt: "EFEELE.dev logo with green background and light effect. Text: 'Web Development and Technology Blog' and URL 'www.efeele.dev'."
};
---
<Layout pageTitle={pageTitle} description={description} ogimage={ogimage}>
<Hero />
<Tags />
<div class="px-8 max-sm:px-4">
<ListPosts />
</div>
</Layout>

View File

@@ -0,0 +1,240 @@
---
layout: /src/layouts/MarkdownPostLayout.astro
title: Create an Animated Border with Tailwind CSS
author: Fernando López
description: "Add a dynamic touch to your designs with an animated border in Tailwind CSS. Learn how to use conic-gradient and animations to achieve an impressive visual effect. 🚀✨"
image:
url: "/images/posts/animated-borders-tailwind.webp"
alt: "Example of animated borders with Tailwind CSS in a dark design, featuring a vibrant color gradient background."
pubDate: 2025-03-27
tags:
[
"CSS", "Tailwind", "Animation", "Frontend", "UI"
]
languages: ["tailwind", "html", ]
---
The `border` property in CSS cannot be animated natively. However, we can simulate this effect by using a `div` with an animated background and placing the content inside a child element with `padding`, which will act as the "thickness" of the border.
This method might seem complex for those who don't frequently work with CSS or frameworks like Tailwind CSS, but you'll see that it's not that difficult and the final result is quite satisfying.
## Types of Gradients in CSS
To achieve our animated border effect, we need to know the different types of gradients in CSS:
- **Linear Gradient:** Linear gradient along a specific direction.
- [Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient)
- **Radial Gradient:** Radial gradient from a central point outward.
- [Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/radial-gradient)
- **Conic Gradient:** Conic gradient around a central point, creating a "wheel" effect.
- [Documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/conic-gradient)
For our animated border, we'll use **conic gradient**, as it allows us to create a spinning effect.
## Implementing the Animated Border
```html
<div
class="w-full max-w-lg bg-conic/[from_0deg] from-white to-white dark:from-black via-green-400 dark:to-black rounded-2xl p-px"
>
<div class="p-10 rounded-2xl bg-transparent">
<p class="text-white text-center font-semibold ">
Parent container background
</p>
</div>
</div>
```
<div class="w-full max-w-lg bg-conic/[from_0deg] from-white to-white dark:from-black via-green-400 dark:to-black rounded-2xl p-px">
<div class="p-10 rounded-2xl bg-transparent">
<p class="text-white text-center font-semibold mt-8">
Parent container background
</p>
</div>
</div>
<br>
<hr>
<br>
If we add a background to the child container, we achieve the border effect:
```html
<div
class="w-full max-w-lg bg-conic/[from_0deg] from-white to-white dark:from-black via-green-400 dark:to-black rounded-2xl p-px"
>
<!-- Parent container -->
<div class="p-10 rounded-2xl dark:dark:bg-zinc-900 bg-mint-50">
<!-- Child container -->
<p class="text-white text-center font-semibold">
By adding a background to the child container, we achieve the border effect
</p>
</div>
</div>
```
<div class="w-full max-w-lg bg-conic/[from_0deg] from-white to-white dark:from-black via-green-400 dark:to-black rounded-2xl p-px">
<div class="p-10 rounded-2xl dark:bg-zinc-900 bg-zinc-50">
<p class="text-white text-center font-semibold mt-8">
By adding a background to the child container, we achieve the border effect
</p>
</div>
</div>
## Adding Animation with `@property`
We'll use `@property` to define a custom property that will allow us to animate the border:
```css
@property --border-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
```
Then, we create the animation with `@keyframes` and add it to the Tailwind CSS theme:
```css
@theme {
--animate-rotate-border: border-rotate 3s linear infinite;
@keyframes border-rotate {
to {
--border-angle: 360deg;
}
}
}
```
Now we'll implement it in our parent container classes:
```html
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-white to-white dark:from-black via-green-400 dark:to-black animate-rotate-border rounded-2xl p-px"
>
<div class="p-10 rounded-2xl bg-transparent">
<p class="text-white text-center font-semibold">
Animated parent container background
</p>
</div>
</div>
```
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-white to-white dark:from-black via-green-400 dark:to-black animate-rotate-border rounded-2xl p-px">
<div class="p-10 rounded-2xl bg-transparent">
<p class="text-white text-center font-semibold mt-8">
Animated parent container background
</p>
</div>
</div>
<br>
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-white to-white dark:from-black via-green-400 dark:to-black animate-rotate-border rounded-2xl p-px"
>
<div class="p-10 rounded-2xl dark:bg-zinc-900 bg-zinc-50">
<p class="text-white text-center font-semibold mt-8">
This is how it looks with a background in our content
</p>
</div>
</div>
## Adjusting the Border Thickness
By modifying the `padding`, we can control the border thickness:
```html
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-white to-white dark:from-black via-green-400 dark:to-black animate-rotate-border rounded-2xl p-[3px]"
>
<div class="p-10 rounded-2xl dark:bg-zinc-900 bg-zinc-50">
<p class="text-white text-center font-semibold">
By adjusting the padding we can "increase the border thickness"
<br />
<code>p-[3px]</code>
</p>
</div>
</div>
```
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-white to-white dark:from-black via-green-400 dark:to-black animate-rotate-border rounded-2xl p-[3px]"
>
<div class="p-10 rounded-2xl dark:bg-zinc-900 bg-zinc-50">
<p class="text-white text-center font-semibold mt-8">
By adjusting the padding we can "increase the border thickness"
<br>
<code>p-[3px]</code>
</p>
</div>
</div>
## Customizing the Gradient
In Tailwind CSS, we can control the position of the gradient colors:
- `from-*` → Starting color of the gradient.
- `via-*` → Intermediate color.
- `to-*` → Final color of the gradient.
We can also adjust the color positions, for example:
```html
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-white to-white dark:from-black via-green-400 dark:to-black from-30% to-60% animate-rotate-border rounded-2xl p-px"
>
<div class="p-10 rounded-2xl bg-transparent">
<p class="text-white text-center font-semibold">
By adjusting the color positions we achieve a different effect
<br />
<code>from-30% to-60%</code>
</p>
</div>
</div>
```
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-white to-white dark:from-black via-green-400 dark:to-black from-30% to-60% animate-rotate-border rounded-2xl p-px"
>
<div class="p-10 rounded-2xl bg-transparent">
<p class="text-white text-center font-semibold mt-8">
By adjusting the color positions we achieve a different effect
<br />
<code>from-30% to-60%</code>
</p>
</div>
</div>
## Final Result
I'll make some small adjustments, changing the from and to colors to achieve a more natural effect. Also, I'll use a 1px padding.
```html
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-green-200/20 via-green-400 to-green-200/20 from-30% to-60% animate-rotate-border rounded-2xl p-px"
>
<div class="p-10 rounded-2xl dark:bg-zinc-900 bg-zinc-50">
<p class="text-white text-center font-semibold">
This is the final result
</p>
</div>
</div>
```
<div
class="w-full max-w-lg bg-conic/[from_var(--border-angle)] from-green-200/20 via-green-400 to-green-200/20 from-30% to-60% animate-rotate-border rounded-2xl p-px"
>
<div class="p-10 rounded-2xl dark:bg-zinc-900 bg-zinc-50">
<p class="text-white text-center font-semibold mt-8">
This is the final result
</p>
</div>
</div>
## Conclusion
I hope this guide has helped you understand how to create an animated border with Tailwind CSS and that you can implement it in your projects. Experiment with gradients and animations to get unique effects! 🎨✨

View File

@@ -0,0 +1,164 @@
---
layout: /src/layouts/MarkdownPostLayout.astro
title: The Complete Markdown Guide
author: Fernando López
description: "A comprehensive guide to Markdown syntax, covering everything from basic formatting to advanced features. Learn how to create headers, lists, emphasis, and more with this essential markup language for content creation."
image:
url: "/images/posts/markdown.webp"
alt: "Example of animated borders with Tailwind CSS in a dark design, featuring a vibrant color gradient background."
pubDate: 2025-04-05
tags:
[
"documentation", "tutorial", "web-development", "content-creation", "writing"
]
languages: ["markdown", "html", "css"]
---
Markdown is a lightweight markup language that you can use to add formatting elements to plaintext text documents. Created by John Gruber in 2004, Markdown is now one of the world's most popular markup languages.
## Basic Syntax
### Headers
```markdown
# H1
## H2
### H3
#### H4
##### H5
###### H6
```
### Emphasis
```markdown
*Italic text* or _Italic text_
**Bold text** or __Bold text__
***Bold and italic*** or ___Bold and italic___
~~Strikethrough~~
```
### Lists
#### Unordered Lists
```markdown
- First item
- Second item
- Third item
- Indented item
- Another indented item
```
#### Ordered Lists
```markdown
1. First item
2. Second item
3. Third item
1. Indented item
2. Another indented item
```
### Links and Images
```markdown
[Link text](https://www.example.com)
![Alt text](image.jpg)
```
### Code
#### Inline Code
```markdown
Use `code` in your text
```
#### Code Blocks
````markdown
```javascript
const hello = "world";
console.log(hello);
```
````
### Blockquotes
```markdown
> This is a blockquote
>
> It can span multiple lines
```
### Horizontal Rules
```markdown
---
***
___
```
## Extended Syntax
### Tables
```markdown
| Syntax | Description |
| ----------- | ----------- |
| Header | Title |
| Paragraph | Text |
```
### Task Lists
```markdown
- [x] Write the press release
- [ ] Update the website
- [ ] Contact the media
```
### Footnotes
```markdown
Here's a sentence with a footnote. [^1]
[^1]: This is the footnote.
```
### Emoji
```markdown
:smile: :heart: :rocket:
```
### Highlight
```markdown
==highlighted text==
```
## Best Practices
1. **Keep it Simple**: Markdown is meant to be easy to read and write.
2. **Use Consistent Formatting**: Stick to one style for similar elements.
3. **Add Whitespace**: Use blank lines to separate different sections.
4. **Use Headers Properly**: Start with H1 and use lower levels for subsections.
5. **Escape Special Characters**: Use backslash to escape special characters.
## Common Pitfalls
- Forgetting to add spaces after headers
- Not properly indenting nested lists
- Mixing different list markers
- Not escaping special characters when needed
## Tools and Resources
- [Markdown Guide](https://www.markdownguide.org/)
- [Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)
- [Dillinger](https://dillinger.io/) - Online Markdown Editor
- [Markdown Preview](https://markdownlivepreview.com/) - Live Preview Tool
## Conclusion
Markdown is a powerful tool for creating well-formatted documents quickly and efficiently. Whether you're writing documentation, taking notes, or creating content for the web, Markdown provides a simple yet effective way to structure your text.
Remember: The best way to learn Markdown is to practice! Try creating your own documents and experiment with different syntax elements.

View File

@@ -0,0 +1,197 @@
---
layout: /src/layouts/MarkdownPostLayout.astro
title: NeonMint Template Documentation
author: Fernando López
description: "NeonMint is a modern, minimalist template crafted for developers and digital creatives. Its dark-themed layout with mint green highlights delivers a sleek, elegant, and functional visual experience—perfect for portfolios, dashboards, or tech landing pages."
image:
url: "/images/projects/neonmint.webp"
alt: "Screenshot of NeonMint, a modern and minimalist web template built with Astro and TailwindCSS. It displays various sections such as blog, portfolio, work experience, and Markdown guide, in both light and dark modes with mint green accents."
pubDate: 2025-04-04
tags:
[
"documentation", "portfolio", "web-development", "astro", "tailwindcss"
]
languages: ["astro", "javascript", "tailwind", "markdown"]
---
## 🎯 Overview
**NeonMint** is a minimalist and modern template designed for developers and digital creatives. Its dark-toned aesthetic with mint green accents offers a clean, elegant, and functional visual experience, ideal for portfolios, dashboards, or tech landing pages.
## 📁 Project Structure
```bash
└── 📁NeonMint
└── 📁public
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon.png
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon.ico
└── 📁images
├── 📁posts # Post images
└── 📁projects # Project images
└── site.webmanifest # PWA configuration file
└── 📁src
├── 📁components # Reusable UI components
│ ├── 📁blog # Blog components
│ ├── 📁layout # Layout components
│ ├── 📁portfolio # Portfolio components
│ └── 📁ui # UI components
├── 📁icons # Icons (.svg)
├── 📁layouts # Site layouts
│ ├── Layout.astro # Main application layout
│ ├── MarkdownAbout.astro # About-me page layout
│ ├── MarkdownPostLayout.astro # Posts page layout
│ └── ProjectLayout.astro # Projects page layout
├── 📁pages # Site pages
│ ├── about-me.md # About-me page
│ ├── 📁blog
│ │ ├── all-posts.astro # All posts page
│ │ ├── index.astro # Blog home page
│ │ ├── 📁posts # Blog posts
│ │ ├── 📁tags # Blog tags
│ │ └── 📁techs # Blog technologies
│ ├── index.astro # Home page
│ ├── 📁portfolio
│ │ └── 📁projects # Portfolio projects
│ ├── robots.txt.ts # robots.txt configuration
│ └── rss.xml.js # RSS configuration
├── 📁scripts
│ └── menu.js # Menu script
├── 📁styles
│ └── global.css # Global styles
└── 📁utils
└── languages.ts # Technology tools configuration
├── .gitignore
├── astro.config.mjs
├── package-lock.json
├── package.json
├── README.md
└── tsconfig.json
```
## 🛠️ Technology Stack
- **Framework**: Astro v5.4.2
- **UI Library**: Preact v10.26.2
- **Styling**: TailwindCSS v4.0.8
- **Icons**: astro-icon v1.1.5
- **Syntax Highlighting**: PrismJS v1.30.0
- **Animations**: tailwindcss-animated v2.0.0
- **Analytics**: @vercel/speed-insights v1.2.0
## ✨ Key Features
1. **🚀 Performance Optimized**
- Static site generation
- Partial hydration with Preact
- Optimized images and assets
2. **💻 Modern Development Experience**
- TypeScript support
- Hot module replacement
- ESLint integration
3. **🔍 SEO & Analytics**
- Built-in sitemap generation
- RSS feed support
- Vercel Speed Insights
4. **🎨 Styling & UI**
- TailwindCSS for utility-first styling
- Animated components
- Responsive design
- Dark mode support
## 🚀 Getting Started
1. **📦 Installation**
```bash
npm install
```
2. **⚡ Development**
```bash
npm run dev
```
3. **🏗️ Build**
```bash
npm run build
```
4. **👀 Preview**
```bash
npm run preview
```
## ⚙️ Configuration
The project is configured through several key files:
- `astro.config.mjs`: Main Astro configuration
- `tailwind.config.js`: TailwindCSS configuration
- `tsconfig.json`: TypeScript configuration
## 🎨 Customization
### 📄 Adding New Pages
Create new `.astro` files in the `src/pages` directory. The file name will determine the route.
### 🔧 Adding New Languages or Technologies
To incorporate a new programming language or technological tool into the site's capsules, follow these steps:
1. **🖼️ Add the SVG icon**: Place the SVG file of the language or tool in the `src/icons` folder.
> **💡 Recommendation**: For SVG icons, I recommend using [SVGL](https://svgl.app/), an excellent library of high-quality vectors that offers optimized icons for most popular languages and technologies.
2. **📝 Register the language**: Open the `utils/languages.ts` file and add a new entry to the languages object following this format:
```typescript
html: {
name: "HTML 5",
iconName: "html",
},
```
Where:
- `html`: Is the unique identifier for the language
- `name`: Is the name that will be displayed visibly in the interface
- `iconName`: Is the name of the SVG file without the extension (must match exactly with the file name in `src/icons`)
Once these steps are completed, the new language or technology will be available for use in the site's capsules. You can select it when creating or editing projects or posts, and the corresponding icon will be displayed correctly in the interface.
If you encounter any issues during this process, try restarting the development server. In some cases, changes to configuration files or static resources require a restart to be detected correctly.
To verify that the new language has been added correctly, check the list of available technologies in the user interface after restarting the server.
### 🎨 Styling
- Use TailwindCSS classes for styling
- Add custom styles in `src/styles/global.css`
### 🧩 Components
- Create reusable components in `src/components`
- Import icons using `astro-icon`
## 🚀 Deployment
The site is configured for deployment on Vercel, but can be deployed to any static hosting service.
## 🤝 Contributing
1. Fork the repository
2. Create a feature branch
3. Commit your changes
4. Push to the branch
5. Create a Pull Request
## 📄 License
This project is licensed under the MIT License - see the LICENSE file for details.

View File

@@ -0,0 +1,41 @@
---
import Layout from '../../../layouts/Layout.astro';
import BlogPost from '../../../components/blog/BlogPost.astro';
import Heading from '../../../components/ui/Heading.astro';
export async function getStaticPaths() {
const allPosts: any[] = await Astro.glob("../posts/*.md");
const uniqueTags: string[] = [
...new Set(allPosts.map((post: any) => post.frontmatter.tags).flat()),
];
return uniqueTags.map((tag) => {
const filteredPosts = allPosts.filter((post) =>
post.frontmatter.tags.includes(tag),
);
return {
params: { tag },
props: { posts: filteredPosts },
};
});
}
const { tag } = Astro.params;
const { posts } = Astro.props;
---
<Layout pageTitle={tag} >
<section class="py-8">
<div class="flex flex-col gap-8 max-w-4xl mx-auto">
<Heading text="Posts about" textGradient={tag}/>
{
posts.map((post) => (
<BlogPost url={post.url} title={post.frontmatter.title} date={post.frontmatter.pubDate } tags={post.frontmatter.tags } languages={post.frontmatter.languages } image={post.frontmatter.image } />
))
}
</div>
</section>
</Layout>

View File

@@ -0,0 +1,19 @@
---
import Layout from "../../../layouts/Layout.astro";
import Tags from "../../../components/blog/Tags.astro";
import Heading from "../../../components/ui/Heading.astro";
const pageTitle = "Tags";
---
<Layout pageTitle={pageTitle} >
<section class="py-8">
<div class="flex flex-col gap-8 max-w-3xl mx-auto">
<Heading text="Tags" />
<Tags variant="vertical" />
</div>
</section>
</Layout>

View File

@@ -0,0 +1,55 @@
---
import Layout from "../../../layouts/Layout.astro";
import BlogPost from "../../../components/blog/BlogPost.astro";
import Heading from "../../../components/ui/Heading.astro";
import type { MarkdownInstance } from 'astro';
interface Frontmatter {
languages: string[];
title: string;
pubDate: string;
tags: string[];
image: string;
}
export async function getStaticPaths(): Promise<Array<{params: {category: string}, props: {posts: MarkdownInstance<Frontmatter>[]}}>>{
const allPosts: MarkdownInstance<Frontmatter>[] = await Astro.glob<Frontmatter>("../posts/*.md");
const uniqueTags: string[] = [
...new Set(allPosts.map((post: MarkdownInstance<Frontmatter>) => post.frontmatter.languages).flat()),
];
return uniqueTags.map((category) => {
const filteredPosts = allPosts.filter((post) =>
post.frontmatter.languages.includes(category)
);
return {
params: { category },
props: { posts: filteredPosts },
};
});
}
const { category } = Astro.params;
const { posts } = Astro.props;
---
<Layout pageTitle={category} >
<section class="py-8">
<div class="flex flex-col gap-8 max-w-4xl mx-auto">
<Heading text="Posts about" textGradient={category} />
{
posts.map((post) => (
<BlogPost
url={post.url}
title={post.frontmatter.title}
date={post.frontmatter.pubDate}
tags={post.frontmatter.tags}
languages={post.frontmatter.languages}
image={post.frontmatter.image}
/>
))
}
</div>
</section>
</Layout>

View File

@@ -0,0 +1,20 @@
---
import Layout from "../../../layouts/Layout.astro";
import Languages from "../../../components/blog/Languages.astro";
import Heading from "../../../components/ui/Heading.astro";
const pageTitle = "Languages";
const allPosts = await Astro.glob("../posts/*.md");
const languages = [
...new Set(allPosts.map((post) => post.frontmatter.languages).flat()),
];
---
<Layout pageTitle={pageTitle} >
<section class="py-8">
<div class="flex flex-col gap-8 max-w-3xl mx-auto">
<Heading text="Technologies" />
<Languages variant="vertical" />
</div>
</section>
</Layout>