blog github
Saya akan buatkan script lengkap untuk blog Jekyll dengan Material Design 3, tema alam (green/teal), dan fitur yang Anda minta.
Struktur Folder & File
#!/bin/bash
# setup_blog.sh - Script untuk membuat blog Jekyll
# Buat struktur folder
mkdir -p my-nature-blog/{_posts,_layouts,_includes,_sass,_site,assets/{js,css,images},pages,posts}
# Masuk ke folder
cd my-nature-blog
# 1. _config.yml
cat > _config.yml << 'EOF'
title: "Nature Blog"
description: "Blog bertema alam dengan konten berkualitas"
baseurl: ""
url: "https://yourusername.github.io"
# Build settings
markdown: kramdown
highlighter: rouge
permalink: /:year/:month/:day/:title/
paginate: 6
paginate_path: "/page:num/"
plugins:
- jekyll-paginate
- jekyll-seo-tag
- jekyll-sitemap
- jekyll-feed
# Collections
collections:
pages:
output: true
permalink: /:name/
# Defaults
defaults:
- scope:
path: ""
type: "posts"
values:
layout: "post"
author: "Admin"
- scope:
path: ""
values:
layout: "default"
# SEO
twitter:
username: yourtwitter
social:
name: "Nature Blog"
links:
- https://twitter.com/yourtwitter
# Exclude
exclude:
- Gemfile
- Gemfile.lock
- node_modules
- vendor
- setup_blog.sh
EOF
# 2. Gemfile
cat > Gemfile << 'EOF'
source "https://rubygems.org"
gem "jekyll", "~> 4.3"
gem "jekyll-paginate"
gem "jekyll-seo-tag"
gem "jekyll-sitemap"
gem "jekyll-feed"
gem "webrick", "~> 1.7"
EOF
# 3. _layouts/default.html
cat > _layouts/default.html << 'EOF'
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
{% seo %}
<link rel="stylesheet" href="{{ '/assets/css/main.css' | relative_url }}">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ '/feed.xml' | relative_url }}">
</head>
<body>
{% include header.html %}
<main class="main-content">
{{ content }}
</main>
{% include footer.html %}
<script src="{{ '/assets/js/main.js' | relative_url }}"></script>
</body>
</html>
EOF
# 4. _layouts/home.html
cat > _layouts/home.html << 'EOF'
---
layout: default
---
<div class="container">
<section class="hero-section">
<div class="hero-content">
<h1 class="hero-title">{{ page.title | default: site.title }}</h1>
<p class="hero-subtitle">{{ page.description | default: site.description }}</p>
</div>
</section>
<!-- Filter Section -->
<section class="filter-section">
<div class="filter-container">
<div class="filter-group">
<span class="material-icons-round">filter_list</span>
<select id="categoryFilter" class="filter-select">
<option value="">Semua Kategori</option>
{% assign categories = site.categories | sort %}
{% for category in categories %}
<option value="{{ category[0] }}">{{ category[0] }}</option>
{% endfor %}
</select>
</div>
<div class="filter-group">
<span class="material-icons-round">label</span>
<select id="tagFilter" class="filter-select">
<option value="">Semua Tag</option>
{% assign tags = site.tags | sort %}
{% for tag in tags %}
<option value="{{ tag[0] }}">{{ tag[0] }}</option>
{% endfor %}
</select>
</div>
<div class="search-group">
<span class="material-icons-round">search</span>
<input type="text" id="searchInput" placeholder="Cari artikel..." class="search-input">
</div>
</div>
</section>
<!-- Posts Grid -->
<section class="posts-grid" id="postsContainer">
{% for post in paginator.posts %}
{% include post-card.html post=post %}
{% endfor %}
</section>
<!-- Loading Indicator -->
<div id="loadingIndicator" class="loading-indicator" style="display: none;">
<div class="spinner"></div>
</div>
<!-- No Results -->
<div id="noResults" class="no-results" style="display: none;">
<span class="material-icons-round">search_off</span>
<p>Tidak ada artikel yang ditemukan</p>
</div>
</div>
<script>
const allPosts = {{ site.posts | jsonify }};
const currentPage = {{ paginator.page }};
const totalPages = {{ paginator.total_pages }};
</script>
EOF
# 5. _layouts/post.html
cat > _layouts/post.html << 'EOF'
---
layout: default
---
<article class="post-article">
<div class="container">
<div class="post-header">
<div class="post-meta">
{% if page.categories %}
<div class="post-categories">
{% for category in page.categories %}
<span class="category-badge">{{ category }}</span>
{% endfor %}
</div>
{% endif %}
<time datetime="{{ page.date | date_to_xmlschema }}" class="post-date">
<span class="material-icons-round">calendar_today</span>
{{ page.date | date: "%d %B %Y" }}
</time>
<span class="post-reading-time">
<span class="material-icons-round">schedule</span>
{% assign words = content | number_of_words %}
{% if words < 360 %}
1 menit baca
{% else %}
{{ words | divided_by: 180 }} menit baca
{% endif %}
</span>
</div>
<h1 class="post-title">{{ page.title }}</h1>
{% if page.description %}
<p class="post-excerpt">{{ page.description }}</p>
{% endif %}
<div class="post-author">
<div class="author-avatar">
<span class="material-icons-round">person</span>
</div>
<div class="author-info">
<span class="author-name">{{ page.author | default: site.author }}</span>
<span class="author-role">Penulis</span>
</div>
</div>
</div>
{% if page.image %}
<div class="post-featured-image">
<img src="{{ page.image | relative_url }}" alt="{{ page.title }}" loading="lazy">
</div>
{% endif %}
<div class="post-content">
{{ content }}
</div>
{% if page.tags %}
<div class="post-tags">
<span class="material-icons-round">label</span>
{% for tag in page.tags %}
<a href="/tag/{{ tag | slugify }}" class="tag-link">{{ tag }}</a>
{% endfor %}
</div>
{% endif %}
<div class="post-share">
<h3>Bagikan artikel ini</h3>
<div class="share-buttons">
<button class="share-btn" onclick="sharePost('twitter')" title="Share to Twitter">
<span class="material-icons-round">share</span>
</button>
<button class="share-btn" onclick="sharePost('facebook')" title="Share to Facebook">
<span class="material-icons-round">share</span>
</button>
<button class="share-btn" onclick="sharePost('linkedin')" title="Share to LinkedIn">
<span class="material-icons-round">share</span>
</button>
<button class="share-btn" onclick="copyLink()" title="Copy Link">
<span class="material-icons-round">link</span>
</button>
</div>
</div>
</div>
</article>
<!-- Related Posts -->
{% if site.related_posts.size > 0 %}
<section class="related-posts">
<div class="container">
<h2>Artikel Terkait</h2>
<div class="posts-grid">
{% for post in site.related_posts limit: 3 %}
{% include post-card.html post=post %}
{% endfor %}
</div>
</div>
</section>
{% endif %}
EOF
# 6. _includes/header.html
cat > _includes/header.html << 'EOF'
<header class="site-header">
<div class="header-container">
<div class="header-brand">
<a href="{{ '/' | relative_url }}" class="brand-logo">
<span class="material-icons-round">eco</span>
<span class="brand-text">{{ site.title }}</span>
</a>
</div>
<nav class="header-nav" id="headerNav">
<ul class="nav-list">
<li><a href="{{ '/' | relative_url }}" class="nav-link {% if page.url == '/' %}active{% endif %}">Beranda</a></li>
{% for page in site.pages %}
{% if page.title and page.nav != false %}
<li><a href="{{ page.url | relative_url }}" class="nav-link {% if page.url == current_url %}active{% endif %}">{{ page.title }}</a></li>
{% endif %}
{% endfor %}
<li><a href="/categories" class="nav-link">Kategori</a></li>
<li><a href="/tags" class="nav-link">Tags</a></li>
</ul>
</nav>
<div class="header-actions">
<button class="theme-toggle" id="themeToggle" aria-label="Toggle theme">
<span class="material-icons-round">dark_mode</span>
</button>
<button class="mobile-menu-toggle" id="mobileMenuToggle" aria-label="Toggle menu">
<span class="material-icons-round">menu</span>
</button>
</div>
</div>
</header>
EOF
# 7. _includes/footer.html
cat > _includes/footer.html << 'EOF'
<footer class="site-footer">
<div class="footer-container">
<div class="footer-grid">
<div class="footer-brand">
<div class="brand-logo">
<span class="material-icons-round">eco</span>
<span class="brand-text">{{ site.title }}</span>
</div>
<p>{{ site.description }}</p>
<div class="social-links">
<a href="#" class="social-link" aria-label="Twitter">
<span class="material-icons-round">chat</span>
</a>
<a href="#" class="social-link" aria-label="Instagram">
<span class="material-icons-round">photo_camera</span>
</a>
<a href="#" class="social-link" aria-label="GitHub">
<span class="material-icons-round">code</span>
</a>
</div>
</div>
<div class="footer-links">
<h3>Navigasi</h3>
<ul>
<li><a href="{{ '/' | relative_url }}">Beranda</a></li>
<li><a href="/about">Tentang</a></li>
<li><a href="/categories">Kategori</a></li>
<li><a href="/tags">Tags</a></li>
</ul>
</div>
<div class="footer-categories">
<h3>Kategori Populer</h3>
<ul>
{% assign sorted_categories = site.categories | sort %}
{% for category in sorted_categories limit: 5 %}
<li><a href="/category/{{ category[0] | slugify }}">{{ category[0] }}</a></li>
{% endfor %}
</ul>
</div>
<div class="footer-newsletter">
<h3>Newsletter</h3>
<p>Dapatkan update artikel terbaru</p>
<form class="newsletter-form">
<input type="email" placeholder="Email Anda" required>
<button type="submit" class="btn-primary">
<span class="material-icons-round">send</span>
</button>
</form>
</div>
</div>
<div class="footer-bottom">
<p>© {{ site.time | date: '%Y' }} {{ site.title }}. All rights reserved.</p>
<p>Powered by <a href="https://jekyllrb.com" target="_blank">Jekyll</a> & Material Design 3</p>
</div>
</div>
</footer>
EOF
# 8. _includes/post-card.html
cat > _includes/post-card.html << 'EOF'
<article class="post-card" data-categories="{{ include.post.categories | join: ' ' }}" data-tags="{{ include.post.tags | join: ' ' }}">
<a href="{{ include.post.url | relative_url }}" class="post-card-link">
{% if include.post.image %}
<div class="post-card-image">
<img src="{{ include.post.image | relative_url }}" alt="{{ include.post.title }}" loading="lazy">
<div class="post-card-overlay"></div>
</div>
{% else %}
<div class="post-card-image post-card-image-placeholder">
<span class="material-icons-round">image</span>
</div>
{% endif %}
<div class="post-card-content">
<div class="post-card-meta">
{% if include.post.categories %}
<span class="post-card-category">{{ include.post.categories[0] }}</span>
{% endif %}
<time datetime="{{ include.post.date | date_to_xmlschema }}">
{{ include.post.date | date: "%d %b %Y" }}
</time>
</div>
<h3 class="post-card-title">{{ include.post.title }}</h3>
<p class="post-card-excerpt">
{% if include.post.description %}
{{ include.post.description }}
{% else %}
{{ include.post.excerpt | strip_html | truncate: 120 }}
{% endif %}
</p>
<div class="post-card-footer">
<div class="post-card-author">
<span class="material-icons-round">person</span>
<span>{{ include.post.author | default: "Admin" }}</span>
</div>
<div class="post-card-reading-time">
<span class="material-icons-round">schedule</span>
<span>{% assign words = include.post.content | number_of_words %}{% if words < 360 %}1 min{% else %}{{ words | divided_by: 180 }} min{% endif %}</span>
</div>
</div>
</div>
</a>
</article>
EOF
# 9. _sass/main.scss
cat > _sass/main.scss << 'EOF'
// Material Design 3 - Nature Theme
:root {
// Primary Colors - Green/Teal Nature Theme
--md-sys-color-primary: #2E7D32;
--md-sys-color-on-primary: #FFFFFF;
--md-sys-color-primary-container: #B8E6B8;
--md-sys-color-on-primary-container: #002106;
// Secondary Colors - Teal
--md-sys-color-secondary: #00897B;
--md-sys-color-on-secondary: #FFFFFF;
--md-sys-color-secondary-container: #B2DFDB;
--md-sys-color-on-secondary-container: #00211F;
// Tertiary - Soft Green
--md-sys-color-tertiary: #66BB6A;
--md-sys-color-on-tertiary: #FFFFFF;
--md-sys-color-tertiary-container: #C8E6C9;
--md-sys-color-on-tertiary-container: #0A2E0D;
// Surface Colors
--md-sys-color-surface: #FAFAFA;
--md-sys-color-surface-variant: #F5F5F5;
--md-sys-color-on-surface: #1C1B1F;
--md-sys-color-on-surface-variant: #49454F;
// Outline
--md-sys-color-outline: #79747E;
--md-sys-color-outline-variant: #CAC4D0;
// Background
--md-sys-color-background: #F6F9F6;
--md-sys-color-on-background: #1C1B1F;
// Error
--md-sys-color-error: #B3261E;
--md-sys-color-on-error: #FFFFFF;
// Elevation
--md-sys-elevation-1: 0 1px 2px rgba(0,0,0,0.3), 0 1px 3px 1px rgba(0,0,0,0.15);
--md-sys-elevation-2: 0 1px 2px rgba(0,0,0,0.3), 0 2px 6px 2px rgba(0,0,0,0.15);
--md-sys-elevation-3: 0 1px 3px rgba(0,0,0,0.3), 0 4px 8px 3px rgba(0,0,0,0.15);
// Shape
--md-sys-shape-corner-small: 8px;
--md-sys-shape-corner-medium: 12px;
--md-sys-shape-corner-large: 16px;
--md-sys-shape-corner-extra-large: 28px;
// Typography
--md-sys-typescale-display-large: 400 3.5rem/4rem 'Plus Jakarta Sans', sans-serif;
--md-sys-typescale-headline-large: 400 2rem/2.5rem 'Plus Jakarta Sans', sans-serif;
--md-sys-typescale-title-large: 500 1.375rem/1.75rem 'Plus Jakarta Sans', sans-serif;
--md-sys-typescale-body-large: 400 1rem/1.5rem 'Plus Jakarta Sans', sans-serif;
--md-sys-typescale-body-medium: 400 0.875rem/1.25rem 'Plus Jakarta Sans', sans-serif;
--md-sys-typescale-label-large: 500 0.875rem/1.25rem 'Plus Jakarta Sans', sans-serif;
}
// Dark Theme
[data-theme="dark"] {
--md-sys-color-primary: #81C784;
--md-sys-color-on-primary: #003914;
--md-sys-color-primary-container: #005221;
--md-sys-color-on-primary-container: #9CEC98;
--md-sys-color-secondary: #4DB6AC;
--md-sys-color-on-secondary: #003733;
--md-sys-color-secondary-container: #004F4A;
--md-sys-color-on-secondary-container: #6FE7DC;
--md-sys-color-surface: #1C1B1F;
--md-sys-color-surface-variant: #2D2D2D;
--md-sys-color-on-surface: #E6E1E5;
--md-sys-color-on-surface-variant: #CAC4D0;
--md-sys-color-background: #121212;
--md-sys-color-on-background: #E6E1E5;
}
// Reset & Base
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Plus Jakarta Sans', sans-serif;
background-color: var(--md-sys-color-background);
color: var(--md-sys-color-on-background);
line-height: 1.6;
transition: background-color 0.3s, color 0.3s;
}
// Container
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 24px;
}
// Header
.site-header {
background-color: var(--md-sys-color-surface);
box-shadow: var(--md-sys-elevation-2);
position: sticky;
top: 0;
z-index: 1000;
backdrop-filter: blur(10px);
background-color: rgba(var(--md-sys-color-surface), 0.9);
}
.header-container {
max-width: 1200px;
margin: 0 auto;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
}
.brand-logo {
display: flex;
align-items: center;
gap: 8px;
text-decoration: none;
color: var(--md-sys-color-primary);
font-weight: 700;
font-size: 1.5rem;
.material-icons-round {
font-size: 32px;
color: var(--md-sys-color-primary);
}
}
.header-nav {
flex: 1;
@media (max-width: 768px) {
display: none;
position: absolute;
top: 100%;
left: 0;
right: 0;
background-color: var(--md-sys-color-surface);
box-shadow: var(--md-sys-elevation-2);
padding: 16px;
}
&.active {
display: block;
}
}
.nav-list {
display: flex;
list-style: none;
gap: 8px;
justify-content: center;
@media (max-width: 768px) {
flex-direction: column;
}
}
.nav-link {
padding: 10px 20px;
text-decoration: none;
color: var(--md-sys-color-on-surface-variant);
font-weight: 500;
border-radius: var(--md-sys-shape-corner-small);
transition: all 0.3s;
&:hover, &.active {
background-color: var(--md-sys-color-primary-container);
color: var(--md-sys-color-on-primary-container);
}
}
.header-actions {
display: flex;
align-items: center;
gap: 8px;
}
.theme-toggle,
.mobile-menu-toggle {
background: none;
border: none;
cursor: pointer;
padding: 8px;
border-radius: 50%;
color: var(--md-sys-color-on-surface-variant);
transition: background-color 0.3s;
&:hover {
background-color: var(--md-sys-color-surface-variant);
}
.material-icons-round {
font-size: 24px;
}
}
.mobile-menu-toggle {
display: none;
@media (max-width: 768px) {
display: block;
}
}
// Hero Section
.hero-section {
background: linear-gradient(135deg, var(--md-sys-color-primary-container) 0%, var(--md-sys-color-secondary-container) 100%);
padding: 80px 24px;
text-align: center;
margin-bottom: 48px;
border-radius: 0 0 var(--md-sys-shape-corner-extra-large) var(--md-sys-shape-corner-extra-large);
}
.hero-title {
font: var(--md-sys-typescale-display-large);
color: var(--md-sys-color-on-primary-container);
margin-bottom: 16px;
}
.hero-subtitle {
font: var(--md-sys-typescale-body-large);
color: var(--md-sys-color-on-secondary-container);
max-width: 600px;
margin: 0 auto;
}
// Filter Section
.filter-section {
margin-bottom: 48px;
}
.filter-container {
display: flex;
gap: 16px;
flex-wrap: wrap;
align-items: center;
justify-content: center;
padding: 24px;
background-color: var(--md-sys-color-surface);
border-radius: var(--md-sys-shape-corner-large);
box-shadow: var(--md-sys-elevation-1);
}
.filter-group {
display: flex;
align-items: center;
gap: 8px;
background-color: var(--md-sys-color-surface-variant);
padding: 8px 16px;
border-radius: var(--md-sys-shape-corner-medium);
.material-icons-round {
color: var(--md-sys-color-outline);
font-size: 20px;
}
}
.filter-select {
border: none;
background: transparent;
font: var(--md-sys-typescale-body-medium);
color: var(--md-sys-color-on-surface);
cursor: pointer;
outline: none;
min-width: 150px;
}
.search-group {
display: flex;
align-items: center;
gap: 8px;
background-color: var(--md-sys-color-surface-variant);
padding: 8px 16px;
border-radius: var(--md-sys-shape-corner-medium);
flex: 1;
max-width: 300px;
.material-icons-round {
color: var(--md-sys-color-outline);
font-size: 20px;
}
}
.search-input {
border: none;
background: transparent;
font: var(--md-sys-typescale-body-medium);
color: var(--md-sys-color-on-surface);
width: 100%;
outline: none;
}
// Posts Grid
.posts-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 32px;
margin-bottom: 48px;
@media (max-width: 768px) {
grid-template-columns: 1fr;
}
}
// Post Card
.post-card {
background-color: var(--md-sys-color-surface);
border-radius: var(--md-sys-shape-corner-large);
overflow: hidden;
box-shadow: var(--md-sys-elevation-1);
transition: all 0.3s;
&:hover {
transform: translateY(-4px);
box-shadow: var(--md-sys-elevation-3);
}
}
.post-card-link {
text-decoration: none;
color: inherit;
display: block;
}
.post-card-image {
position: relative;
height: 220px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
&:hover img {
transform: scale(1.05);
}
}
.post-card-image-placeholder {
background: linear-gradient(135deg, var(--md-sys-color-primary-container), var(--md-sys-color-secondary-container));
display: flex;
align-items: center;
justify-content: center;
.material-icons-round {
font-size: 64px;
color: var(--md-sys-color-on-primary-container);
opacity: 0.5;
}
}
.post-card-content {
padding: 24px;
}
.post-card-meta {
display: flex;
gap: 12px;
align-items: center;
margin-bottom: 12px;
font: var(--md-sys-typescale-body-medium);
color: var(--md-sys-color-outline);
}
.post-card-category {
background-color: var(--md-sys-color-tertiary-container);
color: var(--md-sys-color-on-tertiary-container);
padding: 4px 12px;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
}
.post-card-title {
font: var(--md-sys-typescale-title-large);
color: var(--md-sys-color-on-surface);
margin-bottom: 12px;
line-height: 1.4;
}
.post-card-excerpt {
font: var(--md-sys-typescale-body-medium);
color: var(--md-sys-color-on-surface-variant);
margin-bottom: 16px;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.post-card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 16px;
border-top: 1px solid var(--md-sys-color-outline-variant);
font: var(--md-sys-typescale-body-medium);
color: var(--md-sys-color-outline);
.material-icons-round {
font-size: 16px;
margin-right: 4px;
vertical-align: middle;
}
}
// Post Article
.post-article {
padding: 48px 0;
}
.post-header {
max-width: 800px;
margin: 0 auto 48px;
text-align: center;
}
.post-meta {
display: flex;
gap: 16px;
justify-content: center;
align-items: center;
flex-wrap: wrap;
margin-bottom: 24px;
font: var(--md-sys-typescale-body-medium);
color: var(--md-sys-color-outline);
.material-icons-round {
font-size: 18px;
vertical-align: middle;
margin-right: 4px;
}
}
.category-badge {
background-color: var(--md-sys-color-primary-container);
color: var(--md-sys-color-on-primary-container);
padding: 6px 16px;
border-radius: 16px;
font-size: 0.875rem;
font-weight: 600;
}
.post-title {
font: var(--md-sys-typescale-display-large);
color: var(--md-sys-color-on-surface);
margin-bottom: 24px;
line-height: 1.2;
}
.post-excerpt {
font: var(--md-sys-typescale-body-large);
color: var(--md-sys-color-on-surface-variant);
margin-bottom: 32px;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.post-author {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
}
.author-avatar {
width: 48px;
height: 48px;
border-radius: 50%;
background-color: var(--md-sys-color-primary-container);
display: flex;
align-items: center;
justify-content: center;
.material-icons-round {
color: var(--md-sys-color-on-primary-container);
}
}
.author-info {
text-align: left;
.author-name {
display: block;
font-weight: 600;
color: var(--md-sys-color-on-surface);
}
.author-role {
font-size: 0.875rem;
color: var(--md-sys-color-outline);
}
}
.post-featured-image {
max-width: 1000px;
margin: 0 auto 48px;
border-radius: var(--md-sys-shape-corner-large);
overflow: hidden;
img {
width: 100%;
height: auto;
display: block;
}
}
.post-content {
max-width: 800px;
margin: 0 auto;
font: var(--md-sys-typescale-body-large);
color: var(--md-sys-color-on-surface);
line-height: 1.8;
h2 {
font: var(--md-sys-typescale-headline-large);
margin: 48px 0 24px;
color: var(--md-sys-color-on-surface);
}
h3 {
font: var(--md-sys-typescale-title-large);
margin: 32px 0 16px;
color: var(--md-sys-color-on-surface);
}
p {
margin-bottom: 24px;
}
blockquote {
border-left: 4px solid var(--md-sys-color-primary);
padding: 16px 24px;
margin: 32px 0;
background-color: var(--md-sys-color-primary-container);
border-radius: 0 var(--md-sys-shape-corner-medium) var(--md-sys-shape-corner-medium) 0;
font-style: italic;
color: var(--md-sys-color-on-primary-container);
}
code {
background-color: var(--md-sys-color-surface-variant);
padding: 2px 8px;
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 0.9em;
color: var(--md-sys-color-secondary);
}
pre {
background-color: var(--md-sys-color-surface-variant);
padding: 24px;
border-radius: var(--md-sys-shape-corner-medium);
overflow-x: auto;
margin: 32px 0;
code {
background: none;
padding: 0;
color: var(--md-sys-color-on-surface);
}
}
table {
width: 100%;
border-collapse: collapse;
margin: 32px 0;
background-color: var(--md-sys-color-surface);
border-radius: var(--md-sys-shape-corner-medium);
overflow: hidden;
box-shadow: var(--md-sys-elevation-1);
th, td {
padding: 16px;
text-align: left;
border-bottom: 1px solid var(--md-sys-color-outline-variant);
}
th {
background-color: var(--md-sys-color-primary-container);
color: var(--md-sys-color-on-primary-container);
font-weight: 600;
}
tr:hover {
background-color: var(--md-sys-color-surface-variant);
}
}
img {
max-width: 100%;
height: auto;
border-radius: var(--md-sys-shape-corner-medium);
margin: 32px 0;
}
ul, ol {
margin: 24px 0;
padding-left: 32px;
li {
margin-bottom: 12px;
}
}
a {
color: var(--md-sys-color-primary);
text-decoration: none;
border-bottom: 2px solid transparent;
transition: border-color 0.3s;
&:hover {
border-bottom-color: var(--md-sys-color-primary);
}
}
}
.post-tags {
max-width: 800px;
margin: 48px auto;
padding: 24px;
background-color: var(--md-sys-color-surface);
border-radius: var(--md-sys-shape-corner-large);
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
.material-icons-round {
color: var(--md-sys-color-outline);
}
}
.tag-link {
background-color: var(--md-sys-color-secondary-container);
color: var(--md-sys-color-on-secondary-container);
padding: 6px 16px;
border-radius: 16px;
text-decoration: none;
font-size: 0.875rem;
font-weight: 500;
transition: all 0.3s;
&:hover {
background-color: var(--md-sys-color-secondary);
color: var(--md-sys-color-on-secondary);
}
}
.post-share {
max-width: 800px;
margin: 48px auto;
padding: 32px;
background-color: var(--md-sys-color-surface);
border-radius: var(--md-sys-shape-corner-large);
text-align: center;
h3 {
margin-bottom: 24px;
color: var(--md-sys-color-on-surface);
}
}
.share-buttons {
display: flex;
gap: 12px;
justify-content: center;
}
.share-btn {
width: 48px;
height: 48px;
border-radius: 50%;
border: none;
background-color: var(--md-sys-color-primary-container);
color: var(--md-sys-color-on-primary-container);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
&:hover {
background-color: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
transform: translateY(-2px);
}
.material-icons-round {
font-size: 24px;
}
}
// Footer
.site-footer {
background-color: var(--md-sys-color-surface);
margin-top: 96px;
padding: 64px 0 32px;
border-top: 1px solid var(--md-sys-color-outline-variant);
}
.footer-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 24px;
}
.footer-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 48px;
margin-bottom: 48px;
}
.footer-brand {
.brand-logo {
margin-bottom: 16px;
display: inline-flex;
}
p {
color: var(--md-sys-color-on-surface-variant);
margin-bottom: 24px;
}
}
.social-links {
display: flex;
gap: 12px;
}
.social-link {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: var(--md-sys-color-surface-variant);
display: flex;
align-items: center;
justify-content: center;
color: var(--md-sys-color-on-surface-variant);
text-decoration: none;
transition: all 0.3s;
&:hover {
background-color: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
}
.material-icons-round {
font-size: 20px;
}
}
.footer-links,
.footer-categories {
h3 {
font: var(--md-sys-typescale-title-large);
margin-bottom: 24px;
color: var(--md-sys-color-on-surface);
}
ul {
list-style: none;
li {
margin-bottom: 12px;
a {
color: var(--md-sys-color-on-surface-variant);
text-decoration: none;
transition: color 0.3s;
&:hover {
color: var(--md-sys-color-primary);
}
}
}
}
}
.footer-newsletter {
h3 {
font: var(--md-sys-typescale-title-large);
margin-bottom: 16px;
color: var(--md-sys-color-on-surface);
}
p {
color: var(--md-sys-color-on-surface-variant);
margin-bottom: 24px;
}
}
.newsletter-form {
display: flex;
gap: 8px;
input {
flex: 1;
padding: 12px 16px;
border: 1px solid var(--md-sys-color-outline);
border-radius: var(--md-sys-shape-corner-medium);
background-color: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
font: var(--md-sys-typescale-body-medium);
outline: none;
&:focus {
border-color: var(--md-sys-color-primary);
}
}
}
.btn-primary {
padding: 12px 24px;
background-color: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
border: none;
border-radius: var(--md-sys-shape-corner-medium);
font: var(--md-sys-typescale-label-large);
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 8px;
&:hover {
background-color: var(--md-sys-color-on-primary-container);
transform: translateY(-2px);
box-shadow: var(--md-sys-elevation-2);
}
}
.footer-bottom {
text-align: center;
padding-top: 32px;
border-top: 1px solid var(--md-sys-color-outline-variant);
color: var(--md-sys-color-on-surface-variant);
font: var(--md-sys-typescale-body-medium);
a {
color: var(--md-sys-color-primary);
text-decoration: none;
}
}
// Loading & Utilities
.loading-indicator {
text-align: center;
padding: 48px;
}
.spinner {
width: 48px;
height: 48px;
border: 4px solid var(--md-sys-color-outline-variant);
border-top-color: var(--md-sys-color-primary);
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.no-results {
text-align: center;
padding: 64px 24px;
color: var(--md-sys-color-on-surface-variant);
.material-icons-round {
font-size: 64px;
margin-bottom: 16px;
opacity: 0.5;
}
}
// Responsive
@media (max-width: 768px) {
.hero-section {
padding: 48px 24px;
}
.hero-title {
font-size: 2rem;
}
.filter-container {
flex-direction: column;
}
.search-group {
max-width: 100%;
width: 100%;
}
.posts-grid {
grid-template-columns: 1fr;
}
.post-content {
padding: 0 16px;
}
.footer-grid {
grid-template-columns: 1fr;
gap: 32px;
}
}
// Print styles
@media print {
.site-header,
.site-footer,
.filter-section,
.post-share {
display: none;
}
.post-content {
max-width: 100%;
}
}
EOF
# 10. assets/js/main.js
cat > assets/js/main.js << 'EOF'
// Theme Toggle
const themeToggle = document.getElementById('themeToggle');
const html = document.documentElement;
// Check for saved theme preference or prefer-color-scheme
const currentTheme = localStorage.getItem('theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
html.setAttribute('data-theme', currentTheme);
updateThemeIcon(currentTheme);
themeToggle?.addEventListener('click', () => {
const currentTheme = html.getAttribute('data-theme');
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
html.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
updateThemeIcon(newTheme);
});
function updateThemeIcon(theme) {
const icon = themeToggle?.querySelector('.material-icons-round');
if (icon) {
icon.textContent = theme === 'light' ? 'dark_mode' : 'light_mode';
}
}
// Mobile Menu Toggle
const mobileMenuToggle = document.getElementById('mobileMenuToggle');
const headerNav = document.getElementById('headerNav');
mobileMenuToggle?.addEventListener('click', () => {
headerNav?.classList.toggle('active');
const icon = mobileMenuToggle.querySelector('.material-icons-round');
icon.textContent = headerNav?.classList.contains('active') ? 'close' : 'menu';
});
// Filter Functionality
const categoryFilter = document.getElementById('categoryFilter');
const tagFilter = document.getElementById('tagFilter');
const searchInput = document.getElementById('searchInput');
const postsContainer = document.getElementById('postsContainer');
const noResults = document.getElementById('noResults');
function filterPosts() {
const category = categoryFilter?.value || '';
const tag = tagFilter?.value || '';
const search = searchInput?.value.toLowerCase() || '';
const posts = document.querySelectorAll('.post-card');
let visibleCount = 0;
posts.forEach(post => {
const postCategories = post.dataset.categories || '';
const postTags = post.dataset.tags || '';
const title = post.querySelector('.post-card-title')?.textContent.toLowerCase() || '';
const excerpt = post.querySelector('.post-card-excerpt')?.textContent.toLowerCase() || '';
const matchCategory = !category || postCategories.includes(category);
const matchTag = !tag || postTags.includes(tag);
const matchSearch = !search || title.includes(search) || excerpt.includes(search);
if (matchCategory && matchTag && matchSearch) {
post.style.display = 'block';
visibleCount++;
} else {
post.style.display = 'none';
}
});
if (noResults) {
noResults.style.display = visibleCount === 0 ? 'block' : 'none';
}
}
categoryFilter?.addEventListener('change', filterPosts);
tagFilter?.addEventListener('change', filterPosts);
searchInput?.addEventListener('input', filterPosts);
// Infinite Scroll
let currentPage = window.currentPage || 1;
const totalPages = window.totalPages || 1;
let isLoading = false;
const loadingIndicator = document.getElementById('loadingIndicator');
function loadMorePosts() {
if (isLoading || currentPage >= totalPages) return;
isLoading = true;
loadingIndicator.style.display = 'block';
currentPage++;
// Fetch next page
fetch(`/page${currentPage}/`)
.then(response => response.text())
.then(html => {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const newPosts = doc.querySelectorAll('.post-card');
newPosts.forEach(post => {
postsContainer?.appendChild(post.cloneNode(true));
});
isLoading = false;
loadingIndicator.style.display = 'none';
// Reapply filters
filterPosts();
})
.catch(error => {
console.error('Error loading posts:', error);
isLoading = false;
loadingIndicator.style.display = 'none';
});
}
// Intersection Observer for infinite scroll
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadMorePosts();
}
},
{ threshold: 0.1 }
);
if (loadingIndicator) {
observer.observe(loadingIndicator);
}
// Share Functionality
function sharePost(platform) {
const url = encodeURIComponent(window.location.href);
const title = encodeURIComponent(document.title);
let shareUrl = '';
switch(platform) {
case 'twitter':
shareUrl = `https://twitter.com/intent/tweet?url=${url}&text=${title}`;
break;
case 'facebook':
shareUrl = `https://www.facebook.com/sharer/sharer.php?u=${url}`;
break;
case 'linkedin':
shareUrl = `https://www.linkedin.com/sharing/share-offsite/?url=${url}`;
break;
}
if (shareUrl) {
window.open(shareUrl, '_blank', 'width=600,height=400');
}
}
function copyLink() {
navigator.clipboard.writeText(window.location.href).then(() => {
alert('Link copied to clipboard!');
}).catch(err => {
console.error('Failed to copy:', err);
});
}
// Smooth scroll for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Add scroll effect to header
let lastScroll = 0;
const header = document.querySelector('.site-header');
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 100) {
header?.classList.add('scrolled');
} else {
header?.classList.remove('scrolled');
}
lastScroll = currentScroll;
});
// Newsletter form
const newsletterForm = document.querySelector('.newsletter-form');
newsletterForm?.addEventListener('submit', (e) => {
e.preventDefault();
const email = e.target.querySelector('input[type="email"]').value;
// Here you would typically send the email to your backend
alert(`Thank you for subscribing with: ${email}`);
e.target.reset();
});
// Add animation on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const scrollObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-in');
scrollObserver.unobserve(entry.target);
}
});
}, observerOptions);
document.querySelectorAll('.post-card').forEach(card => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
scrollObserver.observe(card);
});
// Add CSS for animation
const style = document.createElement('style');
style.textContent = `
.post-card.animate-in {
opacity: 1 !important;
transform: translateY(0) !important;
}
.site-header.scrolled {
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
`;
document.head.appendChild(style);
EOF
# 11. assets/css/main.scss (wrapper)
mkdir -p assets/css
cat > assets/css/main.scss << 'EOF'
---
---
@import "../sass/main";
EOF
# 12. Sample Posts
cat > _posts/2024-01-15-mengenal-keanekaragaman-hayati.md << 'EOF'
---
layout: post
title: "Mengenal Keanekaragaman Hayati Indonesia"
date: 2024-01-15 10:00:00 +0700
categories: [alam, konservasi]
tags: [biodiversitas, indonesia, lingkungan]
description: "Indonesia merupakan salah satu negara dengan tingkat keanekaragaman hayati tertinggi di dunia. Mari kita pelajari lebih dalam."
image: /assets/images/biodiversity.jpg
author: "Dr. Ahmad Wijaya"
---
Indonesia dikenal sebagai salah satu negara **mega-biodiversity** di dunia. Dengan lebih dari 17.000 pulau, negara ini memiliki kekayaan alam yang luar biasa.
## Mengapa Indonesia Kaya Akan Biodiversitas?
Ada beberapa faktor yang membuat Indonesia memiliki keanekaragaman hayati yang tinggi:
1. **Posisi Geografis** - Terletak di garis khatulistiwa
2. **Kepulauan** - Ribuan pulau menciptakan isolasi geografis
3. **Iklim Tropis** - Mendukung pertumbuhan berbagai spesies
### Data Keanekaragaman Hayati
| Kategori | Jumlah Spesies | Persentase Dunia |
|----------|----------------|------------------|
| Tumbuhan | 28,000+ | 10% |
| Burung | 1,771 | 16% |
| Mamalia | 515 | 12% |
| Reptil | 781 | 16% |
> "Keanekaragaman hayati adalah warisan yang harus kita jaga untuk generasi mendatang." - Prof. Jatna Supriatna
## Ancaman Terhadap Biodiversitas
Sayangnya, keanekaragaman hayati Indonesia menghadapi berbagai ancaman:
```python
# Contoh kode untuk menghitung tingkat kepunahan
def calculate_extinction_rate(species_count, endangered_count):
rate = (endangered_count / species_count) * 100
return rate
# Data contoh
total_species = 1000
endangered = 150
rate = calculate_extinction_rate(total_species, endangered)
print(f"Tingkat kepunahan: {rate}%")
Upaya Konservasi
Pemerintah dan berbagai organisasi melakukan berbagai upaya:
- Pembentukan taman nasional
- Program penangkaran satwa langka
- Edukasi masyarakat
- Penegakan hukum terhadap perusakan habitat
Hutan hujan tropis Indonesia adalah paru-paru dunia
Kesimpulan
Menjaga keanekaragaman hayati adalah tanggung jawab kita bersama. Mari mulai dari hal kecil untuk melestarikan alam Indonesia. EOF
cat > _posts/2024-01-20-teknologi-hijau.md << 'EOF'
layout: post title: "Teknologi Hijau untuk Masa Depan Berkelanjutan" date: 2024-01-20 14:30:00 +0700 categories: [teknologi, lingkungan] tags: [green tech, renewable energy, sustainability] description: "Perkembangan teknologi hijau membuka peluang untuk masa depan yang lebih berkelanjutan dan ramah lingkungan." image: /assets/images/green-tech.jpg author: "Sarah Amelia"
Teknologi hijau atau green technology menjadi solusi penting dalam menghadapi perubahan iklim dan degradasi lingkungan.
Apa itu Teknologi Hijau?
Teknologi hijau merujuk pada penerapan ilmu pengetahuan untuk menciptakan produk dan layanan yang ramah lingkungan.
Jenis-jenis Teknologi Hijau
1. Energi Terbarukan
Energi terbarukan adalah sumber energi yang berasal dari proses alam yang berkelanjutan:
- Solar Panel - Energi matahari
- Wind Turbine - Energi angin
- Hydro Power - Energi air
- Geothermal - Energi panas bumi
2. Bangunan Hijau
Konsep bangunan yang efisien dalam penggunaan sumber daya:
// Contoh perhitungan efisiensi energi
class GreenBuilding {
constructor(area, occupants) {
this.area = area;
this.occupants = occupants;
}
calculateEnergyEfficiency() {
const baseConsumption = this.area * 50; // kWh per m²
const optimizedConsumption = baseConsumption * 0.6; // 40% savings
return optimizedConsumption;
}
}
const building = new GreenBuilding(1000, 50);
console.log(`Energy consumption: ${building.calculateEnergyEfficiency()} kWh`);
Keuntungan Teknologi Hijau
| Aspek | Keuntungan |
|---|---|
| Ekonomi | Penghematan biaya jangka panjang |
| Lingkungan | Mengurangi emisi karbon |
| Sosial | Menciptakan lapangan kerja hijau |
| Kesehatan | Udara dan air yang lebih bersih |
"Investasi dalam teknologi hijau bukan hanya tentang menyelamatkan planet, tapi juga tentang menciptakan ekonomi yang lebih kuat." - Ban Ki-moon
Studi Kasus: Kota Hijau di Indonesia
Beberapa kota di Indonesia mulai menerapkan konsep kota hijau:
- Surabaya - Program Surabaya Green and Clean
- Bandung - Bandung Smart City
- Bali - Bali Green Province
Tantangan Implementasi
Meski menjanjikan, ada beberapa tantangan:
- Biaya investasi awal yang tinggi
- Kurangnya kesadaran masyarakat
- Regulasi yang belum optimal
- Keterbatasan teknologi lokal
Masa Depan Teknologi Hijau
Dengan perkembangan AI dan IoT, teknologi hijau akan semakin canggih:
- Smart grid untuk distribusi energi
- Vertical farming untuk ketahanan pangan
- Electric vehicles untuk transportasi bersih
- Waste-to-energy untuk pengelolaan sampah
Mari bersama-sama mendukung transisi menuju ekonomi hijau yang berkelanjutan! EOF
cat > _posts/2024-01-25-pertanian-organik.md << 'EOF'
layout: post title: "Panduan Lengkap Pertanian Organik untuk Pemula" date: 2024-01-25 09:15:00 +0700 categories: [pertanian, gaya-hidup] tags: [organik, farming, sustainable] description: "Pelajari cara memulai pertanian organik dari nol dengan panduan lengkap ini." image: /assets/images/organic-farm.jpg author: "Budi Santoso"
Pertanian organik semakin populer di kalangan masyarakat yang peduli kesehatan dan lingkungan.
Apa itu Pertanian Organik?
Pertanian organik adalah sistem budidaya pertanian yang mengandalkan bahan-bahan alami tanpa menggunakan bahan kimia sintetis.
Prinsip Dasar Pertanian Organik
- Kesehatan Tanah - Tanah yang sehat menghasilkan tanaman yang sehat
- Keanekaragaman - Rotasi tanaman dan polikultur
- Keseimbangan Ekologi - Menjaga keseimbangan alam
- Keberlanjutan - Sistem yang bisa berlanjut untuk generasi mendatang
Langkah Memulai Pertanian Organik
1. Persiapan Lahan
# Checklist persiapan lahan
- [ ] Tes pH tanah
- [ ] Pembersihan lahan
- [ ] Pembuatan bedengan
- [ ] Sistem irigasi
- [ ] Kompos dan pupuk organik
2. Pemilihan Benih
Pilih benih yang:
- Bersertifikat organik
- Adaptif dengan iklim lokal
- Tahan terhadap hama
- Produktivitas tinggi
3. Pembuatan Kompos
Kompos adalah pupuk organik terbaik. Berikut komposisinya:
| Bahan | Proporsi | Fungsi |
|---|---|---|
| Bahan Hijau | 40% | Sumber nitrogen |
| Bahan Coklat | 40% | Sumber karbon |
| Tanah | 10% | Mikroorganisme |
| Pupuk Kandang | 10% | Nutrisi tambahan |
"Tanah yang sehat adalah fondasi dari pertanian organik yang sukses." - Sir Albert Howard
Pengendalian Hama Alami
Pestisida Alami
Berikut resep pestisida alami sederhana:
Bahan:
- 10 siung bawang putih
- 10 buah cabai rawit
- 1 liter air
- 1 sendok makan sabun cair organik
Cara Pembuatan:
- Haluskan bawang putih dan cabai
- Campur dengan air
- Diamkan 24 jam
- Saring dan tambahkan sabun
- Semprotkan ke tanaman
Tanaman Pendamping
Beberapa kombinasi tanaman yang efektif:
- Tomat + Basil - Basil mengusir lalat putih
- Wortel + Bawang - Mengusir lalat wortel
- Kubis + Seledri - Mengusir kupu-kubis
Manfaat Pertanian Organik
Untuk Kesehatan
- Bebas residu pestisida
- Kandungan nutrisi lebih tinggi
- Rasa lebih alami
Untuk Lingkungan
- Menjaga kesuburan tanah
- Melindungi sumber air
- Meningkatkan biodiversitas
- Mengurangi emisi karbon
Untuk Ekonomi
- Harga jual lebih tinggi
- Pasar yang terus berkembang
- Kemandirian petani
Tips untuk Pemula
- Mulai Kecil - Jangan langsung skala besar
- Belajar Terus - Ikuti pelatihan dan workshop
- Bergabung dengan Komunitas - Belajar dari pengalaman orang lain
- Sabar - Hasil tidak instan, butuh proses
- Dokumentasi - Catat semua kegiatan untuk evaluasi
Kesimpulan
Pertanian organik bukan sekadar tren, tapi kebutuhan untuk masa depan yang berkelanjutan. Dengan memulai dari sekarang, kita berkontribusi untuk kesehatan keluarga dan kelestarian bumi.
Selamat bertani organik! 🌱 EOF
13. Static Pages
cat > pages/about.md << 'EOF'
layout: page title: Tentang Kami permalink: /about/ nav: true
Tentang Nature Blog
Nature Blog adalah platform digital yang didedikasikan untuk menyebarkan informasi tentang pelestarian alam, teknologi hijau, dan gaya hidup berkelanjutan.
Visi Kami
Menjadi sumber informasi terpercaya yang menginspirasi masyarakat untuk hidup lebih harmonis dengan alam.
Misi Kami
- Menyediakan konten berkualitas tentang lingkungan dan keberlanjutan
- Mengedukasi masyarakat tentang pentingnya pelestarian alam
- Mempromosikan teknologi dan praktik ramah lingkungan
- Membangun komunitas yang peduli terhadap masa depan bumi
Tim Kami
Tim kami terdiri dari para profesional yang passionate di bidang:
- Konservasi lingkungan
- Teknologi hijau
- Pertanian berkelanjutan
- Pendidikan lingkungan
Kontak
- Email: hello@natureblog.com
- Telepon: +62 21 1234567
- Alamat: Jakarta, Indonesia
Mari bersama-sama menciptakan masa depan yang lebih hijau! 🌿 EOF
cat > pages/categories.md << 'EOF'
layout: page title: Kategori permalink: /categories/ nav: true
Kategori Artikel
{% assign categories = site.categories | sort %} {% for category in categories %}
{{ category[0] }}
{% endfor %} EOF
cat > pages/tags.md << 'EOF'
layout: page title: Tags permalink: /tags/ nav: true
Tags
EOF
14. Create _config for pagination
cat > _config.yml << 'EOF' title: "Nature Blog" description: "Blog bertema alam dengan konten berkualitas tentang lingkungan, teknologi hijau, dan gaya hidup berkelanjutan" baseurl: "" url: "https://yourusername.github.io"
Build settings
markdown: kramdown highlighter: rouge permalink: /:year/:month/:day/:title/ paginate: 6 paginate_path: "/page:num/" plugins:
- jekyll-paginate
- jekyll-seo-tag
- jekyll-sitemap
- jekyll-feed
Collections
collections: pages: output: true permalink: /:name/
Defaults
defaults:
- scope: path: "" type: "posts" values: layout: "post" author: "Admin"
- scope: path: "" values: layout: "default"
SEO
twitter: username: yourtwitter social: name: "Nature Blog" links: - https://twitter.com/yourtwitter
Exclude
exclude:
- Gemfile
- Gemfile.lock
- node_modules
- vendor
- setup_blog.sh
- README.md EOF
echo "✅ Blog Jekyll berhasil dibuat!" echo "" echo "Langkah selanjutnya:" echo "1. cd my-nature-blog" echo "2. bundle install" echo "3. bundle exec jekyll serve" echo "4. Buka http://localhost:4000" echo "" echo "Untuk deploy ke GitHub Pages:" echo "1. git init" echo "2. git add ." echo "3. git commit -m 'Initial commit'" echo "4. git remote add origin https://github.com/username/username.github.io.git" echo "5. git push -u origin main" EOF
chmod +x setup_blog.sh
## Cara Menggunakan:
1. **Jalankan Script:**
```bash
bash setup_blog.sh
cd my-nature-blog
- Install Dependencies:
bundle install
- Jalankan Lokal:
bundle exec jekyll serve
- Buka Browser:
http://localhost:4000
Fitur yang Tersedia:
✅ Material Design 3 dengan tema alam (green/teal) ✅ Responsive Design untuk semua device ✅ Infinite Scroll untuk loading artikel ✅ Filter Kategori & Tags ✅ Search Functionality ✅ Dark/Light Mode ✅ SEO Friendly dengan plugin jekyll-seo-tag ✅ Markdown Support lengkap (quotes, code, table, image) ✅ Syntax Highlighting untuk code ✅ Static Pages (About, Categories, Tags) ✅ Pagination 6 artikel per halaman ✅ Modern UI/UX seperti portal berita ✅ Share Buttons untuk social media ✅ Newsletter Form ✅ Reading Time estimator ✅ Related Posts
Struktur File:
my-nature-blog/
├── _config.yml
├── _posts/
│ ├── 2024-01-15-mengenal-keanekaragaman-hayati.md
│ ├── 2024-01-20-teknologi-hijau.md
│ └── 2024-01-25-pertanian-organik.md
├── _layouts/
│ ├── default.html
│ ├── home.html
│ └── post.html
├── _includes/
│ ├── header.html
│ ├── footer.html
│ └── post-card.html
├── _sass/
│ └── main.scss
├── assets/
│ ├── css/
│ │ └── main.scss
│ ├── js/
│ │ └── main.js
│ └── images/
├── pages/
│ ├── about.md
│ ├── categories.md
│ └── tags.md
└── Gemfile
Blog siap untuk di-deploy ke GitHub Pages! 🚀