diff --git a/src/app.js b/src/app.js
index b9cf9cb..cb41462 100644
--- a/src/app.js
+++ b/src/app.js
@@ -1827,6 +1827,90 @@ function handlePopState() {
handleRoute(false);
}
+/**
+ * Strip HTML tags from a string for meta descriptions
+ */
+function stripHtml(html) {
+ const tmp = document.createElement("div");
+ tmp.innerHTML = html || "";
+ return tmp.textContent || tmp.innerText || "";
+}
+
+/**
+ * Update page meta tags based on current route for SEO
+ */
+function updatePageMeta(route) {
+ const defaultTitle = "Code Crispies - Learn HTML & CSS Interactively | Free Coding Practice";
+ const defaultDesc =
+ "Master HTML, CSS, and Tailwind through hands-on coding exercises. Free, open-source learning platform with instant feedback. No account required.";
+
+ let title = defaultTitle;
+ let description = defaultDesc;
+
+ if (!route) {
+ document.title = title;
+ return;
+ }
+
+ switch (route.type) {
+ case RouteType.HOME:
+ // Use defaults
+ break;
+
+ case RouteType.SECTION: {
+ const sectionNames = { css: "CSS", html: "HTML", tailwind: "Tailwind CSS" };
+ const sectionName = sectionNames[route.sectionId] || route.sectionId;
+ title = `${sectionName} Lessons - Code Crispies | Learn ${sectionName}`;
+ description = `Learn ${sectionName} through interactive coding exercises. Hands-on practice with instant feedback.`;
+ break;
+ }
+
+ case RouteType.LESSON: {
+ const module = lessonEngine.modules.find((m) => m.id === route.moduleId);
+ const lesson = module?.lessons[route.lessonIndex];
+ if (module && lesson) {
+ title = `${lesson.title} - ${module.title} | Code Crispies`;
+ const lessonDesc = stripHtml(lesson.description || lesson.task);
+ description = lessonDesc.length > 155 ? lessonDesc.slice(0, 152) + "..." : lessonDesc || defaultDesc;
+ }
+ break;
+ }
+
+ case RouteType.REFERENCE: {
+ const refNames = {
+ css: "CSS Properties",
+ selectors: "CSS Selectors",
+ flexbox: "Flexbox",
+ grid: "CSS Grid",
+ html: "HTML Elements"
+ };
+ const refName = refNames[route.refId] || "Reference";
+ title = `${refName} Reference - Code Crispies`;
+ description = `Quick reference guide for ${refName}. Syntax, examples, and common patterns for web development.`;
+ break;
+ }
+ }
+
+ // Update document title
+ document.title = title;
+
+ // Update meta description
+ const metaDesc = document.querySelector('meta[name="description"]');
+ if (metaDesc) metaDesc.setAttribute("content", description);
+
+ // Update Open Graph tags
+ const ogTitle = document.querySelector('meta[property="og:title"]');
+ const ogDesc = document.querySelector('meta[property="og:description"]');
+ if (ogTitle) ogTitle.setAttribute("content", title.replace(" | Code Crispies", "").replace(" - Code Crispies", ""));
+ if (ogDesc) ogDesc.setAttribute("content", description);
+
+ // Update Twitter tags
+ const twitterTitle = document.querySelector('meta[name="twitter:title"]');
+ const twitterDesc = document.querySelector('meta[name="twitter:description"]');
+ if (twitterTitle) twitterTitle.setAttribute("content", title.replace(" | Code Crispies", "").replace(" - Code Crispies", ""));
+ if (twitterDesc) twitterDesc.setAttribute("content", description);
+}
+
/**
* Main route handler - switches between page types
*/
@@ -1858,6 +1942,7 @@ function handleRoute(shouldUpdateUrl = true) {
}
updateNavHighlight(route);
+ updatePageMeta(route);
}
/**
diff --git a/src/index.html b/src/index.html
index 0e895af..6231b8b 100644
--- a/src/index.html
+++ b/src/index.html
@@ -4,11 +4,55 @@
+
+
+
Code Crispies - Learn HTML & CSS Interactively | Free Coding Practice
- Code Crispies - Learn HTML & CSS Interactively
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -42,78 +86,76 @@
- Learn Web DevelopmentInteractively
- Master HTML, CSS, and Tailwind through hands-on exercises. Free and open source.
+ Learn Web DevelopmentBy Writing Real Code
+
+ Master HTML, CSS, and Tailwind through hands-on exercises with instant feedback. Free and open source.
+
+ Start Learning Free
-
-
-
- How It Works
-
-
-
1
-
Write Code
+
+ Why Code Crispies Works
+
+
+
+
+
+
+ Learn by Doing
- Type CSS, HTML, or Tailwind directly in the browser editor. No installation, no configuration—start coding
- immediately.
+ Write real code from lesson one. No videos to watch—just you, an editor, and instant feedback on every keystroke.
-
-
-
2
-
See Results
-
Watch your changes appear instantly in the live preview. Understand how each property affects the output.
-
-
-
3
-
Build Skills
-
Complete focused exercises that reinforce concepts. Track your progress and return anytime to continue.
-
+
+
+
+
+
+ Practice at Your Pace
+ Start with basics, fill gaps in your understanding, then accelerate. Pick up where you left off anytime.
+
+
+
+
+
+ Master Real Skills
+
+ Learn CSS, HTML, and Tailwind the way professionals use them—through hands-on exercises and
+ reference guides .
+
+
-
-
-
-
Beginner Friendly
-
- No prior experience required. Lessons start with fundamentals and introduce concepts gradually, with clear
- explanations for each step.
-
-
-
-
Practical Focus
-
- Every exercise teaches skills you'll use in real projects—flexbox layouts ,
- form styling , responsive design , and modern
- CSS techniques.
-
-
+
+ Explore Learning Paths
+
- Start Learning
- Free and open source. No account required.
+ Start Learning Today
+ Free and open source. No account required. Progress saved locally.
+ Begin Your Journey
@@ -196,9 +238,7 @@
>
⟲
-
- 🎲
-
+ 🎲
Run
diff --git a/src/main.css b/src/main.css
index e483c7f..4684dbe 100644
--- a/src/main.css
+++ b/src/main.css
@@ -1591,7 +1591,85 @@ input:checked + .toggle-slider::before {
font-size: 1.1rem;
color: var(--light-text);
max-width: 500px;
- margin: 0 auto;
+ margin: 0 auto 2rem;
+}
+
+.hero .cta-button {
+ margin-top: 1rem;
+}
+
+/* Why It Works Section */
+.why-it-works {
+ padding: 3rem 1rem;
+ text-align: center;
+}
+
+.why-it-works h2 {
+ font-size: 1.75rem;
+ color: var(--primary-dark);
+ margin-bottom: 2rem;
+}
+
+.benefits-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
+ gap: var(--spacing-lg);
+ text-align: left;
+}
+
+.benefit-card {
+ background: var(--panel-bg);
+ padding: var(--spacing-lg);
+ border-radius: var(--border-radius-lg);
+ box-shadow: var(--shadow);
+ transition:
+ transform 0.2s,
+ box-shadow 0.2s;
+}
+
+.benefit-card:hover {
+ transform: translateY(-4px);
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
+}
+
+.benefit-icon {
+ width: 48px;
+ height: 48px;
+ color: var(--primary-color);
+ margin-bottom: var(--spacing-md);
+}
+
+.benefit-card h3 {
+ font-size: 1.1rem;
+ color: var(--primary-dark);
+ margin-bottom: var(--spacing-sm);
+}
+
+.benefit-card p {
+ color: var(--light-text);
+ line-height: 1.6;
+ font-size: 0.95rem;
+}
+
+.benefit-card a {
+ color: var(--primary-color);
+ text-decoration: none;
+}
+
+.benefit-card a:hover {
+ text-decoration: underline;
+}
+
+/* Learning Paths Section */
+.learning-paths {
+ padding: 2rem 1rem 3rem;
+ text-align: center;
+}
+
+.learning-paths h2 {
+ font-size: 1.75rem;
+ color: var(--primary-dark);
+ margin-bottom: 0;
}
/* Section Cards */
@@ -1635,7 +1713,8 @@ input:checked + .toggle-slider::before {
margin-bottom: var(--spacing-md);
}
-.section-card h2 {
+.section-card h2,
+.section-card h3 {
font-size: 1.25rem;
margin-bottom: var(--spacing-xs);
}
@@ -1736,7 +1815,16 @@ input:checked + .toggle-slider::before {
/* Landing CTA */
.landing-cta {
text-align: center;
- padding: 2rem 1rem 3rem;
+ padding: 3rem 1rem;
+ background: var(--panel-bg);
+ border-radius: var(--border-radius-lg);
+ margin-top: var(--spacing-lg);
+}
+
+.landing-cta h2 {
+ font-size: 1.5rem;
+ color: var(--primary-dark);
+ margin-bottom: var(--spacing-sm);
}
.cta-button {
@@ -2089,7 +2177,9 @@ input:checked + .toggle-slider::before {
color: var(--text-color);
font-size: 0.9rem;
font-weight: 500;
- transition: background 0.2s, color 0.2s;
+ transition:
+ background 0.2s,
+ color 0.2s;
}
.ref-nav-link:hover {