diff --git a/admin/docs/faq.md b/admin/docs/faq.md new file mode 100644 index 0000000..4e5d8a1 --- /dev/null +++ b/admin/docs/faq.md @@ -0,0 +1,195 @@ +# Frequently Asked Questions + +## General Questions + +### What is N.O.M.A.D.? +N.O.M.A.D. (Node for Offline Media, Archives, and Data) is a personal server that gives you access to knowledge, education, and AI assistance without requiring an internet connection. It runs on your own hardware, keeping your data private and accessible anytime. + +### Do I need internet to use N.O.M.A.D.? +No — that's the whole point. Once your content is downloaded, everything works offline. You only need internet to: +- Download new content +- Update the software +- Sync the latest versions of Wikipedia, maps, etc. + +### What hardware do I need? +N.O.M.A.D. is designed for capable hardware, especially if you want to use the AI features. Recommended: +- Modern multi-core CPU +- 16GB+ RAM (32GB+ for best AI performance) +- SSD storage (size depends on content — 500GB minimum, 2TB+ recommended) +- GPU recommended for faster AI responses + +### How much storage do I need? +It depends on what you download: +- Full Wikipedia: ~95GB +- Khan Academy courses: ~50GB +- Medical references: ~500MB +- US state maps: ~2-3GB each +- AI models: 10-40GB depending on model + +Start with essentials and add more as needed. + +--- + +## Content Questions + +### How do I add more Wikipedia content? +1. Go to **Settings** (hamburger menu → Settings) +2. Click **ZIM Manager** +3. Browse available content +4. Click Download on items you want + +### How do I add more educational courses? +1. Open **Kolibri** +2. Sign in as an admin +3. Go to **Device → Channels** +4. Browse and import available channels + +### How current is the content? +Content is as current as when it was last downloaded. Wikipedia snapshots are typically updated monthly. Check the file names or descriptions for dates. + +### Can I add my own files? +Currently, N.O.M.A.D. uses standard content formats (ZIM files for Kiwix, Kolibri channels for education). Custom content support may be added in future versions. + +--- + +## Troubleshooting + +### A feature isn't loading or shows a blank page + +**Try these steps:** +1. Wait 30 seconds — some features take time to start +2. Refresh the page (Ctrl+R or Cmd+R) +3. Go back to the Command Center and try again +4. Check Settings → System to see if the service is running +5. Try restarting the service (Stop, then Start in Apps manager) + +### Maps show a gray/blank area + +The Maps feature requires downloaded map data. If you see a blank area: +1. Go to **Settings → Maps Manager** +2. Download map regions for your area +3. Wait for downloads to complete +4. Return to Maps and refresh + +### AI responses are slow + +Local AI requires significant computing power. To improve speed: +- Close other applications on the server +- Ensure adequate cooling (overheating causes throttling) +- Consider using a smaller/faster AI model if available +- Add a GPU if your hardware supports it + +### "Service unavailable" or connection errors + +The service might still be starting up. Wait 1-2 minutes and try again. + +If the problem persists: +1. Go to **Settings → Apps** +2. Find the problematic service +3. Click **Restart** +4. Wait 30 seconds, then try again + +### Downloads are stuck or failing + +1. Check your internet connection +2. Go to **Settings** and check available storage +3. If storage is full, delete unused content +4. Cancel the stuck download and try again + +### The server won't start + +If you can't access the Command Center at all: +1. Verify the server hardware is powered on +2. Check network connectivity +3. Try accessing directly via the server's IP address +4. Check server logs if you have console access + +### I forgot my Kolibri password + +Kolibri passwords are managed separately: +1. If you're an admin, you can reset user passwords in Kolibri's user management +2. If you forgot the admin password, you may need to reset it via command line (contact your administrator) + +--- + +## Updates and Maintenance + +### How do I update N.O.M.A.D.? +1. Go to **Settings → Check for Updates** +2. If an update is available, click to install +3. The system will download updates and restart automatically +4. This typically takes 2-5 minutes + +### Should I update regularly? +Yes, while you have internet access. Updates include: +- Bug fixes +- New features +- Security improvements +- Performance enhancements + +### How do I update content (Wikipedia, etc.)? +Content updates are separate from software updates: +1. Go to **Settings → ZIM Manager** +2. Check for newer versions of your installed content +3. Download updated versions as needed + +Tip: New Wikipedia snapshots are released approximately monthly. + +### What happens if an update fails? +The system is designed to recover gracefully. If an update fails: +1. The previous version should continue working +2. Try the update again later +3. Check Settings → System for error messages + +### Command-Line Maintenance + +For advanced troubleshooting or when you can't access the web interface, N.O.M.A.D. includes helper scripts in `/opt/project-nomad`: + +**Start all services:** +```bash +sudo bash /opt/project-nomad/start_nomad.sh +``` + +**Stop all services:** +```bash +sudo bash /opt/project-nomad/stop_nomad.sh +``` + +**Update Command Center:** +```bash +sudo bash /opt/project-nomad/update_nomad.sh +``` +*Note: This updates the Command Center only, not individual apps. Update apps through the web interface.* + +**Uninstall N.O.M.A.D.:** +```bash +curl -fsSL https://raw.githubusercontent.com/Crosstalk-Solutions/project-nomad/refs/heads/master/install/uninstall_nomad.sh -o uninstall_nomad.sh +sudo bash uninstall_nomad.sh +``` +*Warning: This cannot be undone. All data will be deleted.* + +--- + +## Privacy and Security + +### Is my data private? +Yes. N.O.M.A.D. runs entirely on your hardware. Your searches, AI conversations, and usage data never leave your server. + +### Can others access my server? +By default, N.O.M.A.D. is accessible on your local network. Anyone on the same network can access it. For public networks, consider additional security measures. + +### Does the AI send data anywhere? +No. The AI runs completely locally. Your conversations are not sent to any external service. + +--- + +## Getting More Help + +### The AI can help +Try asking Open WebUI for help. The local AI can answer questions about many topics, including technical troubleshooting. + +### Check the documentation +You're in the docs now. Use the menu to find specific topics. + +### Release Notes +See what's changed in each version: **[Release Notes](/docs/release-notes)** diff --git a/admin/docs/getting-started.md b/admin/docs/getting-started.md new file mode 100644 index 0000000..6ad7245 --- /dev/null +++ b/admin/docs/getting-started.md @@ -0,0 +1,238 @@ +# Getting Started with N.O.M.A.D. + +This guide will help you install and set up your N.O.M.A.D. server. + +--- + +## Installation + +### System Requirements + +N.O.M.A.D. runs on any **Debian-based Linux** system (Ubuntu recommended). The installation is terminal-based, and everything is accessed through a web browser — no desktop environment needed. + +**Minimum Specs** (Command Center only): +- 2 GHz dual-core processor +- 4 GB RAM +- 5 GB free storage +- Internet connection (for initial install) + +**Recommended Specs** (with AI features): +- AMD Ryzen 7 / Intel Core i7 or better +- 32 GB RAM +- NVIDIA RTX 3060 or better (more VRAM = larger AI models) +- 250 GB+ free storage (SSD preferred) + +The Command Center itself is lightweight — your hardware requirements depend on which tools and content you choose to install. + +### Install N.O.M.A.D. + +Open a terminal and run these two commands: + +```bash +curl -fsSL https://raw.githubusercontent.com/Crosstalk-Solutions/project-nomad/refs/heads/master/install/install_nomad.sh -o install_nomad.sh +``` + +```bash +sudo bash install_nomad.sh +``` + +That's it. Once the install finishes, open a browser and go to: + +- **Same machine:** `http://localhost:8080` +- **Other devices on your network:** `http://YOUR_SERVER_IP:8080` + +### About Internet & Privacy + +N.O.M.A.D. is designed for offline use. Internet is only needed: +- During initial installation +- When downloading additional content + +There is **zero telemetry** — your data stays on your device. + +### About Security + +N.O.M.A.D. has no built-in authentication — it's designed to be open and accessible. If you expose it on a network, consider using firewall rules to control which ports are accessible. + +--- + +## After Installation + +### 1. Run the Easy Setup Wizard + +If this is your first time using N.O.M.A.D., the Easy Setup wizard will help you: +- Choose which apps to enable +- Download map regions for your area +- Select knowledge collections (Wikipedia, medical references, etc.) + +**[Launch Easy Setup →](/easy-setup)** + +The wizard walks you through four simple steps: +1. **Apps** — Choose additional tools like CyberChef or FlatNotes +2. **Maps** — Select geographic regions for offline maps +3. **ZIM Files** — Choose reference collections (Wikipedia, medical, survival guides) +4. **Review** — Confirm your selections and start downloading + +### 2. Wait for Downloads to Complete + +Depending on what you selected, downloads may take a while. You can: +- Monitor progress in the Settings area +- Continue using features that are already installed +- Leave your server running overnight for large downloads + +### 3. Explore Your Content + +Once downloads complete, you're ready to go. Your content works offline whenever you need it. + +--- + +## Understanding Your Tools + +### Kiwix — Your Offline Library + +Kiwix stores compressed versions of websites and references that work without internet. + +**What's included:** +- Full Wikipedia (millions of articles) +- Medical references and first aid guides +- How-to guides and survival information +- Classic books from Project Gutenberg + +**How to use it:** +1. Click **Kiwix** from the Command Center +2. Choose a collection (like Wikipedia) +3. Search or browse just like the regular website + +**[Open Kiwix →](/kiwix)** + +--- + +### Kolibri — Offline Education + +Kolibri provides complete educational courses that work offline. + +**What's included:** +- Khan Academy video courses +- Math, science, reading, and more +- Progress tracking for learners +- Works for all ages + +**How to use it:** +1. Click **Kolibri** from the Command Center +2. Sign in or create a learner account +3. Browse courses and start learning + +**Tip:** Kolibri supports multiple users. Create accounts for each family member to track individual progress. + +**[Open Kolibri →](/kolibri)** + +--- + +### Open WebUI — Your AI Assistant + +Chat with a local AI that runs entirely on your server — no internet needed. + +**What can it do:** +- Answer questions on any topic +- Explain complex concepts simply +- Help with writing and editing +- Brainstorm ideas +- Assist with problem-solving + +**How to use it:** +1. Click **Open WebUI** from the Command Center +2. Type your question or request +3. The AI responds in conversational style + +**Tip:** Be specific in your questions. Instead of "tell me about plants," try "what vegetables grow well in shade?" + +**[Open AI Chat →](/openwebui)** + +--- + +### Maps — Offline Navigation + +View maps without internet. Download the regions you need before going offline. + +**How to use it:** +1. Click **Maps** from the Command Center +2. Navigate by dragging and zooming +3. Search for locations using the search bar + +**To add more map regions:** +1. Go to **Settings → Maps Manager** +2. Select the regions you need +3. Click Download + +**Tip:** Download maps for areas you travel to frequently, plus neighboring regions just in case. + +**[Open Maps →](/maps)** + +--- + +## Managing Your Server + +### Adding More Content + +As your needs change, you can add more content anytime: + +- **More apps:** Settings → Apps +- **More references:** Settings → ZIM Manager +- **More map regions:** Settings → Maps Manager +- **More educational content:** Through Kolibri's built-in content browser + +### Keeping Things Updated + +While you have internet, periodically check for updates: + +1. Go to **Settings → Check for Updates** +2. If updates are available, click to install +3. Wait for the update to complete (your server will restart) + +Content updates (Wikipedia, maps, etc.) can be managed separately from software updates. + +### Monitoring System Health + +Check on your server anytime: + +1. Go to **Settings → System** +2. View CPU, memory, and storage usage +3. Check system uptime and status + +--- + +## Tips for Best Results + +### Before Going Offline + +- **Update everything** — Run software and content updates +- **Download what you need** — Maps, references, educational content +- **Test it** — Make sure features work while you still have internet to troubleshoot + +### Storage Management + +Your server has limited storage. Prioritize: +- Content you'll actually use +- Critical references (medical, survival) +- Maps for your region +- Educational content matching your needs + +Check storage usage in **Settings → System**. + +### Getting Help + +- **In-app docs:** You're reading them now +- **AI assistant:** Ask Open WebUI for help with almost anything +- **Release notes:** See what's new in each version + +--- + +## Next Steps + +You're ready to use N.O.M.A.D. Here are some things to try: + +1. **Look something up** — Search for a topic in Kiwix +2. **Learn something** — Start a Khan Academy course in Kolibri +3. **Ask a question** — Chat with the AI in Open WebUI +4. **Explore maps** — Find your neighborhood in the Maps viewer + +Enjoy your offline knowledge server! diff --git a/admin/docs/home.md b/admin/docs/home.md index 1516eac..cc83b86 100644 --- a/admin/docs/home.md +++ b/admin/docs/home.md @@ -1,71 +1,67 @@ -# Lorem Ipsum Markdown Showcase +# Welcome to Project N.O.M.A.D. + +Your personal offline knowledge server is ready to use. + +## What is N.O.M.A.D.? + +**N.O.M.A.D.** stands for **Node for Offline Media, Archives, and Data**. It's your personal server for accessing knowledge, education, and AI assistance — even when you have no internet connection. + +Think of it as having Wikipedia, Khan Academy, an AI assistant, and offline maps all in one place, running on hardware you control. + +## What Can You Do? + +### Browse Offline Knowledge +Access millions of Wikipedia articles, medical references, how-to guides, and ebooks — all stored locally on your server. No internet required. + +**[Open Kiwix →](/kiwix)** + +### Learn Something New +Khan Academy courses covering math, science, economics, and more. Complete with videos and exercises, all available offline. + +**[Open Kolibri →](/kolibri)** + +### Chat with AI +Ask questions, get explanations, brainstorm ideas, or get help with writing. Your local AI assistant works completely offline. + +**[Open AI Chat →](/openwebui)** + +### View Offline Maps +Navigate and explore maps without an internet connection. Download regions you need before going offline. + +**[Open Maps →](/maps)** --- -## Introduction +## Getting Started -This document serves as a comprehensive example of **Markdown's various formatting possibilities**, using the classic *Lorem Ipsum* text as its content. From basic text styling to lists, code blocks, and tables, you'll find a demonstration of common Markdown features here. +**New to N.O.M.A.D.?** Use the Easy Setup wizard to configure your server and download content collections. + +**[Run Easy Setup →](/easy-setup)** + +Or explore the **[Getting Started Guide](/docs/getting-started)** for a walkthrough of all features. --- -## Basic Text Formatting +## Quick Links -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. - -* This text is **bold**. -* This text is *italic*. -* This text is ***bold and italic***. -* This text is ~~struck through~~. -* You can also use `backticks` for `inline code`. +| I want to... | Go here | +|--------------|---------| +| Download more content | [Install Apps](/apps) | +| Add Wikipedia/reference content | [ZIM Manager](/settings/zim-manager) | +| Download map regions | [Maps Manager](/settings/maps-manager) | +| Check for updates | [System Update](/settings/updates) | +| View system status | [Settings](/settings) | --- -## Headers +## Keeping Your Server Updated -Markdown supports up to six levels of headers. +N.O.M.A.D. works best when kept up to date while you have internet access. This ensures you have the latest: +- Software features and bug fixes +- Wikipedia and reference content +- Educational materials +- AI model improvements -# Header 1 -## Header 2 -### Header 3 -#### Header 4 -##### Header 5 -###### Header 6 +When you go offline, you'll have everything you need — the last synced versions of all your content. ---- - -## Lists - -### Unordered List - -* Lorem ipsum dolor sit amet. - * Consectetur adipiscing elit. - * Sed do eiusmod tempor. -* Incididunt ut labore et dolore magna. -* Aliqua ut enim ad minim veniam. - -### Ordered List - -1. Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -2. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. -3. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - ---- - -## Blockquotes - -> "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." -> -> — John Doe, *Lorem Ipsum Anthology* - ---- - -## Code Blocks - -```python -def fibonacci(n): - a, b = 0, 1 - for i in range(n): - print(a, end=" ") - a, b = b, a + b - -fibonacci(10) \ No newline at end of file +**[Check for Updates →](/settings/updates)** diff --git a/admin/docs/use-cases.md b/admin/docs/use-cases.md new file mode 100644 index 0000000..6f69192 --- /dev/null +++ b/admin/docs/use-cases.md @@ -0,0 +1,190 @@ +# What Can You Do With N.O.M.A.D.? + +N.O.M.A.D. is designed to be your information lifeline when internet isn't available. Here's how different people use it. + +--- + +## Emergency Preparedness + +When disasters strike, internet and cell service often go down first. N.O.M.A.D. keeps critical information at your fingertips. + +**What you can do:** +- Look up first aid and emergency medical procedures +- Access survival guides and emergency protocols +- Find information about water purification, food storage, shelter building +- Use offline maps to navigate when GPS services are degraded +- Research plant identification, weather patterns, radio frequencies + +**Recommended content:** +- Medical Library ZIM collection +- Survival/Prepper reference guides +- Maps for your region and evacuation routes +- Wikipedia (searchable for almost any topic) + +--- + +## Homeschooling and Education + +Teach your children anywhere, with or without internet. Complete curriculum available offline. + +**What you can do:** +- Access Khan Academy's full course library (math, science, reading, history) +- Track progress for multiple students +- Supplement with Wikipedia for research projects +- Use the AI as a patient tutor for any subject +- Access classic literature through Project Gutenberg + +**Recommended content:** +- Khan Academy courses via Kolibri +- Wikipedia for Schools (curated for younger learners) +- Project Gutenberg (classic books) +- Educational ZIM collections + +**Tip:** Create separate Kolibri accounts for each child to track their individual progress. + +--- + +## Off-Grid Living + +Living away from reliable internet doesn't mean living without information. + +**What you can do:** +- Research DIY projects and repairs +- Look up gardening, animal husbandry, food preservation +- Access medical references for remote healthcare +- Learn new skills through educational videos +- Get AI help with planning and problem-solving + +**Recommended content:** +- How-to and DIY reference collections +- Medical and first aid guides +- Agricultural and homesteading references +- Maps for your rural area +- Practical skills courses in Kolibri + +--- + +## Remote Work Sites + +Construction sites, research stations, ships, and remote facilities often lack reliable internet. + +**What you can do:** +- Access technical references and documentation +- Use AI for writing assistance and analysis +- Look up regulations, standards, and procedures +- Provide educational resources for workers +- Maintain communication records with note-taking apps + +**Recommended content:** +- Industry-specific technical references +- Relevant Wikipedia categories +- Maps of work areas +- Documentation and compliance guides + +--- + +## Travel and Expeditions + +International travel, cruises, camping trips — stay informed anywhere. + +**What you can do:** +- Access maps without expensive roaming data +- Research destinations, history, and culture +- Translate concepts with AI assistance +- Identify plants, animals, and geological features +- Access travel health information + +**Recommended content:** +- Maps for destination countries/regions +- Wikipedia in relevant languages +- Medical/health references +- Cultural and historical content + +--- + +## Privacy-Conscious Users + +Some people simply prefer to keep their searches and questions private. + +**What you can do:** +- Search Wikipedia without being tracked +- Ask AI questions that stay on your own hardware +- Learn about sensitive topics privately +- Keep your intellectual curiosity to yourself + +**How it works:** +- All data stays on your server +- No search history sent to companies +- No AI conversations leave your network +- You control your own information + +--- + +## Medical Reference + +When you can't reach a doctor, having reliable medical information can be critical. + +**What you can access:** +- NHS Medicines A-Z (drug information and interactions) +- Medical Library (field medicine, emergency procedures) +- First aid guides +- Anatomy and physiology references +- Disease and symptom information + +**Important:** Medical references are for information only. They don't replace professional medical care. In emergencies, always seek professional help when possible. + +**Recommended content:** +- Medical Essentials ZIM collection +- NHS Medicines reference +- First aid and emergency medicine guides + +--- + +## Academic Research + +Students and researchers can work without depending on university networks. + +**What you can do:** +- Access Wikipedia's extensive article database +- Use AI for research assistance and summarization +- Work on papers and projects offline +- Cross-reference multiple sources +- Take notes with built-in tools + +**Recommended content:** +- Full Wikipedia +- Academic and educational references +- Subject-specific ZIM collections +- Note-taking apps (FlatNotes) + +--- + +## Setting Up for Your Use Case + +### Step 1: Identify Your Needs +What situations might you face without internet? What information would you need? + +### Step 2: Prioritize Content +Storage is limited. Focus on: +1. Critical safety information (medical, emergency) +2. Content matching your primary use case +3. General reference (Wikipedia) +4. Nice-to-have additions + +### Step 3: Download While You Can +Keep your server updated while you have internet. You never know when you'll need to go offline. + +### Step 4: Practice +Try using N.O.M.A.D. before you need it. Familiarity with the tools makes them more useful in a crisis. + +--- + +## Need Something Specific? + +N.O.M.A.D. content is customizable. If you don't see what you need: + +1. **Check ZIM Remote Explorer** — Thousands of ZIM files are available +2. **Browse Kolibri channels** — Educational content for many subjects +3. **Request features** — Let us know what content would help you + +Your offline server, your content choices. diff --git a/admin/inertia/components/CategoryCard.tsx b/admin/inertia/components/CategoryCard.tsx new file mode 100644 index 0000000..2f70c33 --- /dev/null +++ b/admin/inertia/components/CategoryCard.tsx @@ -0,0 +1,88 @@ +import { formatBytes } from '~/lib/util' +import DynamicIcon, { DynamicIconName } from './DynamicIcon' +import { CuratedCategory, CategoryTier } from '../../types/downloads' +import classNames from 'classnames' +import { IconChevronRight, IconCircleCheck } from '@tabler/icons-react' + +export interface CategoryCardProps { + category: CuratedCategory + selectedTier?: CategoryTier | null + onClick?: (category: CuratedCategory) => void +} + +const CategoryCard: React.FC = ({ category, selectedTier, onClick }) => { + // Calculate total size range across all tiers + const getTierTotalSize = (tier: CategoryTier, allTiers: CategoryTier[]): number => { + let total = tier.resources.reduce((acc, r) => acc + r.size_mb * 1024 * 1024, 0) + + // Add included tier sizes recursively + if (tier.includesTier) { + const includedTier = allTiers.find(t => t.slug === tier.includesTier) + if (includedTier) { + total += getTierTotalSize(includedTier, allTiers) + } + } + + return total + } + + const minSize = getTierTotalSize(category.tiers[0], category.tiers) + const maxSize = getTierTotalSize(category.tiers[category.tiers.length - 1], category.tiers) + + return ( +
onClick?.(category)} + > +
+
+
+ +

{category.name}

+
+ {selectedTier ? ( +
+ + {selectedTier.name} +
+ ) : ( + + )} +
+
+ +

{category.description}

+ +
+

+ {category.tiers.length} tiers available +

+
+ {category.tiers.map((tier) => ( + + {tier.name} + {tier.recommended && ' *'} + + ))} +
+

+ Size: {formatBytes(minSize, 1)} - {formatBytes(maxSize, 1)} +

+
+
+ ) +} + +export default CategoryCard diff --git a/admin/inertia/components/StorageProjectionBar.tsx b/admin/inertia/components/StorageProjectionBar.tsx new file mode 100644 index 0000000..36bb214 --- /dev/null +++ b/admin/inertia/components/StorageProjectionBar.tsx @@ -0,0 +1,122 @@ +import classNames from '~/lib/classNames' +import { formatBytes } from '~/lib/util' +import { IconAlertTriangle, IconServer } from '@tabler/icons-react' + +interface StorageProjectionBarProps { + totalSize: number // Total disk size in bytes + currentUsed: number // Currently used space in bytes + projectedAddition: number // Additional space that will be used in bytes +} + +export default function StorageProjectionBar({ + totalSize, + currentUsed, + projectedAddition, +}: StorageProjectionBarProps) { + const projectedTotal = currentUsed + projectedAddition + const currentPercent = (currentUsed / totalSize) * 100 + const projectedPercent = (projectedAddition / totalSize) * 100 + const projectedTotalPercent = (projectedTotal / totalSize) * 100 + const remainingAfter = totalSize - projectedTotal + const willExceed = projectedTotal > totalSize + + // Determine warning level based on projected total + const getProjectedColor = () => { + if (willExceed) return 'bg-desert-red' + if (projectedTotalPercent >= 90) return 'bg-desert-orange' + if (projectedTotalPercent >= 75) return 'bg-desert-tan' + return 'bg-desert-olive' + } + + const getProjectedGlow = () => { + if (willExceed) return 'shadow-desert-red/50' + if (projectedTotalPercent >= 90) return 'shadow-desert-orange/50' + if (projectedTotalPercent >= 75) return 'shadow-desert-tan/50' + return 'shadow-desert-olive/50' + } + + return ( +
+
+
+ + Storage +
+
+ {formatBytes(projectedTotal, 1)} / {formatBytes(totalSize, 1)} + {projectedAddition > 0 && ( + + (+{formatBytes(projectedAddition, 1)} selected) + + )} +
+
+ + {/* Progress bar */} +
+
+ {/* Current usage - darker/subdued */} +
+ {/* Projected addition - highlighted */} + {projectedAddition > 0 && ( +
+ )} +
+ + {/* Percentage label */} +
15 + ? 'left-3 text-desert-white drop-shadow-md' + : 'right-3 text-desert-green' + )} + > + {Math.round(projectedTotalPercent)}% +
+
+ + {/* Legend and warnings */} +
+
+
+
+ Current ({formatBytes(currentUsed, 1)}) +
+ {projectedAddition > 0 && ( +
+
+ + Selected (+{formatBytes(projectedAddition, 1)}) + +
+ )} +
+ + {willExceed ? ( +
+ + Exceeds available space by {formatBytes(projectedTotal - totalSize, 1)} +
+ ) : ( +
+ {formatBytes(remainingAfter, 1)} will remain free +
+ )} +
+
+ ) +} diff --git a/admin/inertia/components/TierSelectionModal.tsx b/admin/inertia/components/TierSelectionModal.tsx new file mode 100644 index 0000000..9603627 --- /dev/null +++ b/admin/inertia/components/TierSelectionModal.tsx @@ -0,0 +1,205 @@ +import { Fragment } from 'react' +import { Dialog, Transition } from '@headlessui/react' +import { IconX, IconCheck, IconInfoCircle } from '@tabler/icons-react' +import { CuratedCategory, CategoryTier, CategoryResource } from '../../types/downloads' +import { formatBytes } from '~/lib/util' +import classNames from 'classnames' +import DynamicIcon, { DynamicIconName } from './DynamicIcon' + +interface TierSelectionModalProps { + isOpen: boolean + onClose: () => void + category: CuratedCategory | null + selectedTierSlug?: string | null + onSelectTier: (category: CuratedCategory, tier: CategoryTier) => void +} + +const TierSelectionModal: React.FC = ({ + isOpen, + onClose, + category, + selectedTierSlug, + onSelectTier, +}) => { + if (!category) return null + + // Get all resources for a tier (including inherited resources) + const getAllResourcesForTier = (tier: CategoryTier): CategoryResource[] => { + const resources = [...tier.resources] + + if (tier.includesTier) { + const includedTier = category.tiers.find(t => t.slug === tier.includesTier) + if (includedTier) { + resources.unshift(...getAllResourcesForTier(includedTier)) + } + } + + return resources + } + + const getTierTotalSize = (tier: CategoryTier): number => { + return getAllResourcesForTier(tier).reduce((acc, r) => acc + r.size_mb * 1024 * 1024, 0) + } + + return ( + + + +
+ + +
+
+ + + {/* Header */} +
+
+
+ +
+ + {category.name} + +

{category.description}

+
+
+ +
+
+ + {/* Content */} +
+

+ Select a tier based on your storage capacity and needs. Higher tiers include all content from lower tiers. +

+ +
+ {category.tiers.map((tier, index) => { + const allResources = getAllResourcesForTier(tier) + const totalSize = getTierTotalSize(tier) + const isSelected = selectedTierSlug === tier.slug + + return ( +
onSelectTier(category, tier)} + className={classNames( + 'border-2 rounded-lg p-5 cursor-pointer transition-all', + isSelected + ? 'border-desert-green bg-desert-green/5 shadow-md' + : 'border-gray-200 hover:border-desert-green/50 hover:shadow-sm', + tier.recommended && !isSelected && 'border-lime-500/50' + )} + > +
+
+
+

+ {tier.name} +

+ {tier.recommended && ( + + Recommended + + )} + {tier.includesTier && ( + + (includes {category.tiers.find(t => t.slug === tier.includesTier)?.name}) + + )} +
+

{tier.description}

+ + {/* Resources preview */} +
+

+ {allResources.length} resources included: +

+
+ {allResources.map((resource, idx) => ( +
+ +
+ {resource.title} + + ({formatBytes(resource.size_mb * 1024 * 1024, 0)}) + +
+
+ ))} +
+
+
+ +
+
+ {formatBytes(totalSize, 1)} +
+
+ {isSelected && } +
+
+
+
+ ) + })} +
+ + {/* Info note */} +
+ +

+ You can change your selection at any time. Downloads will begin when you complete the setup wizard. +

+
+
+ + {/* Footer */} +
+ +
+
+
+
+
+
+
+ ) +} + +export default TierSelectionModal diff --git a/admin/inertia/pages/easy-setup/index.tsx b/admin/inertia/pages/easy-setup/index.tsx index 54d192b..d25ea90 100644 --- a/admin/inertia/pages/easy-setup/index.tsx +++ b/admin/inertia/pages/easy-setup/index.tsx @@ -1,17 +1,22 @@ import { Head, router } from '@inertiajs/react' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' -import { useEffect, useState } from 'react' +import { useEffect, useState, useMemo } from 'react' import AppLayout from '~/layouts/AppLayout' import StyledButton from '~/components/StyledButton' import api from '~/lib/api' import { ServiceSlim } from '../../../types/services' import CuratedCollectionCard from '~/components/CuratedCollectionCard' +import CategoryCard from '~/components/CategoryCard' +import TierSelectionModal from '~/components/TierSelectionModal' import LoadingSpinner from '~/components/LoadingSpinner' import Alert from '~/components/Alert' import { IconCheck, IconChevronDown, IconChevronUp } from '@tabler/icons-react' +import StorageProjectionBar from '~/components/StorageProjectionBar' import { useNotifications } from '~/context/NotificationContext' import useInternetStatus from '~/hooks/useInternetStatus' +import { useSystemInfo } from '~/hooks/useSystemInfo' import classNames from 'classnames' +import { CuratedCategory, CategoryTier, CategoryResource } from '../../../types/downloads' // Capability definitions - maps user-friendly categories to services interface Capability { @@ -102,6 +107,21 @@ type WizardStep = 1 | 2 | 3 | 4 const CURATED_MAP_COLLECTIONS_KEY = 'curated-map-collections' const CURATED_ZIM_COLLECTIONS_KEY = 'curated-zim-collections' +const CURATED_CATEGORIES_KEY = 'curated-categories' +const CATEGORIES_URL = + 'https://raw.githubusercontent.com/Crosstalk-Solutions/project-nomad/feature/tiered-collections/collections/kiwix-categories.json' + +// Helper to get all resources for a tier (including inherited resources) +const getAllResourcesForTier = (tier: CategoryTier, allTiers: CategoryTier[]): CategoryResource[] => { + const resources = [...tier.resources] + if (tier.includesTier) { + const includedTier = allTiers.find((t) => t.slug === tier.includesTier) + if (includedTier) { + resources.unshift(...getAllResourcesForTier(includedTier, allTiers)) + } + } + return resources +} export default function EasySetupWizard(props: { system: { services: ServiceSlim[] } }) { const [currentStep, setCurrentStep] = useState(1) @@ -111,14 +131,21 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim const [isProcessing, setIsProcessing] = useState(false) const [showAdditionalTools, setShowAdditionalTools] = useState(false) + // Category/tier selection state + const [selectedTiers, setSelectedTiers] = useState>(new Map()) + const [tierModalOpen, setTierModalOpen] = useState(false) + const [activeCategory, setActiveCategory] = useState(null) + const { addNotification } = useNotifications() const { isOnline } = useInternetStatus() const queryClient = useQueryClient() + const { data: systemInfo } = useSystemInfo({ enabled: true }) const anySelectionMade = selectedServices.length > 0 || selectedMapCollections.length > 0 || - selectedZimCollections.length > 0 + selectedZimCollections.length > 0 || + selectedTiers.size > 0 const { data: mapCollections, isLoading: isLoadingMaps } = useQuery({ queryKey: [CURATED_MAP_COLLECTIONS_KEY], @@ -136,6 +163,20 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim const allServices = props.system.services // Services that can still be installed (not already installed) + // Fetch curated categories with tiers + const { data: categories, isLoading: isLoadingCategories } = useQuery({ + queryKey: [CURATED_CATEGORIES_KEY], + queryFn: async () => { + const response = await fetch(CATEGORIES_URL) + if (!response.ok) { + throw new Error('Failed to fetch categories') + } + const data = await response.json() + return data.categories as CuratedCategory[] + }, + refetchOnWindowFocus: false, + }) + const availableServices = props.system.services.filter( (service) => !service.installed && service.installation_status !== 'installing' ) @@ -163,6 +204,85 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim ) } + // Category/tier handlers + const handleCategoryClick = (category: CuratedCategory) => { + if (!isOnline) return + setActiveCategory(category) + setTierModalOpen(true) + } + + const handleTierSelect = (category: CuratedCategory, tier: CategoryTier) => { + setSelectedTiers((prev) => { + const newMap = new Map(prev) + // If same tier is selected, deselect it + if (prev.get(category.slug)?.slug === tier.slug) { + newMap.delete(category.slug) + } else { + newMap.set(category.slug, tier) + } + return newMap + }) + } + + const closeTierModal = () => { + setTierModalOpen(false) + setActiveCategory(null) + } + + // Get all resources from selected tiers for downloading + const getSelectedTierResources = (): CategoryResource[] => { + if (!categories) return [] + const resources: CategoryResource[] = [] + selectedTiers.forEach((tier, categorySlug) => { + const category = categories.find((c) => c.slug === categorySlug) + if (category) { + resources.push(...getAllResourcesForTier(tier, category.tiers)) + } + }) + return resources + } + + // Calculate total projected storage from all selections + const projectedStorageBytes = useMemo(() => { + let totalBytes = 0 + + // Add tier resources + const tierResources = getSelectedTierResources() + totalBytes += tierResources.reduce((sum, r) => sum + r.size_mb * 1024 * 1024, 0) + + // Add map collections + if (mapCollections) { + selectedMapCollections.forEach((slug) => { + const collection = mapCollections.find((c) => c.slug === slug) + if (collection) { + totalBytes += collection.resources.reduce((sum, r) => sum + r.size_mb * 1024 * 1024, 0) + } + }) + } + + // Add ZIM collections + if (zimCollections) { + selectedZimCollections.forEach((slug) => { + const collection = zimCollections.find((c) => c.slug === slug) + if (collection) { + totalBytes += collection.resources.reduce((sum, r) => sum + r.size_mb * 1024 * 1024, 0) + } + }) + } + + return totalBytes + }, [selectedTiers, selectedMapCollections, selectedZimCollections, categories, mapCollections, zimCollections]) + + // Get primary disk/filesystem info for storage projection + // Try disk array first (Linux/production), fall back to fsSize (Windows/dev) + const primaryDisk = systemInfo?.disk?.[0] + const primaryFs = systemInfo?.fsSize?.[0] + const storageInfo = primaryDisk + ? { totalSize: primaryDisk.totalSize, totalUsed: primaryDisk.totalUsed } + : primaryFs + ? { totalSize: primaryFs.size, totalUsed: primaryFs.used } + : null + const canProceedToNextStep = () => { if (!isOnline) return false // Must be online to proceed if (currentStep === 1) return true // Can skip app installation @@ -200,9 +320,12 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim await Promise.all(installPromises) + // Download collections and individual tier resources + const tierResources = getSelectedTierResources() const downloadPromises = [ ...selectedMapCollections.map((slug) => api.downloadMapCollection(slug)), ...selectedZimCollections.map((slug) => api.downloadZimCollection(slug)), + ...tierResources.map((resource) => api.downloadRemoteZimFile(resource.url)), ] await Promise.all(downloadPromises) @@ -263,7 +386,7 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim const steps = [ { number: 1, label: 'Apps' }, { number: 2, label: 'Maps' }, - { number: 3, label: 'ZIM Files' }, + { number: 3, label: 'Content' }, { number: 4, label: 'Review' }, ] @@ -577,44 +700,79 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim const renderStep3 = () => (
-

Choose ZIM Files

+

Choose Content Collections

- Select ZIM file collections for offline knowledge. You can always download more later. + Select content categories for offline knowledge. Click a category to choose your preferred tier based on storage capacity.

- {isLoadingZims ? ( + + {/* Curated Categories with Tiers */} + {isLoadingCategories ? (
- ) : zimCollections && zimCollections.length > 0 ? ( -
- {zimCollections.map((collection) => ( -
- isOnline && !collection.all_downloaded && toggleZimCollection(collection.slug) - } - className={classNames( - 'relative', - selectedZimCollections.includes(collection.slug) && - 'ring-4 ring-desert-green rounded-lg', - collection.all_downloaded && 'opacity-75', - !isOnline && 'opacity-50 cursor-not-allowed' - )} - > - - {selectedZimCollections.includes(collection.slug) && ( -
- -
- )} + ) : categories && categories.length > 0 ? ( + <> +
+ {categories.map((category) => ( + + ))} +
+ + {/* Tier Selection Modal */} + + + ) : null} + + {/* Legacy flat collections - show if available and no categories */} + {(!categories || categories.length === 0) && ( + <> + {isLoadingZims ? ( +
+
- ))} -
- ) : ( -
-

No ZIM collections available at this time.

-
+ ) : zimCollections && zimCollections.length > 0 ? ( +
+ {zimCollections.map((collection) => ( +
+ isOnline && !collection.all_downloaded && toggleZimCollection(collection.slug) + } + className={classNames( + 'relative', + selectedZimCollections.includes(collection.slug) && + 'ring-4 ring-desert-green rounded-lg', + collection.all_downloaded && 'opacity-75', + !isOnline && 'opacity-50 cursor-not-allowed' + )} + > + + {selectedZimCollections.includes(collection.slug) && ( +
+ +
+ )} +
+ ))} +
+ ) : ( +
+

No content collections available at this time.

+
+ )} + )}
) @@ -623,7 +781,8 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim const hasSelections = selectedServices.length > 0 || selectedMapCollections.length > 0 || - selectedZimCollections.length > 0 + selectedZimCollections.length > 0 || + selectedTiers.size > 0 return (
@@ -700,6 +859,39 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim
)} + {selectedTiers.size > 0 && ( +
+

+ Content Categories ({selectedTiers.size}) +

+ {Array.from(selectedTiers.entries()).map(([categorySlug, tier]) => { + const category = categories?.find((c) => c.slug === categorySlug) + if (!category) return null + const resources = getAllResourcesForTier(tier, category.tiers) + return ( +
+
+ + + {category.name} - {tier.name} + + + ({resources.length} files) + +
+
    + {resources.map((resource, idx) => ( +
  • + {resource.title} +
  • + ))} +
+
+ ) + })} +
+ )} +
{renderStepIndicator()} + {storageInfo && ( +
+ +
+ )}
{currentStep === 1 && renderStep1()} {currentStep === 2 && renderStep2()} diff --git a/admin/inertia/providers/NotificationProvider.tsx b/admin/inertia/providers/NotificationProvider.tsx index aa5d888..a8314ea 100644 --- a/admin/inertia/providers/NotificationProvider.tsx +++ b/admin/inertia/providers/NotificationProvider.tsx @@ -22,7 +22,7 @@ const NotificationsProvider = ({ children }: { children: React.ReactNode }) => { } const removeNotification = (id: string) => { - setNotifications(notifications.filter((n) => n.id !== id)) + setNotifications((prev) => prev.filter((n) => n.id !== id)) } const removeAllNotifications = () => { diff --git a/admin/types/downloads.ts b/admin/types/downloads.ts index 043a787..6828214 100644 --- a/admin/types/downloads.ts +++ b/admin/types/downloads.ts @@ -59,3 +59,33 @@ export type DownloadJobWithProgress = { filepath: string filetype: string } + +// Tiered category types for curated collections UI +export type CategoryResource = { + title: string + description: string + size_mb: number + url: string +} + +export type CategoryTier = { + name: string + slug: string + description: string + recommended?: boolean + includesTier?: string + resources: CategoryResource[] +} + +export type CuratedCategory = { + name: string + slug: string + icon: string + description: string + language: string + tiers: CategoryTier[] +} + +export type CuratedCategoriesFile = { + categories: CuratedCategory[] +} diff --git a/collections/CATEGORIES-TODO.md b/collections/CATEGORIES-TODO.md new file mode 100644 index 0000000..28d3e72 --- /dev/null +++ b/collections/CATEGORIES-TODO.md @@ -0,0 +1,107 @@ +# Kiwix Categories To-Do List + +Potential categories to add to the tiered collections system in `kiwix-categories.json`. + +## Current Categories (Completed) +- [x] Medicine - Medical references, first aid, emergency care +- [x] Survival & Preparedness - Food prep, prepper videos, repair guides +- [x] Education & Reference - Wikipedia, textbooks, TED talks + +--- + +## High Priority + +### Technology & Programming +Stack Overflow, developer documentation, coding tutorials +- Stack Overflow (multiple tags available) +- DevDocs documentation +- freeCodeCamp +- Programming language references + +### Children & Family +Age-appropriate educational content for kids +- Wikipedia for Schools +- Wikibooks Children's Bookshelf +- Khan Academy Kids (via Kolibri - separate system) +- Storybooks, fairy tales + +### Trades & Vocational +Practical skills for building, fixing, and maintaining +- Electrical wiring guides +- Plumbing basics +- Automotive repair +- Woodworking +- Welding fundamentals + +### Agriculture & Gardening +Food production and farming (expand beyond what's in Survival) +- Practical Plants database +- Permaculture guides +- Seed saving +- Animal husbandry +- Composting and soil management + +--- + +## Medium Priority + +### Languages & Reference +Dictionaries, language learning, translation +- Wiktionary (multiple languages) +- Language learning resources +- Translation dictionaries +- Grammar guides + +### History & Culture +Historical knowledge and cultural encyclopedias +- Wikipedia History portal content +- Historical documents +- Cultural archives +- Biographies + +### Legal & Civic +Laws, rights, and civic procedures +- Legal references +- Constitutional documents +- Civic procedures +- Rights and responsibilities + +### Communications +Emergency and amateur radio, networking +- Ham radio guides +- Emergency communication protocols +- Basic networking/IT +- Signal procedures + +--- + +## Nice To Have + +### Entertainment +Recreational reading and activities +- Project Gutenberg (fiction categories) +- Chess tutorials +- Puzzles and games +- Music theory + +### Religion & Philosophy +Spiritual and philosophical texts +- Religious texts (various traditions) +- Philosophy references +- Ethics guides + +### Regional/Non-English Bundles +Content in other languages +- Spanish language bundle +- French language bundle +- Other major languages + +--- + +## Notes + +- Each category should have 3 tiers: Essential, Standard, Comprehensive +- Higher tiers include all content from lower tiers via `includesTier` +- Check Kiwix catalog for available ZIM files: https://download.kiwix.org/zim/ +- Consider storage constraints - Essential tiers should be <500MB ideally +- Mark one tier as `recommended: true` (usually Essential) diff --git a/collections/kiwix-categories.json b/collections/kiwix-categories.json new file mode 100644 index 0000000..53ed8b3 --- /dev/null +++ b/collections/kiwix-categories.json @@ -0,0 +1,325 @@ +{ + "categories": [ + { + "name": "Medicine", + "slug": "medicine", + "icon": "IconStethoscope", + "description": "Medical references, guides, and encyclopedias for healthcare information and emergency preparedness.", + "language": "en", + "tiers": [ + { + "name": "Essential", + "slug": "medicine-essential", + "description": "Core medical references for first aid, medications, and emergency care. Start here.", + "recommended": true, + "resources": [ + { + "title": "Medical Library", + "description": "Field and emergency medicine books and guides", + "url": "https://download.kiwix.org/zim/other/zimgit-medicine_en_2024-08.zim", + "size_mb": 67 + }, + { + "title": "NHS Medicines A to Z", + "description": "How medicines work, dosages, side effects, and interactions", + "url": "https://download.kiwix.org/zim/zimit/nhs.uk_en_medicines_2025-12.zim", + "size_mb": 16 + }, + { + "title": "Military Medicine", + "description": "Tactical and field medicine manuals", + "url": "https://download.kiwix.org/zim/zimit/fas-military-medicine_en_2025-06.zim", + "size_mb": 78 + }, + { + "title": "CDC Health Information", + "description": "Disease prevention, travel health, and outbreak information", + "url": "https://download.kiwix.org/zim/zimit/wwwnc.cdc.gov_en_all_2024-11.zim", + "size_mb": 170 + } + ] + }, + { + "name": "Standard", + "slug": "medicine-standard", + "description": "Comprehensive medical encyclopedia with detailed health information. Includes everything in Essential.", + "includesTier": "medicine-essential", + "resources": [ + { + "title": "MedlinePlus", + "description": "NIH's consumer health encyclopedia - diseases, conditions, drugs, supplements", + "url": "https://download.kiwix.org/zim/zimit/medlineplus.gov_en_all_2025-01.zim", + "size_mb": 1800 + } + ] + }, + { + "name": "Comprehensive", + "slug": "medicine-comprehensive", + "description": "Professional-level medical references and textbooks. Includes everything in Standard.", + "includesTier": "medicine-standard", + "resources": [ + { + "title": "Wikipedia Medicine", + "description": "Curated medical articles from Wikipedia with images", + "url": "https://download.kiwix.org/zim/wikipedia/wikipedia_en_medicine_maxi_2026-01.zim", + "size_mb": 2000 + }, + { + "title": "LibreTexts Medicine", + "description": "Open-source medical textbooks and educational content", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_med_2025-01.zim", + "size_mb": 1100 + }, + { + "title": "LibrePathology", + "description": "Pathology reference for disease identification", + "url": "https://download.kiwix.org/zim/other/librepathology_en_all_maxi_2025-09.zim", + "size_mb": 76 + } + ] + } + ] + }, + { + "name": "Survival & Preparedness", + "slug": "survival", + "icon": "IconShieldCheck", + "description": "Emergency preparedness, self-sufficiency, food storage, and practical survival skills.", + "language": "en", + "tiers": [ + { + "name": "Essential", + "slug": "survival-essential", + "description": "Core food preparation and cooking guides. Lightweight text-based resources to get started.", + "recommended": true, + "resources": [ + { + "title": "Food for Preppers", + "description": "Recipes and techniques for food preservation and preparation", + "url": "https://download.kiwix.org/zim/other/zimgit-food-preparation_en_2025-04.zim", + "size_mb": 98 + }, + { + "title": "FOSS Cooking", + "description": "Quick and easy cooking guides and recipes", + "url": "https://download.kiwix.org/zim/zimit/foss.cooking_en_all_2025-11.zim", + "size_mb": 24 + }, + { + "title": "Based.Cooking", + "description": "Simple, practical recipes from the community", + "url": "https://download.kiwix.org/zim/zimit/based.cooking_en_all_2025-11.zim", + "size_mb": 16 + } + ] + }, + { + "name": "Standard", + "slug": "survival-standard", + "description": "Video guides for winter survival, bug-out gear, plus gardening and cooking Q&A. Includes Essential.", + "includesTier": "survival-essential", + "resources": [ + { + "title": "Canadian Prepper: Winter Prepping", + "description": "Video guides for winter survival and cold weather emergencies", + "url": "https://download.kiwix.org/zim/videos/canadian_prepper_winterprepping_en_2025-11.zim", + "size_mb": 1340 + }, + { + "title": "Canadian Prepper: Bug Out Roll", + "description": "Essential gear selection for your bug-out bag", + "url": "https://download.kiwix.org/zim/videos/canadian_prepper_bugoutroll_en_2025-08.zim", + "size_mb": 975 + }, + { + "title": "Gardening Q&A", + "description": "Stack Exchange Q&A for growing your own food", + "url": "https://download.kiwix.org/zim/stack_exchange/gardening.stackexchange.com_en_all_2025-12.zim", + "size_mb": 923 + }, + { + "title": "Cooking Q&A", + "description": "Stack Exchange Q&A for cooking techniques and food safety", + "url": "https://download.kiwix.org/zim/stack_exchange/cooking.stackexchange.com_en_all_2025-12.zim", + "size_mb": 236 + } + ] + }, + { + "name": "Comprehensive", + "slug": "survival-comprehensive", + "description": "Full prepper video library plus repair guides and DIY skills. Includes Standard.", + "includesTier": "survival-standard", + "resources": [ + { + "title": "Urban Prepper", + "description": "Comprehensive urban emergency preparedness video series", + "url": "https://download.kiwix.org/zim/videos/urban-prepper_en_all_2025-11.zim", + "size_mb": 2240 + }, + { + "title": "Canadian Prepper: Prepping Food", + "description": "Long-term food storage and survival meal preparation", + "url": "https://download.kiwix.org/zim/videos/canadian_prepper_preppingfood_en_2025-09.zim", + "size_mb": 2160 + }, + { + "title": "Canadian Prepper: Bug Out Concepts", + "description": "Strategies and planning for emergency evacuation", + "url": "https://download.kiwix.org/zim/videos/canadian_prepper_bugoutconcepts_en_2025-11.zim", + "size_mb": 2890 + }, + { + "title": "Learning Self-Reliance", + "description": "Prepping, survival skills, beekeeping, and homesteading", + "url": "https://download.kiwix.org/zim/videos/lrnselfreliance_en_all_2025-12.zim", + "size_mb": 3970 + }, + { + "title": "iFixit Repair Guides", + "description": "Step-by-step repair guides for electronics, appliances, and vehicles", + "url": "https://download.kiwix.org/zim/ifixit/ifixit_en_all_2025-12.zim", + "size_mb": 3570 + }, + { + "title": "DIY & Home Improvement Q&A", + "description": "Stack Exchange Q&A for home repairs and construction", + "url": "https://download.kiwix.org/zim/stack_exchange/diy.stackexchange.com_en_all_2025-12.zim", + "size_mb": 1900 + } + ] + } + ] + }, + { + "name": "Education & Reference", + "slug": "education", + "icon": "IconSchool", + "description": "Encyclopedias, textbooks, tutorials, and educational videos for self-directed learning.", + "language": "en", + "tiers": [ + { + "name": "Essential", + "slug": "education-essential", + "description": "Core reference materials - Wikipedia's best articles and open textbooks. Lightweight, text-focused.", + "recommended": true, + "resources": [ + { + "title": "Wikipedia Top 45,000 Articles", + "description": "The 45,000 best Wikipedia articles, optimized for size (no images)", + "url": "https://download.kiwix.org/zim/wikipedia/wikipedia_en_top_nopic_2025-12.zim", + "size_mb": 1880 + }, + { + "title": "Wikibooks", + "description": "Open-content textbooks covering math, science, computing, and more", + "url": "https://download.kiwix.org/zim/wikibooks/wikibooks_en_all_nopic_2025-10.zim", + "size_mb": 3100 + } + ] + }, + { + "name": "Standard", + "slug": "education-standard", + "description": "Adds educational videos, university-level tutorials, and STEM textbooks. Includes Essential.", + "includesTier": "education-essential", + "resources": [ + { + "title": "TED-Ed", + "description": "Educational video lessons on science, history, literature, and more", + "url": "https://download.kiwix.org/zim/ted/ted_mul_ted-ed_2025-07.zim", + "size_mb": 5610 + }, + { + "title": "Wikiversity", + "description": "Tutorials, courses, and learning materials for all levels", + "url": "https://download.kiwix.org/zim/wikiversity/wikiversity_en_all_maxi_2025-11.zim", + "size_mb": 2370 + }, + { + "title": "LibreTexts Mathematics", + "description": "Open-source math textbooks from algebra to calculus", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_math_2025-01.zim", + "size_mb": 831 + }, + { + "title": "LibreTexts Physics", + "description": "Physics courses and textbooks", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_phys_2025-01.zim", + "size_mb": 560 + }, + { + "title": "LibreTexts Chemistry", + "description": "Chemistry courses and textbooks", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_chem_2025-01.zim", + "size_mb": 2180 + }, + { + "title": "LibreTexts Biology", + "description": "Biology courses and textbooks", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_bio_2025-01.zim", + "size_mb": 2240 + }, + { + "title": "Project Gutenberg: Education", + "description": "Classic educational texts and resources", + "url": "https://download.kiwix.org/zim/gutenberg/gutenberg_en_education_2025-12.zim", + "size_mb": 606 + } + ] + }, + { + "name": "Comprehensive", + "slug": "education-comprehensive", + "description": "Complete educational library with full Wikipedia, enhanced textbooks, and TED talks. Includes Standard.", + "includesTier": "education-standard", + "resources": [ + { + "title": "Wikipedia (Full, No Images)", + "description": "Complete English Wikipedia - over 6 million articles", + "url": "https://download.kiwix.org/zim/wikipedia/wikipedia_en_all_mini_2025-12.zim", + "size_mb": 11400 + }, + { + "title": "Wikibooks (With Images)", + "description": "Open textbooks with full illustrations and diagrams", + "url": "https://download.kiwix.org/zim/wikibooks/wikibooks_en_all_maxi_2025-10.zim", + "size_mb": 5400 + }, + { + "title": "TED Conference", + "description": "Main TED conference talks on ideas worth spreading", + "url": "https://download.kiwix.org/zim/ted/ted_mul_ted-conference_2025-08.zim", + "size_mb": 16500 + }, + { + "title": "LibreTexts Humanities", + "description": "Literature, philosophy, history, and social sciences", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_human_2025-01.zim", + "size_mb": 3730 + }, + { + "title": "LibreTexts Geosciences", + "description": "Earth science, geology, and environmental studies", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_geo_2025-01.zim", + "size_mb": 1190 + }, + { + "title": "LibreTexts Engineering", + "description": "Engineering courses and technical references", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_eng_2025-01.zim", + "size_mb": 678 + }, + { + "title": "LibreTexts Business", + "description": "Business, economics, and management textbooks", + "url": "https://download.kiwix.org/zim/libretexts/libretexts.org_en_biz_2025-01.zim", + "size_mb": 840 + } + ] + } + ] + } + ] +}