sexyjekyll-theme 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +82 -0
- data/LICENSE +21 -0
- data/README.de.md +276 -0
- data/README.es.md +276 -0
- data/README.fr.md +276 -0
- data/README.it.md +219 -0
- data/README.md +276 -0
- data/_includes/critical-css.html +4 -0
- data/_includes/footer.html +81 -0
- data/_includes/head.html +88 -0
- data/_includes/nav.html +21 -0
- data/_includes/related-posts.html +75 -0
- data/_includes/social-icon.html +98 -0
- data/_includes/structured-data-article.html +55 -0
- data/_includes/structured-data-breadcrumb.html +28 -0
- data/_includes/structured-data-person.html +82 -0
- data/_includes/structured-data-website.html +23 -0
- data/_layouts/blog.html +101 -0
- data/_layouts/category.html +66 -0
- data/_layouts/contact.html +26 -0
- data/_layouts/default.html +13 -0
- data/_layouts/home.html +30 -0
- data/_layouts/llms.txt +34 -0
- data/_layouts/post.html +99 -0
- data/_plugins/auto_related_posts.rb +153 -0
- data/_plugins/category_generator.rb +27 -0
- data/_plugins/llms_txt_generator.rb +45 -0
- data/_plugins/localized_date.rb +52 -0
- data/assets/bg.jpeg +0 -0
- data/assets/bg.webp +0 -0
- data/assets/debug/blocco.png +0 -0
- data/assets/debug/categorie.jpeg +0 -0
- data/assets/debug/categorie.png +0 -0
- data/assets/debug/codice.png +0 -0
- data/assets/debug/contrasto.jpeg +0 -0
- data/assets/debug/dipendenze.png +0 -0
- data/assets/debug/h1.png +0 -0
- data/assets/debug/pagespeed.png +0 -0
- data/assets/debug/ricerca.png +0 -0
- data/assets/debug/richieste.png +0 -0
- data/assets/favicon/android-icon-144x144.png +0 -0
- data/assets/favicon/android-icon-192x192.png +0 -0
- data/assets/favicon/android-icon-36x36.png +0 -0
- data/assets/favicon/android-icon-48x48.png +0 -0
- data/assets/favicon/android-icon-72x72.png +0 -0
- data/assets/favicon/android-icon-96x96.png +0 -0
- data/assets/favicon/apple-icon-114x114.png +0 -0
- data/assets/favicon/apple-icon-120x120.png +0 -0
- data/assets/favicon/apple-icon-144x144.png +0 -0
- data/assets/favicon/apple-icon-152x152.png +0 -0
- data/assets/favicon/apple-icon-180x180.png +0 -0
- data/assets/favicon/apple-icon-57x57.png +0 -0
- data/assets/favicon/apple-icon-60x60.png +0 -0
- data/assets/favicon/apple-icon-72x72.png +0 -0
- data/assets/favicon/apple-icon-76x76.png +0 -0
- data/assets/favicon/apple-icon-precomposed.png +0 -0
- data/assets/favicon/apple-icon.png +0 -0
- data/assets/favicon/favicon-16x16.png +0 -0
- data/assets/favicon/favicon-32x32.png +0 -0
- data/assets/favicon/favicon-96x96.png +0 -0
- data/assets/favicon/favicon.ico +0 -0
- data/assets/favicon/ms-icon-144x144.png +0 -0
- data/assets/favicon/ms-icon-150x150.png +0 -0
- data/assets/favicon/ms-icon-310x310.png +0 -0
- data/assets/favicon/ms-icon-70x70.png +0 -0
- data/assets/images/aiact.jpeg +0 -0
- data/assets/images/aiethics.jpeg +0 -0
- data/assets/images/green.jpeg +0 -0
- data/assets/images/jekyll.webp +0 -0
- data/assets/images/parenting.jpeg +0 -0
- data/assets/images/seo-generativo.jpeg +0 -0
- data/assets/images/upskilling-ai.jpeg +0 -0
- data/assets/pic.jpeg +0 -0
- data/assets/screens/screen.jpeg +0 -0
- data/assets/screens/screen2.jpeg +0 -0
- data/css/animations.css +404 -0
- data/css/style.css +2250 -0
- data/css/syntax-dark.css +157 -0
- data/css/syntax-light.css +157 -0
- data/js/main.js +706 -0
- data/js/simple-jekyll-search.min.js +6 -0
- metadata +254 -0
data/README.md
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# SexyJekyll Theme
|
|
2
|
+
|
|
3
|
+
A modern, feature-rich Jekyll theme designed for professional blogs and personal websites. Built with accessibility, performance, and user experience in mind.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
### Design & User Experience
|
|
10
|
+
- **Modern Design**: Clean, minimalist aesthetic
|
|
11
|
+
- **Fully Responsive**: Mobile-first design that works on all devices
|
|
12
|
+
- **Reading Progress**: Visual indicator showing article reading progress
|
|
13
|
+
- **Print Styles**: Optimized layouts for printing
|
|
14
|
+
|
|
15
|
+
### Content & Navigation
|
|
16
|
+
- **Advanced Search**: Instant client-side search with keyword highlighting
|
|
17
|
+
- **Related Posts**: Smart post recommendations based on categories and tags
|
|
18
|
+
- **Categories**: Category-based filtering and organization
|
|
19
|
+
- **Pagination**: Customizable post pagination
|
|
20
|
+
|
|
21
|
+
### SEO & Social
|
|
22
|
+
- **SEO Optimized**: Meta tags, Open Graph, Twitter Cards
|
|
23
|
+
- **Structured Data**: JSON-LD schema for better search engine understanding
|
|
24
|
+
- **RSS Feed**: Automatic feed generation
|
|
25
|
+
- **Sitemap**: Auto-generated sitemap for search engines
|
|
26
|
+
|
|
27
|
+
### Accessibility
|
|
28
|
+
- **WCAG 2.1 Level AA**: Comprehensive accessibility support
|
|
29
|
+
- **Skip to Content**: Keyboard navigation helpers
|
|
30
|
+
- **Semantic HTML**: Proper HTML5 landmarks and structure
|
|
31
|
+
- **ARIA Labels**: Screen reader friendly
|
|
32
|
+
- **Reduced Motion**: Respects user motion preferences
|
|
33
|
+
- **High Contrast**: Excellent color contrast ratios
|
|
34
|
+
|
|
35
|
+
### Performance
|
|
36
|
+
- **Responsive Images**: WebP format with multiple sizes
|
|
37
|
+
- **Lazy Loading**: Images load as needed
|
|
38
|
+
- **Optimized CSS/JS**: Minified and efficient code
|
|
39
|
+
- **Fast Load Times**: Optimized for performance
|
|
40
|
+
|
|
41
|
+
### Developer Features
|
|
42
|
+
- **Syntax Highlighting**: Code blocks with line numbers (Rouge)
|
|
43
|
+
- **Reading Time**: Automatic reading time estimation
|
|
44
|
+
- **Multi-language**: Full i18n system supporting English, Italian, German, French, and Spanish
|
|
45
|
+
- **Customizable**: Easy configuration via `_config.yml`
|
|
46
|
+
- **Well Documented**: Comprehensive documentation included
|
|
47
|
+
|
|
48
|
+
### AI & LLM Features
|
|
49
|
+
- **llms.txt Support**: Automatic generation of AI-friendly content summaries
|
|
50
|
+
- **Per-Post llms.txt**: Each blog post generates its own dedicated llms.txt file at `/blog/YYYY/MM/DD/post-slug/llms.txt`
|
|
51
|
+
- **Site-level llms.txt**: Main llms.txt file at root with site overview and content structure
|
|
52
|
+
- **Structured Content**: Clean, semantic HTML5 markup optimized for AI crawlers
|
|
53
|
+
- **JSON-LD Schema**: Rich structured data for better content understanding
|
|
54
|
+
- **AI Crawler Friendly**: Welcoming approach to AI indexing with clear instructions
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
### As a Ruby Gem (Recommended)
|
|
59
|
+
|
|
60
|
+
Add this line to your Jekyll site's `Gemfile`:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
gem "sexyjekyll-theme"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
And add this line to your Jekyll site's `_config.yml`:
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
theme: sexyjekyll-theme
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Then execute:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
bundle install
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Remote Theme (GitHub Pages)
|
|
79
|
+
|
|
80
|
+
If you're using GitHub Pages, add this to your `_config.yml`:
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
remote_theme: amargiovanni/sexyjekyll-theme
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Manual Installation
|
|
87
|
+
|
|
88
|
+
1. Download or clone this repository
|
|
89
|
+
2. Copy the files to your Jekyll site
|
|
90
|
+
3. Update your `_config.yml` with the theme settings
|
|
91
|
+
|
|
92
|
+
## Quick Start
|
|
93
|
+
|
|
94
|
+
1. **Install the theme** using one of the methods above
|
|
95
|
+
|
|
96
|
+
2. **Configure** your `_config.yml`:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
# Site settings
|
|
100
|
+
title: Your Name
|
|
101
|
+
email: your.email@example.com
|
|
102
|
+
description: Your site description
|
|
103
|
+
baseurl: ""
|
|
104
|
+
url: "https://yoursite.com"
|
|
105
|
+
lang: en # Options: en, it, de, fr, es
|
|
106
|
+
|
|
107
|
+
# Author information
|
|
108
|
+
author:
|
|
109
|
+
name: Your Name
|
|
110
|
+
email: your.email@example.com
|
|
111
|
+
linkedin: https://www.linkedin.com/in/yourprofile/
|
|
112
|
+
bluesky: https://bsky.app/profile/yourhandle
|
|
113
|
+
|
|
114
|
+
# Navigation logo
|
|
115
|
+
nav_logo:
|
|
116
|
+
type: text # 'text' or 'image'
|
|
117
|
+
text: YN # Your initials or text
|
|
118
|
+
# image: /assets/img/logo.png # Or path to logo image
|
|
119
|
+
# alt: Your Logo
|
|
120
|
+
|
|
121
|
+
# Hero section
|
|
122
|
+
hero:
|
|
123
|
+
name: Your Name
|
|
124
|
+
role: Your Role
|
|
125
|
+
subtitle: Your Company or Tagline
|
|
126
|
+
tagline: Your personal tagline
|
|
127
|
+
description: A brief description about you
|
|
128
|
+
|
|
129
|
+
# Blog section
|
|
130
|
+
blog:
|
|
131
|
+
title: Blog
|
|
132
|
+
description: Your blog description
|
|
133
|
+
|
|
134
|
+
# Contact section
|
|
135
|
+
contact:
|
|
136
|
+
title: Get In Touch
|
|
137
|
+
description: Contact page description
|
|
138
|
+
links:
|
|
139
|
+
- name: Email
|
|
140
|
+
url: mailto:your.email@example.com
|
|
141
|
+
type: email
|
|
142
|
+
- name: LinkedIn
|
|
143
|
+
url: https://www.linkedin.com/in/yourprofile/
|
|
144
|
+
type: linkedin
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
3. **Create your first post** in `_posts/`:
|
|
148
|
+
|
|
149
|
+
```markdown
|
|
150
|
+
---
|
|
151
|
+
layout: post
|
|
152
|
+
title: "Your First Post"
|
|
153
|
+
subtitle: "Optional subtitle"
|
|
154
|
+
date: 2025-11-01
|
|
155
|
+
categories: blog tech
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
Your post content here...
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
4. **Run Jekyll**:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
bundle exec jekyll serve
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Visit `http://localhost:4000` to see your site!
|
|
168
|
+
|
|
169
|
+
## Configuration
|
|
170
|
+
|
|
171
|
+
### Available Layouts
|
|
172
|
+
|
|
173
|
+
- `default` - Base layout for all pages
|
|
174
|
+
- `home` - Homepage with hero section
|
|
175
|
+
- `blog` - Blog listing page
|
|
176
|
+
- `post` - Individual blog post
|
|
177
|
+
- `about` - About page
|
|
178
|
+
- `contact` - Contact page with social links
|
|
179
|
+
- `category` - Category-specific post listing
|
|
180
|
+
- `404` - Custom 404 error page
|
|
181
|
+
|
|
182
|
+
### Plugins
|
|
183
|
+
|
|
184
|
+
The theme uses these Jekyll plugins:
|
|
185
|
+
|
|
186
|
+
**Standard Plugins:**
|
|
187
|
+
- `jekyll-feed` - RSS feed generation
|
|
188
|
+
- `jekyll-seo-tag` - SEO meta tags
|
|
189
|
+
- `jekyll-paginate` - Post pagination
|
|
190
|
+
- `jekyll-sitemap` - Sitemap generation
|
|
191
|
+
- `liquid_reading_time` - Reading time estimation
|
|
192
|
+
- `jekyll_picture_tag` - Responsive images
|
|
193
|
+
|
|
194
|
+
**Custom Plugins:**
|
|
195
|
+
- `llms_txt_generator` - Automatically generates llms.txt files for each blog post and creates AI-friendly content summaries
|
|
196
|
+
- `auto_related_posts` - Intelligent post recommendation system based on categories, tags, and content similarity using TF-IDF-like algorithm
|
|
197
|
+
- `category_generator` - Automatically creates dedicated pages for each category with filtered post listings
|
|
198
|
+
- `localized_date` - Liquid filter for formatting dates according to the selected language (e.g., "15 January 2025" in English, "15 gennaio 2025" in Italian)
|
|
199
|
+
|
|
200
|
+
### Customization
|
|
201
|
+
|
|
202
|
+
#### Colors and Styles
|
|
203
|
+
|
|
204
|
+
Edit `css/style.css` to customize colors, fonts, and styles.
|
|
205
|
+
|
|
206
|
+
#### Social Links
|
|
207
|
+
|
|
208
|
+
Configure social links in `_config.yml` under `contact.links`. Supported types:
|
|
209
|
+
- email, linkedin, bluesky, twitter, github, instagram, facebook
|
|
210
|
+
- youtube, mastodon, telegram, whatsapp, medium, reddit
|
|
211
|
+
- discord, tiktok, twitch, slack
|
|
212
|
+
|
|
213
|
+
## Documentation
|
|
214
|
+
|
|
215
|
+
Detailed documentation is available in the following files:
|
|
216
|
+
|
|
217
|
+
- [I18N.md](docs/I18N.md) - Internationalization system and language support
|
|
218
|
+
- [ACCESSIBILITY.md](docs/ACCESSIBILITY.md) - Accessibility features and testing
|
|
219
|
+
- [SEARCH.md](docs/SEARCH.md) - Search functionality
|
|
220
|
+
- [READING_PROGRESS.md](docs/READING_PROGRESS.md) - Reading progress indicator
|
|
221
|
+
- [STRUCTURED_DATA.md](docs/STRUCTURED_DATA.md) - SEO structured data
|
|
222
|
+
- [SOCIAL_SHARE.md](SOCIAL_SHARE.md) - How to add social sharing (optional)
|
|
223
|
+
- [COMMENTS.md](docs/COMMENTS.md) - How to add comments (optional)
|
|
224
|
+
- [CHANGELOG.md](CHANGELOG.md) - Version history
|
|
225
|
+
- [PUBLISHING.md](PUBLISHING.md) - Guide to publish your theme
|
|
226
|
+
|
|
227
|
+
### Available in Multiple Languages
|
|
228
|
+
|
|
229
|
+
- 🇬🇧 [README.md](README.md) - English
|
|
230
|
+
- 🇮🇹 [README.it.md](README.it.md) - Italian
|
|
231
|
+
- 🇩🇪 [README.de.md](README.de.md) - German
|
|
232
|
+
- 🇫🇷 [README.fr.md](README.fr.md) - French
|
|
233
|
+
- 🇪🇸 [README.es.md](README.es.md) - Spanish
|
|
234
|
+
|
|
235
|
+
## Browser Support
|
|
236
|
+
|
|
237
|
+
- Chrome (latest)
|
|
238
|
+
- Firefox (latest)
|
|
239
|
+
- Safari (latest)
|
|
240
|
+
- Edge (latest)
|
|
241
|
+
- Mobile browsers (iOS Safari, Chrome Mobile)
|
|
242
|
+
|
|
243
|
+
## Contributing
|
|
244
|
+
|
|
245
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
246
|
+
|
|
247
|
+
1. Fork the repository
|
|
248
|
+
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
|
249
|
+
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
250
|
+
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
251
|
+
5. Open a Pull Request
|
|
252
|
+
|
|
253
|
+
## Support
|
|
254
|
+
|
|
255
|
+
If you encounter any issues or have questions:
|
|
256
|
+
|
|
257
|
+
- Open an issue on [GitHub](https://github.com/amargiovanni/sexyjekyll-theme/issues)
|
|
258
|
+
- Check the [documentation](https://github.com/amargiovanni/sexyjekyll-theme#readme)
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
263
|
+
|
|
264
|
+
## Credits
|
|
265
|
+
|
|
266
|
+
Created by [Andrea Margiovanni](https://margiovanni.it)
|
|
267
|
+
|
|
268
|
+
## Acknowledgments
|
|
269
|
+
|
|
270
|
+
- Built with [Jekyll](https://jekyllrb.com/)
|
|
271
|
+
- Syntax highlighting by [Rouge](https://github.com/rouge-ruby/rouge)
|
|
272
|
+
- Icons and design inspiration from modern web design trends
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
If you find this theme useful, please consider giving it a star on GitHub!
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
/* Critical CSS - Inline per LCP ottimizzato */
|
|
3
|
+
:root{--bg-primary:#0f0f23;--bg-secondary:rgba(20,20,40,.7);--bg-elevated:rgba(30,30,60,.8);--text-primary:#fff;--text-secondary:#e0e0ff;--text-tertiary:#a0a0d0;--nav-bg:rgba(15,15,35,.6);--color-purple:#a855f7;--color-pink:#ec4899;--color-blue:#3b82f6;--color-cyan:#06b6d4;--accent:#a855f7;--accent-hover:#c084fc;--border:rgba(168,85,247,.2);--font-heading:'Sora',system-ui,sans-serif;--font-body:'Plus Jakarta Sans',system-ui,sans-serif;--spacing-xs:.5rem;--spacing-sm:1rem;--spacing-md:1.5rem;--spacing-lg:2rem;--spacing-xl:3rem;--spacing-2xl:4rem;--spacing-3xl:6rem;--radius-sm:.5rem;--radius-md:1rem;--radius-lg:1.5rem;--radius-full:9999px;--transition-fast:.15s cubic-bezier(.4,0,.2,1);--transition-base:.3s cubic-bezier(.4,0,.2,1)}*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:var(--font-body);background-color:var(--bg-primary);background-image:url('/assets/bg.webp');background-size:cover;background-position:center;background-repeat:no-repeat;background-attachment:fixed;color:var(--text-primary);line-height:1.7;font-size:18px;overflow-x:hidden;position:relative}h1{font-size:inherit}section h1{font-size:clamp(3rem,8vw,6rem)}.nav{position:sticky;top:0;left:0;right:0;z-index:1000;background:var(--nav-bg);backdrop-filter:blur(20px) saturate(180%);border-bottom:1px solid var(--border);transition:all var(--transition-base);box-shadow:0 4px 30px rgba(0,0,0,.15)}.nav-container{max-width:1400px;margin:0 auto;padding:1.5rem var(--spacing-lg);display:flex;justify-content:space-between;align-items:center}.nav-logo{font-family:var(--font-heading);font-size:2rem;font-weight:800;background:linear-gradient(135deg,var(--color-purple) 0%,var(--color-pink) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;text-decoration:none;transition:transform var(--transition-base);display:inline-flex;align-items:center}.nav-logo-image{height:2.5rem;width:auto;max-width:12rem;object-fit:contain;display:block;border-radius:50%}.nav-links{display:flex;gap:var(--spacing-xl)}.nav-link{color:var(--text-secondary);text-decoration:none;font-weight:600;font-size:1.1rem;transition:all var(--transition-base);position:relative;padding:.5rem 0}.hero{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:var(--spacing-3xl) var(--spacing-lg);position:relative}.hero-container{max-width:1100px;margin:0 auto;width:100%}.hero-content{text-align:center}.hero-name{display:block;font-family:var(--font-heading);font-size:clamp(3rem,8vw,6rem);font-weight:800;line-height:1.1;margin-bottom:var(--spacing-md);background:linear-gradient(135deg,var(--color-purple) 0%,var(--color-pink) 50%,var(--color-cyan) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:-.02em}@media (max-width:768px){body{font-size:16px}.nav-container{padding:1.25rem var(--spacing-md)}.nav-logo{font-size:1.6rem}.nav-links{gap:var(--spacing-lg)}.hero{padding:var(--spacing-2xl) var(--spacing-md);min-height:calc(100vh - 70px)}}
|
|
4
|
+
</style>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{% assign t = site.data.i18n[site.lang] %}
|
|
2
|
+
<footer class="footer">
|
|
3
|
+
<div class="footer-container">
|
|
4
|
+
<div class="footer-grid">
|
|
5
|
+
<!-- Column 1: About Section -->
|
|
6
|
+
<div class="footer-section">
|
|
7
|
+
<p class="footer-title">{{ site.author.name }}</p>
|
|
8
|
+
<p class="footer-description">{{ site.description }}</p>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<!-- Column 2: Navigation -->
|
|
12
|
+
<div class="footer-section">
|
|
13
|
+
<p class="footer-title">{{ t.footer.navigation }}</p>
|
|
14
|
+
<ul class="footer-links">
|
|
15
|
+
<li><a href="{{ '/' | relative_url }}">{{ t.nav.home }}</a></li>
|
|
16
|
+
<li><a href="{{ '/blog' | relative_url }}">{{ t.nav.blog }}</a></li>
|
|
17
|
+
<li><a href="{{ '/categories' | relative_url }}">{{ t.nav.categories }}</a></li>
|
|
18
|
+
<li><a href="{{ '/contact' | relative_url }}">{{ t.nav.contacts }}</a></li>
|
|
19
|
+
</ul>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<!-- Column 3: Social Links -->
|
|
23
|
+
<div class="footer-section">
|
|
24
|
+
<p class="footer-title">{{ t.footer.follow_me }}</p>
|
|
25
|
+
<ul class="footer-links footer-contact-list">
|
|
26
|
+
{% for link in site.contact.links %}
|
|
27
|
+
<li>
|
|
28
|
+
<a href="{{ link.url }}" class="footer-contact-link" {% if link.type != 'email' %}target="_blank" rel="noopener noreferrer"{% endif %}>
|
|
29
|
+
<span class="contact-icon">
|
|
30
|
+
{% case link.type %}
|
|
31
|
+
{% when 'email' %}
|
|
32
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>
|
|
33
|
+
{% when 'linkedin' %}
|
|
34
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>
|
|
35
|
+
{% when 'github' %}
|
|
36
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
|
|
37
|
+
{% when 'instagram' %}
|
|
38
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line></svg>
|
|
39
|
+
{% when 'bluesky' %}
|
|
40
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z"/></svg>
|
|
41
|
+
{% when 'mastodon' %}
|
|
42
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M21.327 8.566c0-4.339-2.843-5.61-2.843-5.61-1.433-.658-3.894-.935-6.451-.956h-.063c-2.557.021-5.016.298-6.45.956 0 0-2.843 1.272-2.843 5.61 0 .993-.019 2.181.012 3.441.103 4.243.778 8.425 4.701 9.463 1.809.479 3.362.579 4.612.51 2.268-.126 3.541-.809 3.541-.809l-.075-1.646s-1.621.511-3.441.449c-1.804-.062-3.707-.194-3.999-2.409a4.523 4.523 0 0 1-.04-.621s1.77.433 4.014.536c1.372.063 2.658-.08 3.965-.236 2.506-.299 4.688-1.843 4.962-3.254.434-2.223.398-5.424.398-5.424zm-3.353 5.59h-2.081V9.057c0-1.075-.452-1.62-1.357-1.62-1 0-1.501.647-1.501 1.927v2.791h-2.069V9.364c0-1.28-.501-1.927-1.502-1.927-.905 0-1.357.546-1.357 1.62v5.099H6.026V8.903c0-1.074.273-1.927.823-2.558.566-.631 1.307-.955 2.228-.955 1.065 0 1.872.409 2.405 1.228l.518.869.519-.869c.533-.819 1.34-1.228 2.405-1.228.92 0 1.662.324 2.228.955.549.631.822 1.484.822 2.558v5.253z"/></svg>
|
|
43
|
+
{% else %}
|
|
44
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>
|
|
45
|
+
{% endcase %}
|
|
46
|
+
</span>
|
|
47
|
+
<span class="contact-label">{{ link.name }}</span>
|
|
48
|
+
</a>
|
|
49
|
+
</li>
|
|
50
|
+
{% endfor %}
|
|
51
|
+
</ul>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<!-- Column 4: Built With -->
|
|
55
|
+
<div class="footer-section">
|
|
56
|
+
<p class="footer-title">{{ t.footer.built_with }}</p>
|
|
57
|
+
<a href="https://jekyllrb.com" target="_blank" rel="noopener noreferrer" style="display: inline-block; margin-bottom: var(--spacing-xs);">
|
|
58
|
+
<img src="{{ '/assets/images/jekyll.webp' | relative_url }}" alt="Jekyll" style="height: 40px; width: auto; opacity: 0.9; transition: opacity var(--transition-base);" onmouseover="this.style.opacity='1'" onmouseout="this.style.opacity='0.9'">
|
|
59
|
+
</a>
|
|
60
|
+
<p class="footer-description">
|
|
61
|
+
{{ t.footer.jekyll_description }}
|
|
62
|
+
</p>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<!-- Bottom Bar -->
|
|
67
|
+
<div class="footer-bottom">
|
|
68
|
+
<div class="footer-license">
|
|
69
|
+
<a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="noopener noreferrer" class="cc-license">
|
|
70
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
71
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-5.5-2.5l7.51-3.49L17.5 6.5 9.99 9.99 6.5 17.5zm5.5-6.6c.61 0 1.1.49 1.1 1.1s-.49 1.1-1.1 1.1-1.1-.49-1.1-1.1.49-1.1 1.1-1.1z"/>
|
|
72
|
+
</svg>
|
|
73
|
+
<span>{{ t.footer.license }}</span>
|
|
74
|
+
</a>
|
|
75
|
+
<span class="separator">·</span>
|
|
76
|
+
<span>© {{ 'now' | date: "%Y" }} {{ site.author.name }}</span>
|
|
77
|
+
</div>
|
|
78
|
+
<p class="footer-tagline">{{ t.footer.made_with_love }} <a href="https://margiovanni.it" title="Andrea">Andrea</a></p>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</footer>
|
data/_includes/head.html
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{% assign t = site.data.i18n[site.lang] %}
|
|
2
|
+
<head>
|
|
3
|
+
<meta charset="UTF-8">
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5
|
+
<meta name="description" content="{% if page.description %}{{ page.description }}{% else %}{{ site.description }}{% endif %}">
|
|
6
|
+
<meta name="author" content="{{ site.author.name }}">
|
|
7
|
+
<meta name="keywords" content="{% if page.keywords %}{{ page.keywords }}{% else %}{{ t.seo.default_keywords }}{% endif %}">
|
|
8
|
+
|
|
9
|
+
<!-- AI Crawlers Meta Tags -->
|
|
10
|
+
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1">
|
|
11
|
+
<meta property="article:author" content="{{ site.author.name }}">
|
|
12
|
+
{% if page.date %}
|
|
13
|
+
<meta property="article:published_time" content="{{ page.date | date_to_xmlschema }}">
|
|
14
|
+
<meta property="article:modified_time" content="{{ page.date | date_to_xmlschema }}">
|
|
15
|
+
{% endif %}
|
|
16
|
+
{% if page.categories %}
|
|
17
|
+
{% for category in page.categories %}
|
|
18
|
+
<meta property="article:tag" content="{{ category }}">
|
|
19
|
+
{% endfor %}
|
|
20
|
+
{% endif %}
|
|
21
|
+
<link rel="canonical" href="{{ page.url | absolute_url }}">
|
|
22
|
+
|
|
23
|
+
<!-- Open Graph -->
|
|
24
|
+
<meta property="og:title" content="{% if page.title %}{{ page.title }} - {{ site.title }}{% else %}{{ site.title }}{% endif %}">
|
|
25
|
+
<meta property="og:description" content="{% if page.description %}{{ page.description }}{% else %}{{ site.description }}{% endif %}">
|
|
26
|
+
<meta property="og:type" content="{% if page.layout == 'post' %}article{% else %}website{% endif %}">
|
|
27
|
+
{% if page.image %}
|
|
28
|
+
<meta property="og:image" content="{{ page.image | absolute_url }}">
|
|
29
|
+
{% endif %}
|
|
30
|
+
|
|
31
|
+
<title>{% if page.title %}{{ page.title }} - {{ site.title }}{% else %}{{ site.title }}{% endif %}</title>
|
|
32
|
+
|
|
33
|
+
<!-- Favicon -->
|
|
34
|
+
<link rel="apple-touch-icon" sizes="57x57" href="{{ '/assets/favicon/apple-icon-57x57.png' | relative_url }}">
|
|
35
|
+
<link rel="apple-touch-icon" sizes="60x60" href="{{ '/assets/favicon/apple-icon-60x60.png' | relative_url }}">
|
|
36
|
+
<link rel="apple-touch-icon" sizes="72x72" href="{{ '/assets/favicon/apple-icon-72x72.png' | relative_url }}">
|
|
37
|
+
<link rel="apple-touch-icon" sizes="76x76" href="{{ '/assets/favicon/apple-icon-76x76.png' | relative_url }}">
|
|
38
|
+
<link rel="apple-touch-icon" sizes="114x114" href="{{ '/assets/favicon/apple-icon-114x114.png' | relative_url }}">
|
|
39
|
+
<link rel="apple-touch-icon" sizes="120x120" href="{{ '/assets/favicon/apple-icon-120x120.png' | relative_url }}">
|
|
40
|
+
<link rel="apple-touch-icon" sizes="144x144" href="{{ '/assets/favicon/apple-icon-144x144.png' | relative_url }}">
|
|
41
|
+
<link rel="apple-touch-icon" sizes="152x152" href="{{ '/assets/favicon/apple-icon-152x152.png' | relative_url }}">
|
|
42
|
+
<link rel="apple-touch-icon" sizes="180x180" href="{{ '/assets/favicon/apple-icon-180x180.png' | relative_url }}">
|
|
43
|
+
<link rel="icon" type="image/png" sizes="192x192" href="{{ '/assets/favicon/android-icon-192x192.png' | relative_url }}">
|
|
44
|
+
<link rel="icon" type="image/png" sizes="32x32" href="{{ '/assets/favicon/favicon-32x32.png' | relative_url }}">
|
|
45
|
+
<link rel="icon" type="image/png" sizes="96x96" href="{{ '/assets/favicon/favicon-96x96.png' | relative_url }}">
|
|
46
|
+
<link rel="icon" type="image/png" sizes="16x16" href="{{ '/assets/favicon/favicon-16x16.png' | relative_url }}">
|
|
47
|
+
<link rel="shortcut icon" href="{{ '/assets/favicon/favicon.ico' | relative_url }}">
|
|
48
|
+
<meta name="msapplication-TileColor" content="#ffffff">
|
|
49
|
+
<meta name="msapplication-TileImage" content="{{ '/assets/favicon/ms-icon-144x144.png' | relative_url }}">
|
|
50
|
+
<meta name="theme-color" content="#ffffff">
|
|
51
|
+
|
|
52
|
+
<!-- Preconnect to external domains for faster resource loading -->
|
|
53
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
54
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
55
|
+
|
|
56
|
+
<!-- Preload risorse critiche -->
|
|
57
|
+
<link rel="preload" href="{{ '/assets/bg.webp' | relative_url }}" as="image" type="image/webp">
|
|
58
|
+
|
|
59
|
+
<!-- Critical CSS inline per LCP ottimizzato -->
|
|
60
|
+
{% include critical-css.html %}
|
|
61
|
+
|
|
62
|
+
<!-- Preload del CSS completo -->
|
|
63
|
+
<link rel="preload" href="{{ '/css/style.css' | relative_url }}?v={{ site.time | date: '%s' }}" as="style">
|
|
64
|
+
|
|
65
|
+
<!-- CSS completo caricato in modo asincrono -->
|
|
66
|
+
<link rel="stylesheet" href="{{ '/css/style.css' | relative_url }}?v={{ site.time | date: '%s' }}" media="print" onload="this.media='all';this.onload=null">
|
|
67
|
+
<noscript><link rel="stylesheet" href="{{ '/css/style.css' | relative_url }}?v={{ site.time | date: '%s' }}"></noscript>
|
|
68
|
+
|
|
69
|
+
<!-- Non-critical CSS preloaded and loaded asynchronously -->
|
|
70
|
+
<link rel="preload" href="{{ '/css/animations.css' | relative_url }}?v={{ site.time | date: '%s' }}" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
|
71
|
+
<noscript><link rel="stylesheet" href="{{ '/css/animations.css' | relative_url }}?v={{ site.time | date: '%s' }}"></noscript>
|
|
72
|
+
|
|
73
|
+
<link rel="preload" href="{{ '/css/syntax-dark.css' | relative_url }}?v={{ site.time | date: '%s' }}" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
|
74
|
+
<noscript><link rel="stylesheet" href="{{ '/css/syntax-dark.css' | relative_url }}?v={{ site.time | date: '%s' }}"></noscript>
|
|
75
|
+
|
|
76
|
+
<!-- Google Fonts loaded asynchronously -->
|
|
77
|
+
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700;800&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'">
|
|
78
|
+
<noscript><link href="https://fonts.googleapis.com/css2?family=Sora:wght@400;500;600;700;800&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet"></noscript>
|
|
79
|
+
|
|
80
|
+
{% seo %}
|
|
81
|
+
{% feed_meta %}
|
|
82
|
+
|
|
83
|
+
<!-- Structured Data (JSON-LD) -->
|
|
84
|
+
{% include structured-data-website.html %}
|
|
85
|
+
{% include structured-data-person.html %}
|
|
86
|
+
{% include structured-data-article.html %}
|
|
87
|
+
{% include structured-data-breadcrumb.html %}
|
|
88
|
+
</head>
|
data/_includes/nav.html
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{% assign t = site.data.i18n[site.lang] %}
|
|
2
|
+
<a href="#main-content" class="skip-to-content">{{ t.nav.skip_to_content }}</a>
|
|
3
|
+
|
|
4
|
+
<nav class="nav" role="navigation" aria-label="{{ t.nav.main_navigation }}">
|
|
5
|
+
<div class="nav-container">
|
|
6
|
+
<a href="{{ '/' | relative_url }}" class="nav-logo" aria-label="{{ site.author.name }} - {{ t.nav.home }}">
|
|
7
|
+
{% if site.nav_logo.type == 'image' %}
|
|
8
|
+
<img src="{{ site.nav_logo.image | relative_url }}" alt="{{ site.nav_logo.alt | default: site.title }}" class="nav-logo-image">
|
|
9
|
+
{% elsif site.nav_logo.text %}
|
|
10
|
+
{{ site.nav_logo.text }}
|
|
11
|
+
{% else %}
|
|
12
|
+
{{ site.author.name | slice: 0, 2 | upcase }}
|
|
13
|
+
{% endif %}
|
|
14
|
+
</a>
|
|
15
|
+
<div class="nav-links">
|
|
16
|
+
<a href="{{ '/' | relative_url }}" class="nav-link {% if page.url == '/' or page.url == '/index.html' %}active{% endif %}" {% if page.url == '/' or page.url == '/index.html' %}aria-current="page"{% endif %}>{{ t.nav.home }}</a>
|
|
17
|
+
<a href="{{ '/blog' | relative_url }}" class="nav-link {% if page.url contains '/blog' %}active{% endif %}" {% if page.url contains '/blog' %}aria-current="page"{% endif %}>{{ t.nav.blog }}</a>
|
|
18
|
+
<a href="{{ '/contact' | relative_url }}" class="nav-link {% if page.url contains '/contact' %}active{% endif %}" {% if page.url contains '/contact' %}aria-current="page"{% endif %}>{{ t.nav.contacts }}</a>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</nav>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{% assign maxRelated = 4 %}
|
|
2
|
+
|
|
3
|
+
{% comment %}
|
|
4
|
+
This include finds related posts using:
|
|
5
|
+
1. Auto-generated related posts (from auto_related_posts.rb plugin) - if available
|
|
6
|
+
2. Fallback to manual category-based matching
|
|
7
|
+
{% endcomment %}
|
|
8
|
+
|
|
9
|
+
{% assign related_posts = "" | split: "" %}
|
|
10
|
+
|
|
11
|
+
{% comment %} Use auto-generated related posts if available {% endcomment %}
|
|
12
|
+
{% if page.auto_related_posts and page.auto_related_posts.size > 0 %}
|
|
13
|
+
{% assign related_posts = page.auto_related_posts %}
|
|
14
|
+
{% else %}
|
|
15
|
+
{% comment %} Fallback: Find posts with common categories {% endcomment %}
|
|
16
|
+
{% assign minCommonCategories = 1 %}
|
|
17
|
+
|
|
18
|
+
{% for post in site.posts %}
|
|
19
|
+
{% if post.url != page.url %}
|
|
20
|
+
{% assign commonCategories = 0 %}
|
|
21
|
+
{% for category in post.categories %}
|
|
22
|
+
{% if page.categories contains category %}
|
|
23
|
+
{% assign commonCategories = commonCategories | plus: 1 %}
|
|
24
|
+
{% endif %}
|
|
25
|
+
{% endfor %}
|
|
26
|
+
|
|
27
|
+
{% if commonCategories >= minCommonCategories %}
|
|
28
|
+
{% assign related_posts = related_posts | push: post %}
|
|
29
|
+
{% endif %}
|
|
30
|
+
{% endif %}
|
|
31
|
+
{% endfor %}
|
|
32
|
+
|
|
33
|
+
{% comment %} If we don't have enough related posts, add recent ones {% endcomment %}
|
|
34
|
+
{% if related_posts.size < maxRelated %}
|
|
35
|
+
{% for post in site.posts %}
|
|
36
|
+
{% if post.url != page.url %}
|
|
37
|
+
{% unless related_posts contains post %}
|
|
38
|
+
{% assign related_posts = related_posts | push: post %}
|
|
39
|
+
{% endunless %}
|
|
40
|
+
{% endif %}
|
|
41
|
+
{% if related_posts.size >= maxRelated %}
|
|
42
|
+
{% break %}
|
|
43
|
+
{% endif %}
|
|
44
|
+
{% endfor %}
|
|
45
|
+
{% endif %}
|
|
46
|
+
{% endif %}
|
|
47
|
+
|
|
48
|
+
{% if related_posts.size > 0 %}
|
|
49
|
+
{% assign t = site.data.i18n[site.lang] %}
|
|
50
|
+
<aside class="related-posts">
|
|
51
|
+
<h2 class="related-posts-title">{{ t.related.you_may_like }}</h2>
|
|
52
|
+
<div class="related-posts-grid">
|
|
53
|
+
{% for post in related_posts limit:maxRelated %}
|
|
54
|
+
<article class="related-post-card">
|
|
55
|
+
<time class="related-post-date" datetime="{{ post.date | date_to_xmlschema }}">
|
|
56
|
+
{{ post.date | localized_date }}
|
|
57
|
+
</time>
|
|
58
|
+
{% if post.categories %}
|
|
59
|
+
<div class="related-post-categories">
|
|
60
|
+
{% for category in post.categories %}
|
|
61
|
+
<span class="related-post-category">{{ category }}</span>
|
|
62
|
+
{% endfor %}
|
|
63
|
+
</div>
|
|
64
|
+
{% endif %}
|
|
65
|
+
<h3 class="related-post-title">
|
|
66
|
+
<a href="{{ post.url | relative_url }}">{{ post.title }}</a>
|
|
67
|
+
</h3>
|
|
68
|
+
{% if post.subtitle %}
|
|
69
|
+
<p class="related-post-subtitle">{{ post.subtitle }}</p>
|
|
70
|
+
{% endif %}
|
|
71
|
+
</article>
|
|
72
|
+
{% endfor %}
|
|
73
|
+
</div>
|
|
74
|
+
</aside>
|
|
75
|
+
{% endif %}
|