added missing files

This commit is contained in:
Daniel Esteban 2026-03-31 13:02:59 +02:00
parent c76274aaf7
commit c5a4535a6a
19 changed files with 600 additions and 0 deletions

View file

@ -0,0 +1,45 @@
/* ── Go Education Project — Docs custom styles ─────────────────────── */
/* Prose heading colors — dark navy matching brand secondary */
.docs-content :is(h1, h2, h3, h4, h5, h6) {
color: #1B3A6B;
}
/* Dark mode headings — lighter so they read on dark bg */
.dark .docs-content :is(h1, h2, h3, h4, h5, h6) {
color: #a8d8f0;
}
/* Prose links — use primary teal */
.docs-content a {
color: var(--color-primary-600, #1DCAD4);
text-decoration-color: var(--color-primary-300, #99e8ed);
}
.docs-content a:hover {
color: var(--color-primary-500, #1DCAD4);
}
/* Blockquote — brand left border */
.docs-content blockquote {
border-left-color: var(--color-primary-400, #1DCAD4);
color: #4a6080;
}
/* Inline code — subtle teal tint */
.docs-content :not(pre) > code {
color: #1B3A6B;
background-color: #e8f6f7;
}
.dark .docs-content :not(pre) > code {
color: #a8d8f0;
background-color: #0d2340;
}
/* Strong / bold — slightly darker navy */
.docs-content strong {
color: #1B3A6B;
font-weight: 700;
}
.dark .docs-content strong {
color: #c8e8f8;
}

View file

@ -0,0 +1,10 @@
---
title: Installation
weight: 2
---
## Installing the Tools
This guide covers installing the software you need to program your Go Education board.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: Introduction
weight: 1
---
## What is Go Education Project?
Go Education Project is an open source & open hardware educational robotics platform designed for students, teachers, and makers worldwide.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: Quick Start
weight: 3
---
## Quick Start
From zero to blinking LED in 5 minutes.
> 📖 Full content coming soon.

View file

@ -0,0 +1,7 @@
---
title: Guides
weight: 40
sidebar:
icon: "hero/book-open"
summary: "Step-by-step project guides from beginner to advanced."
---

View file

@ -0,0 +1,10 @@
---
title: First Project
weight: 1
---
## Your First Project
Build a blinking LED circuit and write your first program — the classic "Hello World" of hardware.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: 3D Printing
weight: 4
---
## 3D Printing
All chassis and structural parts are available as open source STL files.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: Assembly Guide
weight: 2
---
## Assembly Guide
Step-by-step instructions for assembling your Go Education robot.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: Bill of Materials
weight: 1
---
## Bill of Materials
Complete list of components for the Go Education robot kit.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: Electronics
weight: 3
---
## Electronics
Understanding the electronic components in your Go Education kit.
> 📖 Full content coming soon.

View file

@ -0,0 +1,7 @@
---
title: Software
weight: 30
sidebar:
icon: "hero/code-bracket"
summary: "Firmware, APIs, mobile app and web dashboard documentation."
---

View file

@ -0,0 +1,10 @@
---
title: API Reference
weight: 2
---
## API Reference
Complete reference for the Go Education software API.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: Firmware
weight: 1
---
## Firmware
The Go Education board firmware — architecture, building, and flashing.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: Mobile App
weight: 3
---
## Mobile App
Control and monitor your robot from the Go Education mobile app.
> 📖 Full content coming soon.

View file

@ -0,0 +1,10 @@
---
title: Web Dashboard
weight: 4
---
## Web Dashboard
The Go Education web dashboard for classroom management and monitoring.
> 📖 Full content coming soon.

98
deploy.sh Executable file
View file

@ -0,0 +1,98 @@
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# Go Education Project — Deploy to Cloudflare Pages
# Usage: ./deploy.sh [--dry-run]
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
SITE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CF_PROJECT="goeducation-site"
CF_BRANCH="main"
DRY_RUN=false
# ── Parse args ───────────────────────────────────────────────────────────────
for arg in "$@"; do
case $arg in
--dry-run) DRY_RUN=true ;;
*) echo "Unknown argument: $arg"; exit 1 ;;
esac
done
# ── Colors ───────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
info() { echo -e "${CYAN}$*${RESET}"; }
success() { echo -e "${GREEN}$*${RESET}"; }
warn() { echo -e "${YELLOW}$*${RESET}"; }
error() { echo -e "${RED}$*${RESET}"; exit 1; }
step() { echo -e "\n${BOLD}── $* ──────────────────────────────────────${RESET}"; }
# ── Checks ───────────────────────────────────────────────────────────────────
step "Pre-flight checks"
cd "$SITE_DIR"
# Node via nvm
if command -v nvm &>/dev/null || [ -s "$HOME/.nvm/nvm.sh" ]; then
source "$HOME/.nvm/nvm.sh"
nvm use 20 --silent
success "Node $(node --version)"
else
error "nvm not found. Install it or ensure Node 20 is in PATH."
fi
# Local node_modules/.bin takes priority — wrangler, pagefind, tailwindcss come from here
export PATH="$SITE_DIR/node_modules/.bin:$PATH"
# Install deps first if node_modules is missing (needed for tool checks below)
if [ ! -d "$SITE_DIR/node_modules" ]; then
info "node_modules not found — running npm ci..."
npm ci
fi
# Check required tools
command -v hugo &>/dev/null || error "hugo not found."
command -v wrangler &>/dev/null || error "wrangler not found. Run: npm install"
command -v pagefind &>/dev/null || error "pagefind not found. Run: npm install"
command -v tailwindcss &>/dev/null || error "tailwindcss not found. Run: npm install"
info "Hugo: $(hugo version | head -1 | cut -d' ' -f2)"
info "Wrangler: $(wrangler --version 2>&1 | head -1)"
info "Pagefind: $(pagefind --version 2>&1 | head -1)"
$DRY_RUN && warn "DRY RUN — build will run but upload will be skipped."
# ── npm deps (already handled above if missing) ───────────────────────────────
step "npm dependencies"
success "node_modules present (wrangler $(wrangler --version 2>&1 | head -1))"
# ── Hugo build ────────────────────────────────────────────────────────────────
step "Hugo build"
info "Building site..."
rm -rf "$SITE_DIR/public"
hugo --minify --environment production
success "Hugo build complete ($(find public -name '*.html' | wc -l | tr -d ' ') HTML pages)"
# ── Pagefind — search index ───────────────────────────────────────────────────
step "Pagefind search index"
info "Indexing content for search..."
pagefind --site public
success "Search index built"
# ── Deploy ────────────────────────────────────────────────────────────────────
step "Deploy → Cloudflare Pages"
if $DRY_RUN; then
warn "Dry run: skipping upload."
warn "Would deploy: $(du -sh public | cut -f1) to project '$CF_PROJECT' (branch: $CF_BRANCH)"
else
info "Uploading to Cloudflare Pages..."
wrangler pages deploy public \
--project-name "$CF_PROJECT" \
--branch "$CF_BRANCH"
echo ""
success "Deploy complete! → https://${CF_PROJECT}.pages.dev"
fi

View file

@ -0,0 +1,157 @@
{{- $context := .context -}}
{{- $no_sidebar := ne .no_sidebar false -}}
{{- $pad_sidebar := true -}}
{{- $sidebar_dynamic_class := cond $no_sidebar (cond $pad_sidebar "lg:hidden xl:block" "lg:hidden") "lg:sticky" -}}
{{- $root_section := cond (eq site.Home.Type "docs") site.Home $context.FirstSection -}}
{{- $page_url := $context.RelPermalink -}}
{{/* Only replace explicit mobile menu links with automated links for Docs pages */}}
{{ if not $no_sidebar }}
<div class="hb-sidebar-mobile-menu fixed inset-0 z-10 bg-white dark:bg-black/80 hidden"></div>
{{ end }}
<aside class="hb-sidebar-container max-lg:[transform:translate3d(0,-100%,0)] {{ $sidebar_dynamic_class }}">
<div class="px-4 pt-4 lg:hidden">
</div>
<div class="hb-scrollbar lg:h-[calc(100vh-var(--navbar-height))]">
<ul class="flex flex-col gap-1 lg:hidden">
{{ template "menu-links" (dict "context" site.Home "pageURL" $page_url "page" $context "toc" true) -}}
{{ template "custom-menu-links" }}
</ul>
{{- if $no_sidebar -}}
<div class="max-xl:hidden h-0 w-64 shrink-0"></div>
{{- else -}}
<ul class="flex flex-col gap-1 max-lg:hidden">
{{ template "menu-links" (dict "context" $root_section "page" $context "pageURL" $page_url) }}
{{ template "custom-menu-links" }}
</ul>
{{ end -}}
</div>
</aside>
{{- define "menu-links" -}}
{{ template "link-tree" (dict "context" .context "level" 0 "page" .page "pageURL" .pageURL "toc" (.toc | default false)) }}
{{- end -}}
{{- define "link-tree" -}}
{{- if ge .level 4 -}}
{{- return -}}
{{- end -}}
{{- $context := .context -}}
{{- $page := .page -}}
{{- $page_url := .page.RelPermalink -}}
{{- $level := .level -}}
{{- $toc := .toc | default false -}}
{{- with $items := union .context.RegularPages .context.Sections -}}
{{- $items = where $items "Params.sidebar.hidden" "!=" true -}}
{{- if eq $level 0 -}}
{{/* ── Level 0: section group headers with icon ─────────────── */}}
{{- range $items.ByWeight -}}
{{- $active := eq $page_url .RelPermalink -}}
{{- $is_expanded := or (.Params.sidebar.open) (.IsAncestor $page) $active | default false -}}
{{- $icon := .Params.sidebar.icon | default "" -}}
<li class="{{ if $is_expanded }}open{{ end }}">
{{/* Section header — styled like the image: icon + uppercase label */}}
<div class="flex items-center gap-2 mt-6 mb-1 px-2 py-1 first:mt-2">
{{- if $icon -}}
<span class="text-primary-500 dark:text-primary-400 flex-shrink-0">
{{ partial "functions/get_icon" (dict "name" $icon "attributes" "class=\"h-4 w-4\"") }}
</span>
{{- end -}}
<span class="text-xs font-bold uppercase tracking-widest text-gray-500 dark:text-gray-400 select-none">
{{- .LinkTitle -}}
</span>
</div>
{{- if and $toc $active -}}
{{- template "mobile-toc" dict "page" . -}}
{{- end -}}
{{- template "link-tree" dict "context" . "page" $page "pageURL" $page_url "level" (add $level 1) "toc" $toc -}}
</li>
{{- end -}}
{{- else -}}
{{/* ── Level 1+: regular indented links ─────────────────────── */}}
<div class="ltr:pr-0 overflow-hidden">
<ul class="hb-sidebar-list">
{{- range $items.ByWeight -}}
{{- $active := eq $page_url .RelPermalink -}}
{{- $is_expanded := or (.Params.sidebar.open) (.IsAncestor $page) $active | default false -}}
{{- $title := .LinkTitle | default .File.BaseFileName -}}
<li class="flex flex-col {{ if $is_expanded }}open{{ end }}">
{{- template "custom-menu-link" dict "context" . "active" $active "title" $title "link" .RelPermalink -}}
{{- if and $toc $active -}}
{{ template "mobile-toc" dict "page" . }}
{{- end -}}
{{ template "link-tree" dict "context" . "page" $page "pageURL" $page_url "level" (add $level 1) "toc" $toc }}
</li>
{{- end -}}
</ul>
</div>
{{- end -}}
{{- end -}}
{{- end -}}
{{- define "mobile-toc" -}}
{{ $page := .page }}
{{ with $page.Fragments.Headings }}
<ul class="hb-sidebar-mobile-toc">
{{- range . -}}
{{- with .Headings -}}
{{- range . -}}
<li>
<a href="#{{ anchorize .ID }}" class="hb-docs-link">
{{- .Title -}}
</a>
</li>
{{- end -}}
{{- end -}}
{{- end -}}
</ul>
{{ end }}
{{- end -}}
{{- define "custom-menu-links" -}}
{{- range site.Menus.sidebar -}}
{{- $name := .Name -}}
{{ if eq .Params.type "separator" }}
<li class="[word-break:break-word] mt-5 mb-2 px-2 py-1.5 text-sm font-semibold text-gray-900 first:mt-0 dark:text-gray-100 cursor-default">
<span>{{ $name }}</span>
</li>
{{ else }}
<li>{{ template "custom-menu-link" dict "active" false "title" $name "link" (.URL | relLangURL) }}</li>
{{ end }}
{{- end -}}
{{- end -}}
{{- define "custom-menu-link" -}}
{{- $is_external := strings.HasPrefix .link "http" -}}
<a
class="hb-sidebar-custom-link
{{- if .active }}
sidebar-active-item bg-primary-100 font-semibold text-primary-800 dark:bg-primary-300 dark:text-primary-900
{{- else }}
text-gray-500 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-primary-800 dark:hover:text-gray-50
{{- end -}}"
href="{{ .link }}"
{{ if $is_external }}target="_blank" rel="noreferer"{{ end }}
>
{{- .title -}}
{{- with .context -}}
{{- if or .RegularPages .Sections -}}
<span data-hb-sidebar-toggle>
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-[18px] min-w-[18px] rounded-sm p-0.5 hover:bg-gray-800/5 dark:hover:bg-gray-100/5">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" class="origin-center transition-transform rtl:-rotate-180"></path>
</svg>
</span>
{{- end -}}
{{- end -}}
</a>
{{- end -}}

View file

@ -0,0 +1,28 @@
<div class="flex w-full">
{{ partial "components/sidebar.html" (dict "context" . "no_sidebar" false) }}
{{ partial "components/toc.html" . }}
<article class="flex w-full min-w-0 min-h-[calc(100vh-var(--navbar-height))] justify-center break-words pb-8 pr-[calc(env(safe-area-inset-right)-1.5rem)]">
<main class="prose prose-slate lg:prose-xl dark:prose-invert w-full min-w-0 px-6 pt-4 md:px-12 docs-content">
{{ if (.Params.show_breadcrumb | default true) }}
<div class="mb-1">
{{ partial "components/breadcrumb.html" . }}
</div>
{{ end }}
<div class="content" data-pagefind-body>
<h1 data-pagefind-meta="title">{{ .Title }}</h1>
{{ .Content }}
<span data-pagefind-filter="type" style="display:none;">docs</span>
{{ with .Params.categories }}
<span data-pagefind-filter="category" style="display:none;">{{ index . 0 }}</span>
{{ end }}
</div>
{{ partial "components/last-edited.html" . }}
{{ .Scratch.Set "invert_pager" true }}
{{ partial "components/next-in-series.html" . }}
{{ partial "comments.html" . }}
</main>
</article>
</div>

View file

@ -0,0 +1,138 @@
{{ $type := (lower .type) | default "note" }}
{{ $content := .content }}
{{ $title := .title }}
{{ if or (not $title) (eq $title "") }}
{{ $i18n_key := printf "callout_%s" $type }}
{{ $title = or (i18n $i18n_key) (title $type) }}
{{ end }}
{{/* Brand-aware color mappings — info/note types use primary teal, others unchanged */}}
{{ $alertConfigs := dict
"note" (dict
"icon" "pencil"
"class" "bg-primary-50 dark:bg-primary-950"
"textClass" "text-primary-700 dark:text-primary-300"
"borderClass" "border-primary-400"
)
"abstract" (dict
"icon" "clipboard-document-list"
"class" "bg-primary-50 dark:bg-primary-950"
"textClass" "text-primary-700 dark:text-primary-300"
"borderClass" "border-primary-400"
)
"summary" (dict
"icon" "clipboard-document-list"
"class" "bg-primary-50 dark:bg-primary-950"
"textClass" "text-primary-700 dark:text-primary-300"
"borderClass" "border-primary-400"
)
"info" (dict
"icon" "information-circle"
"class" "bg-primary-50 dark:bg-primary-950"
"textClass" "text-primary-700 dark:text-primary-300"
"borderClass" "border-primary-400"
)
"todo" (dict
"icon" "check-circle"
"class" "bg-primary-50 dark:bg-primary-950"
"textClass" "text-primary-700 dark:text-primary-300"
"borderClass" "border-primary-400"
)
"tip" (dict
"icon" "light-bulb"
"class" "bg-emerald-100 dark:bg-emerald-900"
"textClass" "text-emerald-600 dark:text-emerald-300"
"borderClass" "border-emerald-500"
)
"success" (dict
"icon" "check-circle"
"class" "bg-green-100 dark:bg-green-900"
"textClass" "text-green-600 dark:text-green-300"
"borderClass" "border-green-500"
)
"question" (dict
"icon" "question-mark-circle"
"class" "bg-yellow-100 dark:bg-yellow-900"
"textClass" "text-yellow-700 dark:text-yellow-300"
"borderClass" "border-yellow-500"
)
"warning" (dict
"icon" "exclamation-triangle"
"class" "bg-orange-100 dark:bg-orange-900"
"textClass" "text-orange-600 dark:text-orange-300"
"borderClass" "border-orange-500"
)
"failure" (dict
"icon" "x-circle"
"class" "bg-red-100 dark:bg-red-900"
"textClass" "text-red-600 dark:text-red-300"
"borderClass" "border-red-500"
)
"danger" (dict
"icon" "exclamation-triangle"
"class" "bg-red-100 dark:bg-red-900"
"textClass" "text-red-600 dark:text-red-300"
"borderClass" "border-red-500"
)
"bug" (dict
"icon" "bug-ant"
"class" "bg-red-100 dark:bg-red-900"
"textClass" "text-red-600 dark:text-red-300"
"borderClass" "border-red-500"
)
"example" (dict
"icon" "beaker"
"class" "bg-purple-100 dark:bg-purple-900"
"textClass" "text-purple-600 dark:text-purple-300"
"borderClass" "border-purple-500"
)
"quote" (dict
"icon" "chat-bubble-left-right"
"class" "bg-gray-100 dark:bg-gray-800"
"textClass" "text-gray-600 dark:text-gray-300"
"borderClass" "border-gray-500"
)
"important" (dict
"icon" "exclamation-circle"
"class" "bg-purple-100 dark:bg-purple-900"
"textClass" "text-purple-600 dark:text-purple-300"
"borderClass" "border-purple-500"
)
"caution" (dict
"icon" "exclamation-triangle"
"class" "bg-red-100 dark:bg-red-900"
"textClass" "text-red-600 dark:text-red-300"
"borderClass" "border-red-500"
)
}}
{{ $config := index $alertConfigs $type }}
{{ $icon := $type }}
{{ $class := "bg-primary-50 dark:bg-primary-950" }}
{{ $textClass := "text-primary-700 dark:text-primary-300" }}
{{ $borderClass := "border-primary-400" }}
{{ if $config }}
{{ $icon = $config.icon }}
{{ $class = $config.class }}
{{ $textClass = $config.textClass }}
{{ $borderClass = $config.borderClass }}
{{ end }}
<div class="callout flex px-4 py-3 mb-6 rounded-md border-l-4 {{ $class }} {{ $borderClass }}"
data-callout="{{ $type }}"
data-callout-metadata="">
<span class="callout-icon pr-3 pt-1 {{ $textClass }}">
{{ partial "functions/get_icon" (dict "name" $icon "attributes" "height=\"24\"") }}
</span>
<div class="callout-content dark:text-neutral-300">
{{- with $title -}}
<div class="callout-title font-semibold mb-1 {{ $textClass }}">
{{- . -}}
</div>
{{- end -}}
<div class="callout-body {{ $textClass }}">
{{- $content -}}
</div>
</div>
</div>