Initial commit: Forrest Mims Electronics Reference Library

Astro site with e-book reader for classic electronics notebooks.
15 Mims notebooks + 1 Ugly's Electrical Reference, served via
Docker/Caddy at mims.l.supported.systems. PDFs tracked with git-lfs.
This commit is contained in:
Ryan Malloy 2026-02-13 05:09:09 -07:00
commit f7b160a9c1
95 changed files with 10453 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*.pdf filter=lfs diff=lfs merge=lfs -text
*.PDF filter=lfs diff=lfs merge=lfs -text

22
.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
# Dependencies
node_modules/
# Build output
dist/
.astro/
# Environment
.env
.env.local
# IDE
.vscode/
.idea/
# OS
.DS_Store
Thumbs.db
# Logs
*.log
npm-debug.log*

BIN
notebooks/01_Basic_Semiconductor_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/02_Op_Amp_IC_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/03_555_Timer_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/04_Formulas_Tables_Basic_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/05_Communications_Projects.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/06_Solar_Cell_Projects.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/07_Optoelectronics_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/08_Sensor_Projects.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/09_Magnet_And_Sensor_Projects.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/10_Optoelectronic_Circuits_1986.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/11_Basic_Semiconductor_1993.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
notebooks/12_Op_Amp_IC_1985.pdf (Stored with Git LFS) Normal file

Binary file not shown.

193
notebooks/README.md Normal file
View File

@ -0,0 +1,193 @@
# Forrest M. Mims III - Engineer's Mini-Notebook Collection
A collection of the legendary hand-illustrated electronics notebooks originally published by Radio Shack in the 1980s-1990s. These notebooks are considered classics in electronics education, featuring Mims' distinctive hand-drawn circuit diagrams and clear explanations.
## Downloaded PDFs (12 files, 68MB total)
| # | Filename | Size | Description |
|---|----------|------|-------------|
| 01 | `01_Basic_Semiconductor_Circuits.pdf` | 4.3 MB | Transistors, diodes, basic circuits |
| 02 | `02_Op_Amp_IC_Circuits.pdf` | 4.3 MB | Operational amplifier projects |
| 03 | `03_555_Timer_Circuits.pdf` | 2.9 MB | 555 timer applications |
| 04 | `04_Formulas_Tables_Basic_Circuits.pdf` | 4.2 MB | Reference formulas & tables |
| 05 | `05_Communications_Projects.pdf` | 10.7 MB | Radio and communications |
| 06 | `06_Solar_Cell_Projects.pdf` | 4.5 MB | Solar/photovoltaic circuits |
| 07 | `07_Optoelectronics_Circuits.pdf` | 4.2 MB | LEDs, phototransistors, fiber optics |
| 08 | `08_Sensor_Projects.pdf` | 4.4 MB | Various sensor circuits |
| 09 | `09_Magnet_And_Sensor_Projects.pdf` | 4.3 MB | Magnetic sensors & projects |
| 10 | `10_Optoelectronic_Circuits_1986.pdf` | 10.7 MB | Earlier edition with bonus content |
| 11 | `11_Basic_Semiconductor_1993.pdf` | 4.4 MB | Revised 1993 edition |
| 12 | `12_Op_Amp_IC_1985.pdf` | 10.7 MB | Original 1985 edition |
---
## Complete Archive.org Details
### 1. Basic Semiconductor Circuits
**Local File:** `01_Basic_Semiconductor_Circuits.pdf`
**Archive.org:** [View Online](https://archive.org/details/electronics_-_Forrest_Mims-engineers_mini-notebook_basic_semiconductor_circuits_)
| Format | Filename |
|--------|----------|
| PDF (Image) | `electronics - Forrest Mims-engineer's mini-notebook basic semiconductor circuits (radio shack electronics).pdf` |
| PDF (Text Layer) | `electronics - Forrest Mims-engineer's mini-notebook basic semiconductor circuits (radio shack electronics)_text.pdf` |
| DjVu | `electronics - Forrest Mims-engineer's mini-notebook basic semiconductor circuits (radio shack electronics).djvu` |
| Plain Text | `electronics - Forrest Mims-engineer's mini-notebook basic semiconductor circuits (radio shack electronics)_djvu.txt` |
---
### 2. Op Amp IC Circuits
**Local File:** `02_Op_Amp_IC_Circuits.pdf`
**Archive.org:** [View Online](https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Op_Amp_Ic_Circuits_Radio_Shack_Electronics)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Forrest Mims-Engineer's Mini-Notebook Op Amp Ic Circuits (Radio Shack Electronics)(1).pdf` |
| PDF (Text Layer) | `Forrest Mims-Engineer's Mini-Notebook Op Amp Ic Circuits (Radio Shack Electronics)(1)_text.pdf` |
| DjVu | `Forrest Mims-Engineer's Mini-Notebook Op Amp Ic Circuits (Radio Shack Electronics)(1).djvu` |
| Plain Text | `Forrest Mims-Engineer's Mini-Notebook Op Amp Ic Circuits (Radio Shack Electronics)(1)_djvu.txt` |
---
### 3. 555 Timer Circuits
**Local File:** `03_555_Timer_Circuits.pdf`
**Archive.org:** [View Online](https://archive.org/details/electronics_-_Forrest_Mims-engineers_mini-notebook_555_timer_circuits_radio_sha)
| Format | Filename |
|--------|----------|
| PDF (Image) | `electronics - Forrest Mims-engineer's mini-notebook 555 timer circuits (radio shack electronics).pdf` |
| PDF (Text Layer) | `electronics - Forrest Mims-engineer's mini-notebook 555 timer circuits (radio shack electronics)_text.pdf` |
| DjVu | `electronics - Forrest Mims-engineer's mini-notebook 555 timer circuits (radio shack electronics).djvu` |
| Plain Text | `electronics - Forrest Mims-engineer's mini-notebook 555 timer circuits (radio shack electronics)_djvu.txt` |
---
### 4. Formulas, Tables & Basic Circuits
**Local File:** `04_Formulas_Tables_Basic_Circuits.pdf`
**Archive.org:** [View Online](https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Formulas_Tables_Basic_Circuits_Radio_Shack)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Forrest Mims-Engineer's Mini-Notebook Formulas Tables Basic Circuits (Radio Shack Electronics).pdf` |
| PDF (Text Layer) | `Forrest Mims-Engineer's Mini-Notebook Formulas Tables Basic Circuits (Radio Shack Electronics)_text.pdf` |
| DjVu | `Forrest Mims-Engineer's Mini-Notebook Formulas Tables Basic Circuits (Radio Shack Electronics).djvu` |
| Plain Text | `Forrest Mims-Engineer's Mini-Notebook Formulas Tables Basic Circuits (Radio Shack Electronics)_djvu.txt` |
---
### 5. Communications Projects
**Local File:** `05_Communications_Projects.pdf`
**Archive.org:** [View Online](https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_-_Communications_Projects_Radio_Shack_Elec)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Forrest Mims-Engineer's Mini-Notebook - Communications Projects (Radio Shack Electronics).pdf` |
| PDF (Text Layer) | `Forrest Mims-Engineer's Mini-Notebook - Communications Projects (Radio Shack Electronics)_text.pdf` |
| DjVu | `Forrest Mims-Engineer's Mini-Notebook - Communications Projects (Radio Shack Electronics).djvu` |
| Plain Text | `Forrest Mims-Engineer's Mini-Notebook - Communications Projects (Radio Shack Electronics)_djvu.txt` |
---
### 6. Solar Cell Projects
**Local File:** `06_Solar_Cell_Projects.pdf`
**Archive.org:** [View Online](https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Solar_Cell_Projects_Radio_Shack_Electronic)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Forrest Mims-Engineer's Mini-Notebook Solar Cell Projects (Radio Shack Electronics).pdf` |
| PDF (Text Layer) | `Forrest Mims-Engineer's Mini-Notebook Solar Cell Projects (Radio Shack Electronics)_text.pdf` |
| DjVu | `Forrest Mims-Engineer's Mini-Notebook Solar Cell Projects (Radio Shack Electronics).djvu` |
| Plain Text | `Forrest Mims-Engineer's Mini-Notebook Solar Cell Projects (Radio Shack Electronics)_djvu.txt` |
---
### 7. Optoelectronics Circuits
**Local File:** `07_Optoelectronics_Circuits.pdf`
**Archive.org:** [View Online](https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Optoelectronics_Circuits_Radio_Shack_Elect)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Forrest Mims-Engineer's Mini-Notebook Optoelectronics Circuits (Radio Shack Electronics).pdf` |
| PDF (Text Layer) | `Forrest Mims-Engineer's Mini-Notebook Optoelectronics Circuits (Radio Shack Electronics)_text.pdf` |
| DjVu | `Forrest Mims-Engineer's Mini-Notebook Optoelectronics Circuits (Radio Shack Electronics).djvu` |
| Plain Text | `Forrest Mims-Engineer's Mini-Notebook Optoelectronics Circuits (Radio Shack Electronics)_djvu.txt` |
---
### 8. Sensor Projects
**Local File:** `08_Sensor_Projects.pdf`
**Archive.org:** [View Online](https://archive.org/details/Forrest_Mims-engineers_mini-notebook_sensor_projects_radio_shack_electronics)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Forrest Mims-engineer's mini-notebook sensor projects (radio shack electronics).pdf` |
| PDF (Text Layer) | `Forrest Mims-engineer's mini-notebook sensor projects (radio shack electronics)_text.pdf` |
| DjVu | `Forrest Mims-engineer's mini-notebook sensor projects (radio shack electronics).djvu` |
| Plain Text | `Forrest Mims-engineer's mini-notebook sensor projects (radio shack electronics)_djvu.txt` |
---
### 9. Magnet and Sensor Projects
**Local File:** `09_Magnet_And_Sensor_Projects.pdf`
**Archive.org:** [View Online](https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Magnet_And_Sensor_Projects_Radio_Shack_Ele)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Forrest Mims-Engineer's Mini-Notebook Magnet And Sensor Projects (Radio Shack Electronics).pdf` |
| PDF (Text Layer) | `Forrest Mims-Engineer's Mini-Notebook Magnet And Sensor Projects (Radio Shack Electronics)_text.pdf` |
| DjVu | `Forrest Mims-Engineer's Mini-Notebook Magnet And Sensor Projects (Radio Shack Electronics).djvu` |
| Plain Text | `Forrest Mims-Engineer's Mini-Notebook Magnet And Sensor Projects (Radio Shack Electronics)_djvu.txt` |
---
### 10. Optoelectronic Circuits (1986 Edition)
**Local File:** `10_Optoelectronic_Circuits_1986.pdf`
**Archive.org:** [View Online](https://archive.org/details/Radio_Shack_Engineers_Mini-Notebook_-_Optoelectronic_Circuits_-_F._Mims_1986_W)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Radio Shack Engineer's Mini-Notebook - Optoelectronic Circuits - F. Mims (1986) WW.pdf` |
| PDF (Text Layer) | `Radio Shack Engineer's Mini-Notebook - Optoelectronic Circuits - F. Mims (1986) WW_text.pdf` |
| DjVu | `Radio Shack Engineer's Mini-Notebook - Optoelectronic Circuits - F. Mims (1986) WW.djvu` |
| Plain Text | `Radio Shack Engineer's Mini-Notebook - Optoelectronic Circuits - F. Mims (1986) WW_djvu.txt` |
---
### 11. Basic Semiconductor Circuits (1993 Edition)
**Local File:** `11_Basic_Semiconductor_1993.pdf`
**Archive.org:** [View Online](https://archive.org/details/Radio_Shack_Engineers_Mini-Notebook_-_Basic_Semiconductor_Circuits_-_F._Mims_19)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Radio Shack Engineer's Mini-Notebook - Basic Semiconductor Circuits - F. Mims (1993) WW.pdf` |
| PDF (Text Layer) | `Radio Shack Engineer's Mini-Notebook - Basic Semiconductor Circuits - F. Mims (1993) WW_text.pdf` |
| DjVu | `Radio Shack Engineer's Mini-Notebook - Basic Semiconductor Circuits - F. Mims (1993) WW.djvu` |
| Plain Text | `Radio Shack Engineer's Mini-Notebook - Basic Semiconductor Circuits - F. Mims (1993) WW_djvu.txt` |
---
### 12. Op Amp IC Circuits (1985 Edition)
**Local File:** `12_Op_Amp_IC_1985.pdf`
**Archive.org:** [View Online](https://archive.org/details/Radio_Shack_Engineers_Mini-Notebook_-_Op_Amp_IC_Circuits_-_F._Mims_1985_WW)
| Format | Filename |
|--------|----------|
| PDF (Image) | `Radio Shack Engineer's Mini-Notebook - Op Amp IC Circuits - F. Mims (1985) WW.pdf` |
| PDF (Text Layer) | `Radio Shack Engineer's Mini-Notebook - Op Amp IC Circuits - F. Mims (1985) WW_text.pdf` |
| DjVu | `Radio Shack Engineer's Mini-Notebook - Op Amp IC Circuits - F. Mims (1985) WW.djvu` |
| Plain Text | `Radio Shack Engineer's Mini-Notebook - Op Amp IC Circuits - F. Mims (1985) WW_djvu.txt` |
---
## About Forrest M. Mims III
Forrest M. Mims III is an American amateur scientist, author, and inventor known for his hand-illustrated electronics books. His distinctive style—featuring hand-lettered text and meticulously drawn circuit diagrams—became iconic in the Radio Shack "Engineer's Mini-Notebook" series.
These notebooks taught countless hobbyists and students the fundamentals of electronics through practical, buildable projects.
## Source Collection
All materials sourced from the [Folkscanomy: Tandy and Radio Shack Books](https://archive.org/details/folkscanomy_tandy) collection on Archive.org.
---
*Downloaded: January 2026*

43
notebooks/download_mims.sh Executable file
View File

@ -0,0 +1,43 @@
#!/bin/bash
# Forrest Mims Mini-Notebook Downloader
NOTEBOOKS=(
"electronics_-_Forrest_Mims-engineers_mini-notebook_basic_semiconductor_circuits_"
"Forrest_Mims-Engineers_Mini-Notebook_Op_Amp_Ic_Circuits_Radio_Shack_Electronics"
"electronics_-_Forrest_Mims-engineers_mini-notebook_555_timer_circuits_radio_sha"
"Forrest_Mims-Engineers_Mini-Notebook_Formulas_Tables_Basic_Circuits_Radio_Shack"
"Forrest_Mims-Engineers_Mini-Notebook_-_Communications_Projects_Radio_Shack_Elec"
"Forrest_Mims-engineers_mini-notebook_basic_semiconductor_circuits_radio_shack_e"
"Forrest_Mims-Engineers_Mini-Notebook_Solar_Cell_Projects_Radio_Shack_Electronic"
"Forrest_Mims-Engineers_Mini-Notebook_Magnet_and_Sensor_Projects_Radio_Shack_Ele"
"Forrest_Mims-Engineers_Mini-Notebook_Optoelectronics_Circuits_Radio_Shack_Elect"
"Forrest_Mims-Engineers_Mini-Notebook_-_Sensor_Projects_Radio_Shack_Electronics"
"RadioShackEngineersMiniNotebookOpAmpICCircuits"
"Forrest_Mims-Engineers_Mini-Notebook_Formulas_Tables_and_Basic_Circuits_Radio_S"
"RadioShackEngineersMiniNotebookBasicSemiconductorCircuits"
"RadioShackEngineersMiniNotebookOptoelectronicCircuits"
)
echo "📚 Downloading Forrest Mims Mini-Notebooks from Archive.org"
echo "============================================================"
for id in "${NOTEBOOKS[@]}"; do
echo ""
echo "📖 Processing: $id"
# Get metadata JSON
curl -s "https://archive.org/metadata/$id" > "${id}_metadata.json" 2>/dev/null
# Try to download PDF (try common naming patterns)
for pattern in "${id}.pdf" "${id}_text.pdf" "$(echo $id | sed 's/_/-/g').pdf"; do
url="https://archive.org/download/$id/$pattern"
if curl -sI "$url" 2>/dev/null | grep -q "200 OK"; then
echo " ⬇️ Downloading PDF: $pattern"
curl -s -L -o "${id}.pdf" "$url"
break
fi
done
done
echo ""
echo "✅ Download complete!"

12
site/.env.example Normal file
View File

@ -0,0 +1,12 @@
# Docker Compose Configuration
COMPOSE_PROJECT_NAME=mims-library
# Mode: development or production
MODE=production
NODE_ENV=production
# Caddy reverse proxy hostname
CADDY_HOST=mims.localhost
# Dev mode: uncomment to mount src for hot reload
# DEV_MOUNT=./src

24
site/.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

20
site/Caddyfile Normal file
View File

@ -0,0 +1,20 @@
:4321 {
root * /srv
file_server
# Handle clean URLs - try file, then directory, then .html extension
try_files {path} {path}/ {path}.html /index.html
# Compression
encode gzip
# Cache static assets
@static {
path *.jpg *.jpeg *.png *.gif *.ico *.css *.js *.pdf *.svg *.woff *.woff2
}
header @static Cache-Control "public, max-age=604800, immutable"
# Security headers
header X-Frame-Options "SAMEORIGIN"
header X-Content-Type-Options "nosniff"
}

33
site/Dockerfile Normal file
View File

@ -0,0 +1,33 @@
# Build stage
FROM ghcr.io/astral-sh/uv:python3.11-bookworm-slim AS base
WORKDIR /app
# Install Node.js
RUN apt-get update && apt-get install -y curl && \
curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
apt-get install -y nodejs && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Development target
FROM base AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 4321
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
# Build stage for production
FROM base AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production target - serve static files with Caddy
FROM caddy:alpine AS production
COPY --from=builder /app/dist /srv
COPY Caddyfile /etc/caddy/Caddyfile
EXPOSE 4321
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]

37
site/Makefile Normal file
View File

@ -0,0 +1,37 @@
.PHONY: dev prod build up down logs clean
# Development mode with hot reload
dev:
MODE=development DEV_MOUNT=./src docker compose up --build
# Production mode
prod:
MODE=production docker compose up -d --build
# Build only
build:
docker compose build
# Start containers
up:
docker compose up -d
# Stop containers
down:
docker compose down
# View logs
logs:
docker compose logs -f
# Clean up
clean:
docker compose down -v --rmi local
# Local development without Docker
local:
npm run dev
# Build static site
static:
npm run build

43
site/README.md Normal file
View File

@ -0,0 +1,43 @@
# Astro Starter Kit: Minimal
```sh
npm create astro@latest -- --template minimal
```
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```text
/
├── public/
├── src/
│ └── pages/
│ └── index.astro
└── package.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).

24
site/astro.config.mjs Normal file
View File

@ -0,0 +1,24 @@
// @ts-check
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import tailwindcss from '@tailwindcss/vite';
// https://astro.build/config
export default defineConfig({
integrations: [react()],
// Production site URL for correct link generation
site: process.env.SITE_URL || 'https://mims.l.supported.systems',
// Disable telemetry and devToolbar
telemetry: false,
devToolbar: { enabled: false },
vite: {
plugins: [tailwindcss()],
server: {
host: '0.0.0.0',
}
}
});

22
site/components.json Normal file
View File

@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/styles/global.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {}
}

24
site/docker-compose.yml Normal file
View File

@ -0,0 +1,24 @@
services:
mims-library:
build:
context: .
dockerfile: Dockerfile
target: ${MODE:-production}
container_name: mims-library
restart: unless-stopped
environment:
- NODE_ENV=${NODE_ENV:-production}
- HOST=0.0.0.0
- PORT=4321
volumes:
# Dev mode: mount source for hot reload
- ${DEV_MOUNT:-/dev/null}:/app/src:ro
networks:
- caddy
labels:
caddy: ${CADDY_HOST:-mims.localhost}
caddy.reverse_proxy: "{{upstreams 4321}}"
networks:
caddy:
external: true

7346
site/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

32
site/package.json Normal file
View File

@ -0,0 +1,32 @@
{
"name": "site",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/react": "^4.4.2",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@tailwindcss/vite": "^4.1.18",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"astro": "^5.16.7",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.562.0",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-pdf": "^10.3.0",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.18"
},
"devDependencies": {
"tw-animate-css": "^1.4.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

4
site/public/favicon.svg Normal file
View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#3b5998" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>

After

Width:  |  Height:  |  Size: 296 B

BIN
site/public/pdfs/mims/01_Basic_Semiconductor_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/02_Op_Amp_IC_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/03_555_Timer_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/04_Formulas_Tables_Basic_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/05_Communications_Projects.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/06_Solar_Cell_Projects.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/07_Optoelectronics_Circuits.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/08_Sensor_Projects.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/09_Magnet_And_Sensor_Projects.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/10_Optoelectronic_Circuits_1986.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/11_Basic_Semiconductor_1993.pdf (Stored with Git LFS) Normal file

Binary file not shown.

BIN
site/public/pdfs/mims/12_Op_Amp_IC_1985.pdf (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
site/public/pdfs/uglys/Uglys_Electrical_Reference_2005.pdf (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,69 @@
---
import { Badge } from '@/components/ui/badge';
import type { CollectionEntry } from 'astro:content';
interface Props {
book: CollectionEntry<'books'>;
}
const { book } = Astro.props;
const { title, shortTitle, description, topics, localPdf, coverImage, year, collection } = book.data;
---
<a
href={`/${collection}/${book.slug.split('/').pop()}`}
class="book-card block bg-card rounded-lg border border-border overflow-hidden hover:border-primary/50"
>
<div class="relative">
{coverImage ? (
<img
src={coverImage}
alt={`Cover of ${shortTitle}`}
class="w-full aspect-[3/4] object-cover object-top"
loading="lazy"
/>
) : (
<div class="w-full aspect-[3/4] bg-muted flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
</div>
)}
{year && (
<div class="absolute top-2 right-2 bg-card/90 backdrop-blur-sm text-xs font-medium px-2 py-1 rounded border border-border">
{year}
</div>
)}
</div>
<div class="p-4 space-y-3">
<div>
<h3 class="font-semibold text-foreground title-accent line-clamp-2 leading-tight">
{shortTitle}
</h3>
<p class="text-sm text-muted-foreground mt-1 line-clamp-2">
{description}
</p>
</div>
<div class="flex flex-wrap gap-1">
{topics.slice(0, 3).map((topic) => (
<Badge variant="secondary" className="text-xs">
{topic.replace(/-/g, ' ')}
</Badge>
))}
</div>
<div class="pt-2 border-t border-border flex items-center justify-between text-xs text-muted-foreground">
<span class="flex items-center gap-1">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
</svg>
PDF
</span>
<span class="text-primary font-medium">View →</span>
</div>
</div>
</a>

View File

@ -0,0 +1,27 @@
---
import BookCard from './BookCard.astro';
import type { CollectionEntry } from 'astro:content';
interface Props {
books: CollectionEntry<'books'>[];
title?: string;
description?: string;
}
const { books, title, description } = Astro.props;
---
<section class="space-y-6">
{(title || description) && (
<div class="space-y-2">
{title && <h2 class="text-2xl font-bold title-accent">{title}</h2>}
{description && <p class="text-muted-foreground">{description}</p>}
</div>
)}
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
{books.map((book) => (
<BookCard book={book} />
))}
</div>
</section>

View File

@ -0,0 +1,310 @@
import { useState, useRef, useEffect } from 'react';
interface EBookReaderProps {
pdfUrl: string;
title: string;
coverImage?: string;
}
export default function EBookReader({ pdfUrl, title, coverImage }: EBookReaderProps) {
const [isFullscreen, setIsFullscreen] = useState(false);
const [brightness, setBrightness] = useState(100);
const [isWarmLight, setIsWarmLight] = useState(true);
const containerRef = useRef<HTMLDivElement>(null);
// Handle escape key to exit fullscreen
useEffect(() => {
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape' && isFullscreen) {
setIsFullscreen(false);
}
};
window.addEventListener('keydown', handleEscape);
return () => window.removeEventListener('keydown', handleEscape);
}, [isFullscreen]);
// Lock scroll when fullscreen
useEffect(() => {
if (isFullscreen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
return () => {
document.body.style.overflow = '';
};
}, [isFullscreen]);
return (
<>
{/* Fullscreen overlay */}
{isFullscreen && (
<div
className="fixed inset-0 bg-stone-900/95 z-50 flex items-center justify-center p-2 md:p-4"
onClick={(e) => e.target === e.currentTarget && setIsFullscreen(false)}
>
<div className="w-full max-w-[95vw] h-full flex flex-col">
{/* Fullscreen header */}
<div className="flex items-center justify-between py-3 px-4 text-stone-300">
<div className="flex items-center gap-3">
<div className="w-2 h-2 rounded-full bg-amber-500 animate-pulse" />
<span className="text-sm font-medium">{title}</span>
</div>
<div className="flex items-center gap-4">
{/* Brightness control */}
<div className="flex items-center gap-2">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-stone-400">
<circle cx="12" cy="12" r="4"/>
<path d="M12 2v2"/>
<path d="M12 20v2"/>
<path d="m4.93 4.93 1.41 1.41"/>
<path d="m17.66 17.66 1.41 1.41"/>
<path d="M2 12h2"/>
<path d="M20 12h2"/>
<path d="m6.34 17.66-1.41 1.41"/>
<path d="m19.07 4.93-1.41 1.41"/>
</svg>
<input
type="range"
min="50"
max="100"
value={brightness}
onChange={(e) => setBrightness(Number(e.target.value))}
className="w-20 h-1 bg-stone-700 rounded-lg appearance-none cursor-pointer accent-amber-500"
/>
</div>
{/* Warm light toggle */}
<button
onClick={() => setIsWarmLight(!isWarmLight)}
className={`p-2 rounded-lg transition-colors ${isWarmLight ? 'bg-amber-500/20 text-amber-400' : 'text-stone-400 hover:text-stone-300'}`}
title="Warm light"
>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M8 2h8"/>
<path d="M9 2v2.789a4 4 0 0 1-.672 2.219l-.656.984A4 4 0 0 0 7 10.212V14a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2v-3.788a4 4 0 0 0-.672-2.219l-.656-.984A4 4 0 0 1 15 4.788V2"/>
<path d="M9 16v3a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-3"/>
</svg>
</button>
{/* Close button */}
<button
onClick={() => setIsFullscreen(false)}
className="p-2 rounded-lg text-stone-400 hover:text-stone-200 hover:bg-stone-800 transition-colors"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M18 6 6 18"/>
<path d="m6 6 12 12"/>
</svg>
</button>
</div>
</div>
{/* Fullscreen reader */}
<div
className="flex-1 rounded-lg overflow-hidden shadow-2xl"
style={{
filter: `brightness(${brightness}%)`,
backgroundColor: isWarmLight ? '#f5f0e6' : '#fff'
}}
>
<iframe
src={`${pdfUrl}#toolbar=0&navpanes=0&scrollbar=1&view=FitH`}
className="w-full h-full border-0"
title={title}
style={{
filter: isWarmLight ? 'sepia(15%)' : 'none'
}}
/>
</div>
{/* Fullscreen footer hint */}
<div className="text-center py-2 text-stone-500 text-xs">
Press <kbd className="px-1.5 py-0.5 bg-stone-800 rounded text-stone-400">Esc</kbd> or click outside to exit
</div>
</div>
</div>
)}
{/* E-Reader Device Frame */}
<div
ref={containerRef}
className="ereader-device relative w-full"
>
{/* Device outer shell */}
<div className="relative bg-gradient-to-b from-stone-800 via-stone-900 to-stone-950 rounded-2xl md:rounded-[2rem] p-2 md:p-3 shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5),inset_0_1px_1px_rgba(255,255,255,0.1)]">
{/* Device bezel with subtle texture */}
<div className="relative bg-gradient-to-b from-stone-700 to-stone-800 rounded-xl md:rounded-[1.5rem] p-[2px] md:p-[3px] shadow-[inset_0_2px_4px_rgba(0,0,0,0.3)]">
{/* Inner bezel */}
<div className="bg-stone-900 rounded-xl md:rounded-[1.4rem] p-1.5 md:p-2">
{/* Screen area */}
<div className="relative rounded-xl overflow-hidden bg-stone-950 shadow-[inset_0_0_30px_rgba(0,0,0,0.5)]">
{/* Status bar */}
<div className="flex items-center justify-between px-4 py-2 bg-stone-900/90 border-b border-stone-800">
<div className="flex items-center gap-2">
<div className="w-1.5 h-1.5 rounded-full bg-emerald-500" />
<span className="text-[10px] text-stone-400 font-medium tracking-wide uppercase">Reading</span>
</div>
<div className="flex items-center gap-3 text-stone-500">
<span className="text-[10px]">{title}</span>
</div>
<div className="flex items-center gap-2">
{/* Battery indicator */}
<div className="flex items-center gap-1">
<div className="w-5 h-2.5 rounded-sm border border-stone-600 p-[1px]">
<div className="w-full h-full rounded-[1px] bg-emerald-500" />
</div>
</div>
</div>
</div>
{/* PDF Display with paper texture */}
<div
className="relative"
style={{
background: isWarmLight
? 'linear-gradient(to bottom, #faf8f3, #f5f0e6)'
: 'linear-gradient(to bottom, #ffffff, #fafafa)',
filter: `brightness(${brightness}%)`
}}
>
{/* Paper texture overlay */}
<div
className="absolute inset-0 opacity-30 pointer-events-none mix-blend-multiply"
style={{
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
}}
/>
<iframe
src={`${pdfUrl}#toolbar=0&navpanes=0&scrollbar=1&view=FitH`}
className="w-full border-0 relative z-10"
style={{
height: 'max(75vh, 600px)',
filter: isWarmLight ? 'sepia(10%)' : 'none'
}}
title={title}
/>
</div>
{/* Bottom control bar */}
<div className="flex items-center justify-between px-4 py-3 bg-stone-900/90 border-t border-stone-800">
{/* Left controls */}
<div className="flex items-center gap-1">
<button
onClick={() => setIsWarmLight(!isWarmLight)}
className={`p-2 rounded-lg transition-all ${isWarmLight ? 'bg-amber-500/20 text-amber-400' : 'text-stone-500 hover:text-stone-300'}`}
title="Warm reading light"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M8 2h8"/>
<path d="M9 2v2.789a4 4 0 0 1-.672 2.219l-.656.984A4 4 0 0 0 7 10.212V14a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2v-3.788a4 4 0 0 0-.672-2.219l-.656-.984A4 4 0 0 1 15 4.788V2"/>
<path d="M9 16v3a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-3"/>
</svg>
</button>
{/* Brightness slider */}
<div className="flex items-center gap-2 px-2">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-stone-500">
<circle cx="12" cy="12" r="4"/>
<path d="M12 2v2"/>
<path d="M12 20v2"/>
<path d="m4.93 4.93 1.41 1.41"/>
<path d="m17.66 17.66 1.41 1.41"/>
<path d="M2 12h2"/>
<path d="M20 12h2"/>
<path d="m6.34 17.66-1.41 1.41"/>
<path d="m19.07 4.93-1.41 1.41"/>
</svg>
<input
type="range"
min="50"
max="100"
value={brightness}
onChange={(e) => setBrightness(Number(e.target.value))}
className="w-16 h-1 bg-stone-700 rounded-lg appearance-none cursor-pointer accent-amber-500"
/>
</div>
</div>
{/* Center - Fullscreen */}
<button
onClick={() => setIsFullscreen(true)}
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-stone-800 hover:bg-stone-700 text-stone-300 transition-all text-sm font-medium"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M8 3H5a2 2 0 0 0-2 2v3"/>
<path d="M21 8V5a2 2 0 0 0-2-2h-3"/>
<path d="M3 16v3a2 2 0 0 0 2 2h3"/>
<path d="M16 21h3a2 2 0 0 0 2-2v-3"/>
</svg>
<span className="hidden sm:inline">Immersive Mode</span>
</button>
{/* Right controls */}
<div className="flex items-center gap-1">
<a
href={pdfUrl}
target="_blank"
rel="noopener noreferrer"
className="p-2 rounded-lg text-stone-500 hover:text-stone-300 hover:bg-stone-800 transition-all"
title="Open in new tab"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" x2="21" y1="14" y2="3"/>
</svg>
</a>
<a
href={pdfUrl}
download
className="p-2 rounded-lg text-stone-500 hover:text-stone-300 hover:bg-stone-800 transition-all"
title="Download PDF"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" x2="12" y1="15" y2="3"/>
</svg>
</a>
</div>
</div>
</div>
</div>
</div>
{/* Device bottom chin with logo */}
<div className="flex items-center justify-center py-3">
<div className="flex items-center gap-2 text-stone-600">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
<span className="text-[10px] font-medium tracking-widest uppercase">Mims Reader</span>
</div>
</div>
</div>
{/* Device shadow */}
<div className="absolute -bottom-4 left-1/2 -translate-x-1/2 w-3/4 h-8 bg-black/20 blur-xl rounded-full" />
</div>
{/* Fallback for non-embedded viewing */}
<div className="mt-4 text-center">
<p className="text-sm text-muted-foreground">
PDF not displaying correctly?{' '}
<a href={pdfUrl} target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">
Open in browser
</a>{' '}
or{' '}
<a href={pdfUrl} download className="text-primary hover:underline">
download the file
</a>.
</p>
</div>
</>
);
}

View File

@ -0,0 +1,106 @@
import { useState } from 'react';
import { Button } from '@/components/ui/button';
interface PdfViewerProps {
pdfUrl: string;
}
export default function PdfViewer({ pdfUrl }: PdfViewerProps) {
const [isFullscreen, setIsFullscreen] = useState(false);
return (
<div className="flex flex-col">
{/* Controls */}
<div className="flex items-center justify-between p-3 border-b border-border bg-muted/30">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14 2 14 8 20 8"/>
</svg>
<span>PDF Document</span>
</div>
<div className="flex items-center gap-2">
<Button
variant="outline"
size="sm"
onClick={() => setIsFullscreen(!isFullscreen)}
className="h-8"
>
{isFullscreen ? (
<>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mr-1.5">
<path d="M8 3v3a2 2 0 0 1-2 2H3"/>
<path d="M21 8h-3a2 2 0 0 1-2-2V3"/>
<path d="M3 16h3a2 2 0 0 1 2 2v3"/>
<path d="M16 21v-3a2 2 0 0 1 2-2h3"/>
</svg>
<span className="hidden sm:inline">Compact</span>
</>
) : (
<>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="mr-1.5">
<path d="M8 3H5a2 2 0 0 0-2 2v3"/>
<path d="M21 8V5a2 2 0 0 0-2-2h-3"/>
<path d="M3 16v3a2 2 0 0 0 2 2h3"/>
<path d="M16 21h3a2 2 0 0 0 2-2v-3"/>
</svg>
<span className="hidden sm:inline">Expand</span>
</>
)}
</Button>
<a
href={pdfUrl}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm border border-border rounded-md hover:bg-muted transition-colors"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" x2="21" y1="14" y2="3"/>
</svg>
<span className="hidden sm:inline">Open in new tab</span>
</a>
<a
href={pdfUrl}
download
className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" x2="12" y1="15" y2="3"/>
</svg>
<span className="hidden sm:inline">Download</span>
</a>
</div>
</div>
{/* PDF Embed */}
<div className={`bg-neutral-200 dark:bg-neutral-800 ${isFullscreen ? 'h-[85vh]' : 'h-[600px]'} transition-all duration-300`}>
<iframe
src={`${pdfUrl}#toolbar=1&navpanes=1&scrollbar=1`}
className="w-full h-full border-0"
title="PDF Viewer"
/>
</div>
{/* Fallback message */}
<div className="p-4 text-center text-sm text-muted-foreground bg-muted/30 border-t border-border">
<p>
PDF not displaying? Try{' '}
<a href={pdfUrl} target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">
opening directly
</a>{' '}
or{' '}
<a href={pdfUrl} download className="text-primary hover:underline">
downloading the file
</a>.
</p>
</div>
</div>
);
}

View File

@ -0,0 +1,46 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const badgeVariants = cva(
"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
secondary:
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
destructive:
"border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
)
function Badge({
className,
variant,
asChild = false,
...props
}: React.ComponentProps<"span"> &
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
const Comp = asChild ? Slot : "span"
return (
<Comp
data-slot="badge"
className={cn(badgeVariants({ variant }), className)}
{...props}
/>
)
}
export { Badge, badgeVariants }

View File

@ -0,0 +1,62 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
"icon-sm": "size-8",
"icon-lg": "size-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
function Button({
className,
variant = "default",
size = "default",
asChild = false,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
}) {
const Comp = asChild ? Slot : "button"
return (
<Comp
data-slot="button"
data-variant={variant}
data-size={size}
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
}
export { Button, buttonVariants }

View File

@ -0,0 +1,92 @@
import * as React from "react"
import { cn } from "@/lib/utils"
function Card({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card"
className={cn(
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
className
)}
{...props}
/>
)
}
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-header"
className={cn(
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
className
)}
{...props}
/>
)
}
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-title"
className={cn("leading-none font-semibold", className)}
{...props}
/>
)
}
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-action"
className={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
)}
{...props}
/>
)
}
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-content"
className={cn("px-6", className)}
{...props}
/>
)
}
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-footer"
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
{...props}
/>
)
}
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
}

View File

@ -0,0 +1,255 @@
import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function DropdownMenu({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
}
function DropdownMenuPortal({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
return (
<DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
)
}
function DropdownMenuTrigger({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
return (
<DropdownMenuPrimitive.Trigger
data-slot="dropdown-menu-trigger"
{...props}
/>
)
}
function DropdownMenuContent({
className,
sideOffset = 4,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
return (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
className
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
)
}
function DropdownMenuGroup({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
return (
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
)
}
function DropdownMenuItem({
className,
inset,
variant = "default",
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean
variant?: "default" | "destructive"
}) {
return (
<DropdownMenuPrimitive.Item
data-slot="dropdown-menu-item"
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
/>
)
}
function DropdownMenuCheckboxItem({
className,
children,
checked,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
return (
<DropdownMenuPrimitive.CheckboxItem
data-slot="dropdown-menu-checkbox-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
checked={checked}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<CheckIcon className="size-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
)
}
function DropdownMenuRadioGroup({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
return (
<DropdownMenuPrimitive.RadioGroup
data-slot="dropdown-menu-radio-group"
{...props}
/>
)
}
function DropdownMenuRadioItem({
className,
children,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
return (
<DropdownMenuPrimitive.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<CircleIcon className="size-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
)
}
function DropdownMenuLabel({
className,
inset,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean
}) {
return (
<DropdownMenuPrimitive.Label
data-slot="dropdown-menu-label"
data-inset={inset}
className={cn(
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
className
)}
{...props}
/>
)
}
function DropdownMenuSeparator({
className,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
return (
<DropdownMenuPrimitive.Separator
data-slot="dropdown-menu-separator"
className={cn("bg-border -mx-1 my-1 h-px", className)}
{...props}
/>
)
}
function DropdownMenuShortcut({
className,
...props
}: React.ComponentProps<"span">) {
return (
<span
data-slot="dropdown-menu-shortcut"
className={cn(
"text-muted-foreground ml-auto text-xs tracking-widest",
className
)}
{...props}
/>
)
}
function DropdownMenuSub({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
}
function DropdownMenuSubTrigger({
className,
inset,
children,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean
}) {
return (
<DropdownMenuPrimitive.SubTrigger
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto size-4" />
</DropdownMenuPrimitive.SubTrigger>
)
}
function DropdownMenuSubContent({
className,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
return (
<DropdownMenuPrimitive.SubContent
data-slot="dropdown-menu-sub-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
className
)}
{...props}
/>
)
}
export {
DropdownMenu,
DropdownMenuPortal,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuLabel,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
}

View File

@ -0,0 +1,66 @@
"use client"
import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs"
import { cn } from "@/lib/utils"
function Tabs({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot="tabs"
className={cn("flex flex-col gap-2", className)}
{...props}
/>
)
}
function TabsList({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.List>) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
className={cn(
"bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
className
)}
{...props}
/>
)
}
function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
/>
)
}
function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn("flex-1 outline-none", className)}
{...props}
/>
)
}
export { Tabs, TabsList, TabsTrigger, TabsContent }

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: 555 Timer IC Circuits"
shortTitle: "555 Timer Circuits"
collection: "mims"
year: 1986
description: "Everything about the legendary 555 timer IC. Monostable and astable modes, pulse generators, oscillators, and creative timing applications."
topics: ["555-timer", "oscillators", "timing", "integrated-circuits"]
archiveOrgId: "electronics_-_Forrest_Mims-engineers_mini-notebook_555_timer_circuits_radio_sha"
archiveOrgUrl: "https://archive.org/details/electronics_-_Forrest_Mims-engineers_mini-notebook_555_timer_circuits_radio_sha"
localPdf: "/pdfs/mims/03_555_Timer_Circuits.pdf"
coverImage: "/covers/mims/03_555_Timer_Circuits-01.jpg"
sortOrder: 3
formats:
- type: "PDF"
filename: "03_555_Timer_Circuits.pdf"
- type: "DjVu"
filename: "electronics - Forrest Mims-engineer's mini-notebook 555 timer circuits (radio shack electronics).djvu"
---
The 555 timer is one of the most versatile ICs ever made. This notebook shows you dozens of ways to use it, from simple LED blinkers to complex timing circuits.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Basic Semiconductor Circuits (1993 Edition)"
shortTitle: "Semiconductors (1993)"
collection: "mims"
year: 1993
description: "Revised 1993 edition with updated component values and additional circuits. Reflects improvements in semiconductor technology over 7 years."
topics: ["semiconductors", "transistors", "diodes", "updated"]
archiveOrgId: "Radio_Shack_Engineers_Mini-Notebook_-_Basic_Semiconductor_Circuits_-_F._Mims_19"
archiveOrgUrl: "https://archive.org/details/Radio_Shack_Engineers_Mini-Notebook_-_Basic_Semiconductor_Circuits_-_F._Mims_19"
localPdf: "/pdfs/mims/11_Basic_Semiconductor_1993.pdf"
coverImage: "/covers/mims/11_Basic_Semiconductor_1993-01.jpg"
sortOrder: 11
formats:
- type: "PDF"
filename: "11_Basic_Semiconductor_1993.pdf"
- type: "DjVu"
filename: "Radio Shack Engineer's Mini-Notebook - Basic Semiconductor Circuits - F. Mims (1993) WW.djvu"
---
The updated 1993 edition of the semiconductor basics notebook. Seven years of refinement produced improved circuits and clearer explanations.

View File

@ -0,0 +1,22 @@
---
title: "Engineer's Mini-Notebook: Basic Semiconductor Circuits"
shortTitle: "Basic Semiconductor Circuits"
collection: "mims"
year: 1986
description: "Fundamental transistor and diode circuits with Mims' signature hand-drawn illustrations. Covers NPN/PNP transistors, rectifiers, voltage regulators, and basic amplifier configurations."
topics: ["semiconductors", "transistors", "diodes", "amplifiers"]
archiveOrgId: "electronics_-_Forrest_Mims-engineers_mini-notebook_basic_semiconductor_circuits_"
archiveOrgUrl: "https://archive.org/details/electronics_-_Forrest_Mims-engineers_mini-notebook_basic_semiconductor_circuits_"
localPdf: "/pdfs/mims/01_Basic_Semiconductor_Circuits.pdf"
coverImage: "/covers/mims/01_Basic_Semiconductor_Circuits-01.jpg"
sortOrder: 1
formats:
- type: "PDF"
filename: "01_Basic_Semiconductor_Circuits.pdf"
- type: "DjVu"
filename: "electronics - Forrest Mims-engineer's mini-notebook basic semiconductor circuits (radio shack electronics).djvu"
- type: "Text"
filename: "electronics - Forrest Mims-engineer's mini-notebook basic semiconductor circuits (radio shack electronics)_djvu.txt"
---
The foundational notebook covering transistor basics, diode applications, and simple semiconductor circuits. Perfect for beginners learning the fundamentals of solid-state electronics.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Communications Projects"
shortTitle: "Communications Projects"
collection: "mims"
year: 1986
description: "Radio and communications circuits including transmitters, receivers, modulators, and antenna projects. Great for amateur radio enthusiasts and experimenters."
topics: ["communications", "radio", "transmitters", "receivers"]
archiveOrgId: "Forrest_Mims-Engineers_Mini-Notebook_-_Communications_Projects_Radio_Shack_Elec"
archiveOrgUrl: "https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_-_Communications_Projects_Radio_Shack_Elec"
localPdf: "/pdfs/mims/05_Communications_Projects.pdf"
coverImage: "/covers/mims/05_Communications_Projects-01.jpg"
sortOrder: 5
formats:
- type: "PDF"
filename: "05_Communications_Projects.pdf"
- type: "DjVu"
filename: "Forrest Mims-Engineer's Mini-Notebook - Communications Projects (Radio Shack Electronics).djvu"
---
Build your own radio circuits! From simple crystal radios to FM transmitters and receivers, this notebook covers the fundamentals of wireless communication.

View File

@ -0,0 +1,24 @@
---
title: "Engineer's Notebook II: A Handbook of Integrated Circuit Applications"
shortTitle: "Engineer's Notebook II"
collection: "mims"
year: 1982
description: "The foundational handbook covering integrated circuit applications. Features Mims' iconic hand-drawn schematics for op-amps, timers, audio circuits, power supplies, and dozens of practical IC projects."
topics: ["integrated circuits", "op-amps", "IC applications", "handbook"]
archiveOrgId: "ENGINEERSNOTEBOOKII"
archiveOrgUrl: "https://archive.org/details/ENGINEERSNOTEBOOKII"
localPdf: "/pdfs/mims/Engineers_Notebook_II_IC_Applications.pdf"
coverImage: "/covers/mims/Engineers_Notebook_II_IC_Applications-01.jpg"
sortOrder: 1
formats:
- type: "PDF"
filename: "Engineers_Notebook_II_IC_Applications.pdf"
- type: "EPUB"
filename: "ENGINEERS_NOTEBOOK_II.epub"
---
Engineer's Notebook II is one of the foundational volumes in Forrest Mims' legendary series. Published in 1982, this handbook focuses on practical integrated circuit applications with Mims' signature hand-drawn schematics.
The book covers a wide range of IC applications including operational amplifiers, 555 timers, audio circuits, power supply designs, and many more practical projects. Each circuit is accompanied by clear explanations and component values, making it easy to build and experiment.
This is essential reading for anyone interested in understanding how integrated circuits work and how to use them in real-world applications.

View File

@ -0,0 +1,22 @@
---
title: "Engineer's Mini-Notebook: Environmental Projects"
shortTitle: "Environmental Projects"
collection: "mims"
year: 1990
description: "Electronics projects for environmental monitoring and measurement. Covers temperature sensors, humidity detectors, rain gauges, light meters, and other circuits for observing and measuring the natural world."
topics: ["environmental", "sensors", "monitoring", "projects"]
archiveOrgId: "engineers-mini-notebook-555-timer-circuits"
archiveOrgUrl: "https://archive.org/details/engineers-mini-notebook-555-timer-circuits"
localPdf: "/pdfs/mims/Engineers_Mini_Notebook_Environmental_Projects.pdf"
coverImage: "/covers/mims/Engineers_Mini_Notebook_Environmental_Projects-01.jpg"
sortOrder: 14
formats:
- type: "PDF"
filename: "Engineers_Mini_Notebook_Environmental_Projects.pdf"
---
This Mini-Notebook focuses on electronics projects for environmental monitoring - a fascinating intersection of electronics and nature observation.
Projects include temperature measurement circuits, humidity sensors, rain detectors, light intensity meters, wind speed indicators, and more. Each project is designed to be buildable with commonly available components and includes Mims' characteristic clear hand-drawn schematics.
Perfect for makers interested in weather stations, environmental science, or outdoor monitoring applications.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Formulas, Tables & Basic Circuits"
shortTitle: "Formulas & Tables"
collection: "mims"
year: 1986
description: "Essential reference of electronics formulas, component values, schematic symbols, and fundamental circuits. The perfect pocket reference for any electronics workbench."
topics: ["reference", "formulas", "schematic-symbols", "fundamentals"]
archiveOrgId: "Forrest_Mims-Engineers_Mini-Notebook_Formulas_Tables_Basic_Circuits_Radio_Shack"
archiveOrgUrl: "https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Formulas_Tables_Basic_Circuits_Radio_Shack"
localPdf: "/pdfs/mims/04_Formulas_Tables_Basic_Circuits.pdf"
coverImage: "/covers/mims/04_Formulas_Tables_Basic_Circuits-01.jpg"
sortOrder: 4
formats:
- type: "PDF"
filename: "04_Formulas_Tables_Basic_Circuits.pdf"
- type: "DjVu"
filename: "Forrest Mims-Engineer's Mini-Notebook Formulas Tables Basic Circuits (Radio Shack Electronics).djvu"
---
The ultimate pocket reference. Ohm's Law, resistor color codes, capacitor values, schematic symbols, and dozens of basic circuits - all in Mims' clear, hand-drawn style.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Magnet and Sensor Projects"
shortTitle: "Magnet & Sensor Projects"
collection: "mims"
year: 1986
description: "Magnetic sensing and related projects. Hall effect sensors, reed switches, magnetic field detectors, and creative magnet-based circuits."
topics: ["magnets", "hall-effect", "sensors", "magnetic-fields"]
archiveOrgId: "Forrest_Mims-Engineers_Mini-Notebook_Magnet_And_Sensor_Projects_Radio_Shack_Ele"
archiveOrgUrl: "https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Magnet_And_Sensor_Projects_Radio_Shack_Ele"
localPdf: "/pdfs/mims/09_Magnet_And_Sensor_Projects.pdf"
coverImage: "/covers/mims/09_Magnet_And_Sensor_Projects-01.jpg"
sortOrder: 9
formats:
- type: "PDF"
filename: "09_Magnet_And_Sensor_Projects.pdf"
- type: "DjVu"
filename: "Forrest Mims-Engineer's Mini-Notebook Magnet And Sensor Projects (Radio Shack Electronics).djvu"
---
Magnets and electronics make a powerful combination. Build magnetic field detectors, proximity sensors, and position sensing circuits.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Op Amp IC Circuits (1985 Edition)"
shortTitle: "Op Amps (1985)"
collection: "mims"
year: 1985
description: "The original 1985 first printing of the Op Amp notebook. Features the earliest versions of Mims' iconic operational amplifier circuits."
topics: ["op-amps", "integrated-circuits", "amplifiers", "vintage"]
archiveOrgId: "Radio_Shack_Engineers_Mini-Notebook_-_Op_Amp_IC_Circuits_-_F._Mims_1985_WW"
archiveOrgUrl: "https://archive.org/details/Radio_Shack_Engineers_Mini-Notebook_-_Op_Amp_IC_Circuits_-_F._Mims_1985_WW"
localPdf: "/pdfs/mims/12_Op_Amp_IC_1985.pdf"
coverImage: "/covers/mims/12_Op_Amp_IC_1985-01.jpg"
sortOrder: 12
formats:
- type: "PDF"
filename: "12_Op_Amp_IC_1985.pdf"
- type: "DjVu"
filename: "Radio Shack Engineer's Mini-Notebook - Op Amp IC Circuits - F. Mims (1985) WW.djvu"
---
The first edition from 1985 - where it all began for the Op Amp notebook. A piece of electronics education history.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Op Amp IC Circuits"
shortTitle: "Op Amp IC Circuits"
collection: "mims"
year: 1986
description: "Comprehensive guide to operational amplifier circuits. Covers inverting/non-inverting amplifiers, comparators, integrators, differentiators, and practical applications."
topics: ["op-amps", "integrated-circuits", "amplifiers", "analog"]
archiveOrgId: "Forrest_Mims-Engineers_Mini-Notebook_Op_Amp_Ic_Circuits_Radio_Shack_Electronics"
archiveOrgUrl: "https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Op_Amp_Ic_Circuits_Radio_Shack_Electronics"
localPdf: "/pdfs/mims/02_Op_Amp_IC_Circuits.pdf"
coverImage: "/covers/mims/02_Op_Amp_IC_Circuits-01.jpg"
sortOrder: 2
formats:
- type: "PDF"
filename: "02_Op_Amp_IC_Circuits.pdf"
- type: "DjVu"
filename: "Forrest Mims-Engineer's Mini-Notebook Op Amp Ic Circuits (Radio Shack Electronics)(1).djvu"
---
Master the versatile operational amplifier with circuits ranging from simple gain stages to precision instrumentation amplifiers.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Optoelectronic Circuits (1986 Edition)"
shortTitle: "Optoelectronics (1986)"
collection: "mims"
year: 1986
description: "Earlier edition of the optoelectronics notebook with additional content and variations. A collector's edition with unique circuits."
topics: ["optoelectronics", "LEDs", "phototransistors", "vintage"]
archiveOrgId: "Radio_Shack_Engineers_Mini-Notebook_-_Optoelectronic_Circuits_-_F._Mims_1986_W"
archiveOrgUrl: "https://archive.org/details/Radio_Shack_Engineers_Mini-Notebook_-_Optoelectronic_Circuits_-_F._Mims_1986_W"
localPdf: "/pdfs/mims/10_Optoelectronic_Circuits_1986.pdf"
coverImage: "/covers/mims/10_Optoelectronic_Circuits_1986-01.jpg"
sortOrder: 10
formats:
- type: "PDF"
filename: "10_Optoelectronic_Circuits_1986.pdf"
- type: "DjVu"
filename: "Radio Shack Engineer's Mini-Notebook - Optoelectronic Circuits - F. Mims (1986) WW.djvu"
---
The original 1986 printing of the optoelectronics notebook. Compare with the later edition to see how Mims refined his presentations.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Optoelectronics Circuits"
shortTitle: "Optoelectronics Circuits"
collection: "mims"
year: 1986
description: "Light-based electronics including LEDs, phototransistors, optocouplers, fiber optics, and laser circuits. The intersection of light and electronics."
topics: ["optoelectronics", "LEDs", "phototransistors", "fiber-optics"]
archiveOrgId: "Forrest_Mims-Engineers_Mini-Notebook_Optoelectronics_Circuits_Radio_Shack_Elect"
archiveOrgUrl: "https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Optoelectronics_Circuits_Radio_Shack_Elect"
localPdf: "/pdfs/mims/07_Optoelectronics_Circuits.pdf"
coverImage: "/covers/mims/07_Optoelectronics_Circuits-01.jpg"
sortOrder: 7
formats:
- type: "PDF"
filename: "07_Optoelectronics_Circuits.pdf"
- type: "DjVu"
filename: "Forrest Mims-Engineer's Mini-Notebook Optoelectronics Circuits (Radio Shack Electronics).djvu"
---
LEDs, lasers, and light sensors come alive in this notebook. Build everything from simple LED drivers to sophisticated light-based communication systems.

View File

@ -0,0 +1,22 @@
---
title: "Engineer's Mini-Notebook: Schematic Symbols, Device Packages, Design & Testing"
shortTitle: "Schematic Symbols & Testing"
collection: "mims"
year: 1988
description: "Essential reference for reading and drawing electronic schematics. Covers standard schematic symbols, component package types, circuit design basics, and testing procedures with hand-drawn clarity."
topics: ["schematic symbols", "reference", "design", "testing"]
archiveOrgId: "engineers-mini-notebook-555-timer-circuits"
archiveOrgUrl: "https://archive.org/details/engineers-mini-notebook-555-timer-circuits"
localPdf: "/pdfs/mims/Engineers_Mini_Notebook_Schematic_Symbols.pdf"
coverImage: "/covers/mims/Engineers_Mini_Notebook_Schematic_Symbols-01.jpg"
sortOrder: 15
formats:
- type: "PDF"
filename: "Engineers_Mini_Notebook_Schematic_Symbols.pdf"
---
This Mini-Notebook is an essential reference for anyone learning to read or draw electronic schematics. It provides a comprehensive guide to standard schematic symbols used in circuit diagrams.
Beyond symbols, the book covers common component package types (DIPs, TO-92, etc.), basic circuit design principles, and testing procedures for verifying circuit operation. This is the kind of foundational knowledge that every electronics hobbyist needs.
Keep this one handy on your workbench - you'll reference it constantly when building circuits from schematics or designing your own.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Sensor Projects"
shortTitle: "Sensor Projects"
collection: "mims"
year: 1986
description: "Interface with the physical world using sensors. Temperature, light, sound, touch, and motion sensors with practical circuits for each."
topics: ["sensors", "temperature", "light-sensing", "interfacing"]
archiveOrgId: "Forrest_Mims-engineers_mini-notebook_sensor_projects_radio_shack_electronics"
archiveOrgUrl: "https://archive.org/details/Forrest_Mims-engineers_mini-notebook_sensor_projects_radio_shack_electronics"
localPdf: "/pdfs/mims/08_Sensor_Projects.pdf"
coverImage: "/covers/mims/08_Sensor_Projects-01.jpg"
sortOrder: 8
formats:
- type: "PDF"
filename: "08_Sensor_Projects.pdf"
- type: "DjVu"
filename: "Forrest Mims-engineer's mini-notebook sensor projects (radio shack electronics).djvu"
---
Sensors let your circuits interact with the real world. This notebook covers thermistors, photocells, microphones, and more - essential for any maker project.

View File

@ -0,0 +1,20 @@
---
title: "Engineer's Mini-Notebook: Solar Cell Projects"
shortTitle: "Solar Cell Projects"
collection: "mims"
year: 1986
description: "Harness the sun with photovoltaic circuits. Solar battery chargers, light meters, solar-powered gadgets, and energy harvesting projects."
topics: ["solar", "photovoltaic", "energy", "green-tech"]
archiveOrgId: "Forrest_Mims-Engineers_Mini-Notebook_Solar_Cell_Projects_Radio_Shack_Electronic"
archiveOrgUrl: "https://archive.org/details/Forrest_Mims-Engineers_Mini-Notebook_Solar_Cell_Projects_Radio_Shack_Electronic"
localPdf: "/pdfs/mims/06_Solar_Cell_Projects.pdf"
coverImage: "/covers/mims/06_Solar_Cell_Projects-01.jpg"
sortOrder: 6
formats:
- type: "PDF"
filename: "06_Solar_Cell_Projects.pdf"
- type: "DjVu"
filename: "Forrest Mims-Engineer's Mini-Notebook Solar Cell Projects (Radio Shack Electronics).djvu"
---
Solar power was cutting-edge in the 80s, and Mims was ahead of his time. Learn to build solar-powered circuits that are still relevant today.

View File

@ -0,0 +1,22 @@
---
title: "Ugly's Electrical References (2005 Edition)"
shortTitle: "Ugly's Electrical References"
collection: "uglys"
year: 2005
description: "The pocket-sized bible for electricians. Packed with tables, formulas, wiring diagrams, NEC code references, and quick calculations for electrical work. An essential field reference."
topics: ["electrical", "wiring", "NEC-code", "reference", "formulas"]
archiveOrgId: "Ugly_sElectricalReference2005"
archiveOrgUrl: "https://archive.org/details/Ugly_sElectricalReference2005"
localPdf: "/pdfs/uglys/Uglys_Electrical_Reference_2005.pdf"
coverImage: "/covers/uglys/Uglys_Electrical_Reference_2005-01.jpg"
sortOrder: 1
formats:
- type: "PDF"
filename: "Uglys_Electrical_Reference_2005.pdf"
- type: "PDF (Text)"
filename: "Ugly_sElectricalReference2005_text.pdf"
---
Ugly's Electrical References has been the go-to pocket reference for electricians since 1970. This spiral-bound guide fits in your back pocket and contains everything you need on the job site - wire ampacities, conduit fill tables, motor calculations, NEC code references, and much more.
Like the Mims notebooks, this is another example of practical, no-nonsense reference material that gets the job done.

View File

@ -0,0 +1,28 @@
import { defineCollection, z } from 'astro:content';
const booksCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
shortTitle: z.string(),
collection: z.enum(['mims', 'uglys', 'other']),
year: z.number().optional(),
description: z.string(),
topics: z.array(z.string()),
archiveOrgId: z.string().optional(),
archiveOrgUrl: z.string().url().optional(),
localPdf: z.string(),
coverImage: z.string().optional(),
pageCount: z.number().optional(),
sortOrder: z.number().default(0),
formats: z.array(z.object({
type: z.string(),
filename: z.string(),
url: z.string().optional()
})).optional()
})
});
export const collections = {
books: booksCollection
};

View File

@ -0,0 +1,86 @@
---
import '@/styles/global.css';
interface Props {
title: string;
description?: string;
}
const { title, description = "Classic electronics reference notebooks from Forrest M. Mims III" } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content={description} />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>{title} | Electronics Reference Library</title>
</head>
<body class="min-h-screen graph-paper-large">
<header class="border-b border-border bg-card/80 backdrop-blur-sm sticky top-0 z-50">
<div class="container mx-auto px-4 py-4">
<nav class="flex items-center justify-between">
<a href="/" class="flex items-center gap-3 hover:opacity-80 transition-opacity">
<div class="w-10 h-10 rounded-lg bg-primary flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-primary-foreground">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
</div>
<div>
<h1 class="text-lg font-semibold title-accent text-foreground">Electronics Library</h1>
<p class="text-xs text-muted-foreground">Classic Reference Collection</p>
</div>
</a>
<div class="flex items-center gap-4">
<a
href="/mims"
class="text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
>
Mims
</a>
<a
href="/uglys"
class="text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
>
Ugly's
</a>
<a
href="https://archive.org"
target="_blank"
rel="noopener noreferrer"
class="text-sm font-medium text-muted-foreground hover:text-foreground transition-colors flex items-center gap-1"
>
Archive.org
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" x2="21" y1="14" y2="3"/>
</svg>
</a>
</div>
</nav>
</div>
</header>
<main class="container mx-auto px-4 py-8">
<slot />
</main>
<footer class="border-t border-border bg-card/50 mt-16">
<div class="container mx-auto px-4 py-8">
<div class="flex flex-col md:flex-row items-center justify-between gap-4 text-sm text-muted-foreground">
<p>
Preserving classic electronics and electrical references
</p>
<p>
Materials sourced from <a href="https://archive.org" target="_blank" rel="noopener noreferrer" class="underline hover:text-foreground">Archive.org</a>
</p>
</div>
</div>
</footer>
</body>
</html>

6
site/src/lib/utils.ts Normal file
View File

@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

256
site/src/pages/index.astro Normal file
View File

@ -0,0 +1,256 @@
---
import Layout from '@/layouts/Layout.astro';
import BookGrid from '@/components/BookGrid.astro';
import { getCollection } from 'astro:content';
const allBooks = await getCollection('books');
const mimsBooks = allBooks
.filter(book => book.data.collection === 'mims')
.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
const uglysBooks = allBooks
.filter(book => book.data.collection === 'uglys')
.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
const featuredMimsBooks = mimsBooks.slice(0, 4);
const totalBooks = allBooks.length;
---
<Layout title="Home">
<!-- Hero Section -->
<section class="text-center py-12 space-y-6">
<div class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-accent/20 text-accent-foreground text-sm font-medium">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
</svg>
Classic Electronics & Electrical Education
</div>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold title-accent max-w-4xl mx-auto leading-tight">
The Hand-Drawn References That
<span class="text-primary">Taught Generations</span>
</h1>
<p class="text-lg text-muted-foreground max-w-2xl mx-auto">
Rediscover legendary electronics and electrical references. From Forrest Mims' hand-illustrated
circuit notebooks to Ugly's essential electrician's guides - timeless knowledge preserved digitally.
</p>
<div class="flex flex-wrap items-center justify-center gap-4 pt-4">
<a
href="#collections"
class="inline-flex items-center gap-2 px-6 py-3 bg-primary text-primary-foreground rounded-lg font-medium hover:bg-primary/90 transition-colors"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
Browse Collections
</a>
<a
href="https://archive.org"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center gap-2 px-6 py-3 border border-border text-foreground rounded-lg font-medium hover:bg-muted transition-colors"
>
About Archive.org
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" x2="21" y1="14" y2="3"/>
</svg>
</a>
</div>
</section>
<!-- Stats -->
<section class="grid grid-cols-2 md:grid-cols-4 gap-4 py-8">
<div class="text-center p-6 rounded-lg bg-card border border-border">
<div class="text-3xl font-bold text-primary">{totalBooks}</div>
<div class="text-sm text-muted-foreground">References</div>
</div>
<div class="text-center p-6 rounded-lg bg-card border border-border">
<div class="text-3xl font-bold text-primary">2</div>
<div class="text-sm text-muted-foreground">Collections</div>
</div>
<div class="text-center p-6 rounded-lg bg-card border border-border">
<div class="text-3xl font-bold text-primary">100+</div>
<div class="text-sm text-muted-foreground">Circuit Projects</div>
</div>
<div class="text-center p-6 rounded-lg bg-card border border-border">
<div class="text-3xl font-bold text-primary">Free</div>
<div class="text-sm text-muted-foreground">PDF Downloads</div>
</div>
</section>
<!-- Collection Cards -->
<section id="collections" class="py-12 scroll-mt-8">
<h2 class="text-2xl font-bold title-accent text-center mb-8">Our Collections</h2>
<div class="grid md:grid-cols-2 gap-6">
<!-- Mims Collection Card -->
<a href="/mims" class="group block p-6 rounded-lg bg-card border border-border hover:border-primary/50 transition-all hover:shadow-lg">
<div class="flex items-start gap-4">
<div class="w-14 h-14 rounded-lg bg-primary/10 flex items-center justify-center shrink-0 group-hover:bg-primary/20 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-primary">
<path d="M12 20h9"/>
<path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
</svg>
</div>
<div class="flex-1">
<div class="flex items-center justify-between">
<h3 class="text-xl font-semibold group-hover:text-primary transition-colors">Forrest Mims Mini-Notebooks</h3>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground group-hover:text-primary transition-colors">
<polyline points="9 18 15 12 9 6"/>
</svg>
</div>
<p class="text-sm text-muted-foreground mt-1">
The legendary Radio Shack Engineer's Mini-Notebook series. Hand-illustrated electronics
education that taught a generation.
</p>
<div class="flex items-center gap-4 mt-4 text-xs text-muted-foreground">
<span class="flex items-center gap-1">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
{mimsBooks.length} notebooks
</span>
<span>1985-1993</span>
</div>
</div>
</div>
</a>
<!-- Ugly's Collection Card -->
<a href="/uglys" class="group block p-6 rounded-lg bg-card border border-border hover:border-chart-2/50 transition-all hover:shadow-lg">
<div class="flex items-start gap-4">
<div class="w-14 h-14 rounded-lg bg-chart-2/10 flex items-center justify-center shrink-0 group-hover:bg-chart-2/20 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-chart-2">
<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>
</svg>
</div>
<div class="flex-1">
<div class="flex items-center justify-between">
<h3 class="text-xl font-semibold group-hover:text-chart-2 transition-colors">Ugly's Electrical References</h3>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground group-hover:text-chart-2 transition-colors">
<polyline points="9 18 15 12 9 6"/>
</svg>
</div>
<p class="text-sm text-muted-foreground mt-1">
The pocket-sized bible for electricians. Packed with tables, formulas, wiring diagrams,
and NEC code references.
</p>
<div class="flex items-center gap-4 mt-4 text-xs text-muted-foreground">
<span class="flex items-center gap-1">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
{uglysBooks.length} reference{uglysBooks.length !== 1 ? 's' : ''}
</span>
<span>Since 1970</span>
</div>
</div>
</div>
</a>
</div>
</section>
<!-- Featured Mims Collection -->
<section class="py-8">
<div class="flex items-center justify-between mb-6">
<div>
<h2 class="text-2xl font-bold title-accent">Featured: Mims Mini-Notebooks</h2>
<p class="text-muted-foreground">Hand-illustrated electronics that shaped a generation</p>
</div>
<a
href="/mims"
class="text-sm font-medium text-primary hover:underline flex items-center gap-1"
>
View all {mimsBooks.length} notebooks
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
</a>
</div>
<BookGrid books={featuredMimsBooks} />
</section>
<!-- About Section -->
<section class="py-12 mt-8 border-t border-border">
<div class="grid md:grid-cols-2 gap-8 items-center">
<div class="space-y-4">
<h2 class="text-2xl font-bold title-accent">Preserving Electronics Heritage</h2>
<p class="text-muted-foreground leading-relaxed">
These references represent the golden age of hands-on electronics education. From Forrest Mims'
distinctive hand-drawn notebooks that taught millions through Radio Shack, to Ugly's practical
field guides trusted by electricians everywhere.
</p>
<p class="text-muted-foreground leading-relaxed">
What makes these works special is their approach: clear explanations, practical focus, and
a personal touch that made complex concepts accessible. Many engineers credit these materials
with sparking their interest in electronics - reading them under the covers with a flashlight,
building circuits on breadboards, learning schematic symbols for the first time.
</p>
<p class="text-muted-foreground leading-relaxed">
All materials have been preserved and made available through Archive.org. Click any item
to view it with our embedded PDF reader, or download it in various formats.
</p>
</div>
<div class="circuit-border p-6 bg-card">
<div class="space-y-4">
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded bg-chart-1/20 flex items-center justify-center shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-chart-1">
<path d="M12 20h9"/>
<path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
</svg>
</div>
<div>
<h4 class="font-semibold">Hand-Illustrated</h4>
<p class="text-sm text-muted-foreground">Every diagram drawn by hand with meticulous care</p>
</div>
</div>
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded bg-accent/20 flex items-center justify-center shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-accent">
<circle cx="12" cy="12" r="10"/>
<polyline points="12 6 12 12 16 14"/>
</svg>
</div>
<div>
<h4 class="font-semibold">Timeless Knowledge</h4>
<p class="text-sm text-muted-foreground">Fundamentals that remain relevant decades later</p>
</div>
</div>
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded bg-primary/20 flex items-center justify-center shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-primary">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
</svg>
</div>
<div>
<h4 class="font-semibold">Practical Projects</h4>
<p class="text-sm text-muted-foreground">Real circuits you can build and learn from</p>
</div>
</div>
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded bg-chart-2/20 flex items-center justify-center shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-chart-2">
<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>
</svg>
</div>
<div>
<h4 class="font-semibold">Field-Ready</h4>
<p class="text-sm text-muted-foreground">Pocket references built for real-world use</p>
</div>
</div>
</div>
</div>
</div>
</section>
</Layout>

View File

@ -0,0 +1,181 @@
---
import Layout from '@/layouts/Layout.astro';
import { Badge } from '@/components/ui/badge';
import EBookReader from '@/components/EBookReader';
import { getCollection, type CollectionEntry } from 'astro:content';
export async function getStaticPaths() {
const books = await getCollection('books');
return books
.filter(book => book.data.collection === 'mims')
.map(book => ({
params: { slug: book.slug.split('/').pop() },
props: { book }
}));
}
interface Props {
book: CollectionEntry<'books'>;
}
const { book } = Astro.props;
const { title, shortTitle, description, topics, localPdf, coverImage, year, archiveOrgUrl, formats } = book.data;
// Get all mims books for navigation
const allBooks = await getCollection('books');
const mimsBooks = allBooks
.filter(b => b.data.collection === 'mims')
.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
const currentIndex = mimsBooks.findIndex(b => b.slug === book.slug);
const prevBook = currentIndex > 0 ? mimsBooks[currentIndex - 1] : null;
const nextBook = currentIndex < mimsBooks.length - 1 ? mimsBooks[currentIndex + 1] : null;
---
<Layout title={shortTitle} description={description}>
<div class="space-y-8">
<!-- Breadcrumb -->
<div class="flex items-center gap-2 text-sm text-muted-foreground">
<a href="/" class="hover:text-foreground transition-colors">Home</a>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
<a href="/mims" class="hover:text-foreground transition-colors">Mims Collection</a>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
<span class="text-foreground">{shortTitle}</span>
</div>
<!-- Compact Header -->
<div class="flex flex-col md:flex-row md:items-start gap-6">
<!-- Book Info -->
<div class="flex-1 space-y-4">
<div>
{year && (
<div class="inline-flex items-center gap-2 text-sm text-muted-foreground mb-2">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect width="18" height="18" x="3" y="4" rx="2" ry="2"/>
<line x1="16" x2="16" y1="2" y2="6"/>
<line x1="8" x2="8" y1="2" y2="6"/>
<line x1="3" x2="21" y1="10" y2="10"/>
</svg>
Published {year}
</div>
)}
<h1 class="text-2xl md:text-3xl font-bold title-accent">{title}</h1>
<p class="text-muted-foreground mt-2">{description}</p>
</div>
<div class="flex flex-wrap gap-2">
{topics.slice(0, 5).map((topic) => (
<Badge variant="secondary" className="text-xs">
{topic.replace(/-/g, ' ')}
</Badge>
))}
{topics.length > 5 && (
<Badge variant="outline" className="text-xs">
+{topics.length - 5} more
</Badge>
)}
</div>
</div>
<!-- Quick Actions -->
<div class="flex flex-row md:flex-col gap-2">
<a
href={localPdf}
download
class="inline-flex items-center justify-center gap-2 px-4 py-2.5 bg-primary text-primary-foreground rounded-lg font-medium hover:bg-primary/90 transition-colors text-sm"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" x2="12" y1="15" y2="3"/>
</svg>
<span>Download</span>
</a>
{archiveOrgUrl && (
<a
href={archiveOrgUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center gap-2 px-4 py-2.5 border border-border rounded-lg font-medium hover:bg-muted transition-colors text-sm"
>
<span>Archive.org</span>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" x2="21" y1="14" y2="3"/>
</svg>
</a>
)}
</div>
</div>
<!-- E-Book Reader -->
<div class="mt-6">
<EBookReader
pdfUrl={localPdf}
title={shortTitle}
coverImage={coverImage}
client:load
/>
</div>
<!-- Navigation -->
<div class="flex items-center justify-between pt-8 border-t border-border">
{prevBook ? (
<a
href={`/mims/${prevBook.slug.split('/').pop()}`}
class="group flex items-center gap-3 p-3 -m-3 rounded-lg hover:bg-muted/50 transition-colors"
>
<div class="w-8 h-8 rounded-full bg-muted flex items-center justify-center group-hover:bg-primary/10 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground group-hover:text-primary transition-colors">
<polyline points="15 18 9 12 15 6"/>
</svg>
</div>
<div class="text-left">
<div class="text-xs text-muted-foreground">Previous</div>
<div class="text-sm font-medium text-foreground hidden sm:block">{prevBook.data.shortTitle}</div>
</div>
</a>
) : (
<div></div>
)}
<a
href="/mims"
class="flex items-center gap-2 px-4 py-2 rounded-lg border border-border hover:bg-muted transition-colors text-sm"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect width="7" height="7" x="3" y="3" rx="1"/>
<rect width="7" height="7" x="14" y="3" rx="1"/>
<rect width="7" height="7" x="14" y="14" rx="1"/>
<rect width="7" height="7" x="3" y="14" rx="1"/>
</svg>
<span class="hidden sm:inline">All Notebooks</span>
</a>
{nextBook ? (
<a
href={`/mims/${nextBook.slug.split('/').pop()}`}
class="group flex items-center gap-3 p-3 -m-3 rounded-lg hover:bg-muted/50 transition-colors"
>
<div class="text-right">
<div class="text-xs text-muted-foreground">Next</div>
<div class="text-sm font-medium text-foreground hidden sm:block">{nextBook.data.shortTitle}</div>
</div>
<div class="w-8 h-8 rounded-full bg-muted flex items-center justify-center group-hover:bg-primary/10 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground group-hover:text-primary transition-colors">
<polyline points="9 18 15 12 9 6"/>
</svg>
</div>
</a>
) : (
<div></div>
)}
</div>
</div>
</Layout>

View File

@ -0,0 +1,85 @@
---
import Layout from '@/layouts/Layout.astro';
import BookGrid from '@/components/BookGrid.astro';
import { getCollection } from 'astro:content';
const allBooks = await getCollection('books');
const mimsBooks = allBooks
.filter(book => book.data.collection === 'mims')
.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
// Get unique topics for filtering
const allTopics = [...new Set(mimsBooks.flatMap(book => book.data.topics))].sort();
---
<Layout
title="Mims Mini-Notebooks"
description="The complete collection of Forrest M. Mims III's Radio Shack Engineer's Mini-Notebooks"
>
<div class="space-y-8">
<!-- Header -->
<div class="space-y-4">
<div class="flex items-center gap-2 text-sm text-muted-foreground">
<a href="/" class="hover:text-foreground transition-colors">Home</a>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
<span>Mims Collection</span>
</div>
<div class="flex flex-col md:flex-row md:items-end justify-between gap-4">
<div>
<h1 class="text-3xl md:text-4xl font-bold title-accent">
Forrest Mims Mini-Notebooks
</h1>
<p class="text-muted-foreground mt-2 max-w-2xl">
The complete Radio Shack Engineer's Mini-Notebook series. Hand-illustrated electronics
education that taught a generation of engineers and hobbyists.
</p>
</div>
<div class="flex items-center gap-2 text-sm text-muted-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
<span>{mimsBooks.length} notebooks</span>
</div>
</div>
</div>
<!-- Topic tags -->
<div class="flex flex-wrap gap-2">
{allTopics.map((topic) => (
<span class="px-3 py-1 text-xs font-medium rounded-full bg-muted text-muted-foreground">
{topic.replace(/-/g, ' ')}
</span>
))}
</div>
<!-- Grid -->
<BookGrid books={mimsBooks} />
<!-- Info box -->
<div class="mt-12 p-6 rounded-lg bg-card border border-border">
<div class="flex items-start gap-4">
<div class="w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-primary">
<circle cx="12" cy="12" r="10"/>
<line x1="12" x2="12" y1="16" y2="12"/>
<line x1="12" x2="12.01" y1="8" y2="8"/>
</svg>
</div>
<div>
<h3 class="font-semibold text-foreground">About This Collection</h3>
<p class="text-sm text-muted-foreground mt-1">
These notebooks were originally published by Radio Shack between 1985 and 1993.
All materials have been preserved and made available through Archive.org's
Folkscanomy project. Click any notebook to view it with our embedded PDF reader,
or download it in various formats.
</p>
</div>
</div>
</div>
</div>
</Layout>

View File

@ -0,0 +1,181 @@
---
import Layout from '@/layouts/Layout.astro';
import { Badge } from '@/components/ui/badge';
import EBookReader from '@/components/EBookReader';
import { getCollection, type CollectionEntry } from 'astro:content';
export async function getStaticPaths() {
const books = await getCollection('books');
return books
.filter(book => book.data.collection === 'uglys')
.map(book => ({
params: { slug: book.slug.split('/').pop() },
props: { book }
}));
}
interface Props {
book: CollectionEntry<'books'>;
}
const { book } = Astro.props;
const { title, shortTitle, description, topics, localPdf, coverImage, year, archiveOrgUrl, formats } = book.data;
// Get all uglys books for navigation
const allBooks = await getCollection('books');
const uglysBooks = allBooks
.filter(b => b.data.collection === 'uglys')
.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
const currentIndex = uglysBooks.findIndex(b => b.slug === book.slug);
const prevBook = currentIndex > 0 ? uglysBooks[currentIndex - 1] : null;
const nextBook = currentIndex < uglysBooks.length - 1 ? uglysBooks[currentIndex + 1] : null;
---
<Layout title={shortTitle} description={description}>
<div class="space-y-8">
<!-- Breadcrumb -->
<div class="flex items-center gap-2 text-sm text-muted-foreground">
<a href="/" class="hover:text-foreground transition-colors">Home</a>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
<a href="/uglys" class="hover:text-foreground transition-colors">Ugly's Collection</a>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
<span class="text-foreground">{shortTitle}</span>
</div>
<!-- Compact Header -->
<div class="flex flex-col md:flex-row md:items-start gap-6">
<!-- Book Info -->
<div class="flex-1 space-y-4">
<div>
{year && (
<div class="inline-flex items-center gap-2 text-sm text-muted-foreground mb-2">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect width="18" height="18" x="3" y="4" rx="2" ry="2"/>
<line x1="16" x2="16" y1="2" y2="6"/>
<line x1="8" x2="8" y1="2" y2="6"/>
<line x1="3" x2="21" y1="10" y2="10"/>
</svg>
{year} Edition
</div>
)}
<h1 class="text-2xl md:text-3xl font-bold title-accent">{title}</h1>
<p class="text-muted-foreground mt-2">{description}</p>
</div>
<div class="flex flex-wrap gap-2">
{topics.slice(0, 5).map((topic) => (
<Badge variant="secondary" className="text-xs">
{topic.replace(/-/g, ' ')}
</Badge>
))}
{topics.length > 5 && (
<Badge variant="outline" className="text-xs">
+{topics.length - 5} more
</Badge>
)}
</div>
</div>
<!-- Quick Actions -->
<div class="flex flex-row md:flex-col gap-2">
<a
href={localPdf}
download
class="inline-flex items-center justify-center gap-2 px-4 py-2.5 bg-primary text-primary-foreground rounded-lg font-medium hover:bg-primary/90 transition-colors text-sm"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" x2="12" y1="15" y2="3"/>
</svg>
<span>Download</span>
</a>
{archiveOrgUrl && (
<a
href={archiveOrgUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center gap-2 px-4 py-2.5 border border-border rounded-lg font-medium hover:bg-muted transition-colors text-sm"
>
<span>Archive.org</span>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>
<polyline points="15 3 21 3 21 9"/>
<line x1="10" x2="21" y1="14" y2="3"/>
</svg>
</a>
)}
</div>
</div>
<!-- E-Book Reader -->
<div class="mt-6">
<EBookReader
pdfUrl={localPdf}
title={shortTitle}
coverImage={coverImage}
client:load
/>
</div>
<!-- Navigation -->
<div class="flex items-center justify-between pt-8 border-t border-border">
{prevBook ? (
<a
href={`/uglys/${prevBook.slug.split('/').pop()}`}
class="group flex items-center gap-3 p-3 -m-3 rounded-lg hover:bg-muted/50 transition-colors"
>
<div class="w-8 h-8 rounded-full bg-muted flex items-center justify-center group-hover:bg-primary/10 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground group-hover:text-primary transition-colors">
<polyline points="15 18 9 12 15 6"/>
</svg>
</div>
<div class="text-left">
<div class="text-xs text-muted-foreground">Previous</div>
<div class="text-sm font-medium text-foreground hidden sm:block">{prevBook.data.shortTitle}</div>
</div>
</a>
) : (
<div></div>
)}
<a
href="/uglys"
class="flex items-center gap-2 px-4 py-2 rounded-lg border border-border hover:bg-muted transition-colors text-sm"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect width="7" height="7" x="3" y="3" rx="1"/>
<rect width="7" height="7" x="14" y="3" rx="1"/>
<rect width="7" height="7" x="14" y="14" rx="1"/>
<rect width="7" height="7" x="3" y="14" rx="1"/>
</svg>
<span class="hidden sm:inline">All References</span>
</a>
{nextBook ? (
<a
href={`/uglys/${nextBook.slug.split('/').pop()}`}
class="group flex items-center gap-3 p-3 -m-3 rounded-lg hover:bg-muted/50 transition-colors"
>
<div class="text-right">
<div class="text-xs text-muted-foreground">Next</div>
<div class="text-sm font-medium text-foreground hidden sm:block">{nextBook.data.shortTitle}</div>
</div>
<div class="w-8 h-8 rounded-full bg-muted flex items-center justify-center group-hover:bg-primary/10 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground group-hover:text-primary transition-colors">
<polyline points="9 18 15 12 9 6"/>
</svg>
</div>
</a>
) : (
<div></div>
)}
</div>
</div>
</Layout>

View File

@ -0,0 +1,86 @@
---
import Layout from '@/layouts/Layout.astro';
import BookGrid from '@/components/BookGrid.astro';
import { getCollection } from 'astro:content';
const allBooks = await getCollection('books');
const uglysBooks = allBooks
.filter(book => book.data.collection === 'uglys')
.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
// Get unique topics for filtering
const allTopics = [...new Set(uglysBooks.flatMap(book => book.data.topics))].sort();
---
<Layout
title="Ugly's Electrical References"
description="The essential pocket reference for electricians - packed with tables, formulas, and NEC code references"
>
<div class="space-y-8">
<!-- Header -->
<div class="space-y-4">
<div class="flex items-center gap-2 text-sm text-muted-foreground">
<a href="/" class="hover:text-foreground transition-colors">Home</a>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"/>
</svg>
<span>Ugly's Collection</span>
</div>
<div class="flex flex-col md:flex-row md:items-end justify-between gap-4">
<div>
<h1 class="text-3xl md:text-4xl font-bold title-accent">
Ugly's Electrical References
</h1>
<p class="text-muted-foreground mt-2 max-w-2xl">
The pocket-sized bible for electricians. Packed with tables, formulas, wiring diagrams,
NEC code references, and quick calculations for electrical work. An essential field reference.
</p>
</div>
<div class="flex items-center gap-2 text-sm text-muted-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
<span>{uglysBooks.length} reference{uglysBooks.length !== 1 ? 's' : ''}</span>
</div>
</div>
</div>
<!-- Topic tags -->
{allTopics.length > 0 && (
<div class="flex flex-wrap gap-2">
{allTopics.map((topic) => (
<span class="px-3 py-1 text-xs font-medium rounded-full bg-muted text-muted-foreground">
{topic.replace(/-/g, ' ')}
</span>
))}
</div>
)}
<!-- Grid -->
<BookGrid books={uglysBooks} />
<!-- Info box -->
<div class="mt-12 p-6 rounded-lg bg-card border border-border">
<div class="flex items-start gap-4">
<div class="w-10 h-10 rounded-lg bg-chart-2/20 flex items-center justify-center shrink-0">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-chart-2">
<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>
</svg>
</div>
<div>
<h3 class="font-semibold text-foreground">About This Collection</h3>
<p class="text-sm text-muted-foreground mt-1">
Ugly's Electrical References has been the go-to pocket reference for electricians since 1970.
This spiral-bound guide fits in your back pocket and contains everything you need on the
job site - wire ampacities, conduit fill tables, motor calculations, NEC code references,
and much more. Like the Mims notebooks, this is practical, no-nonsense reference material
that gets the job done.
</p>
</div>
</div>
</div>
</div>
</Layout>

196
site/src/styles/global.css Normal file
View File

@ -0,0 +1,196 @@
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--radius-2xl: calc(var(--radius) + 8px);
--radius-3xl: calc(var(--radius) + 12px);
--radius-4xl: calc(var(--radius) + 16px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
:root {
--radius: 0.625rem;
/* Warm cream paper background */
--background: oklch(0.97 0.01 85);
--foreground: oklch(0.25 0.02 250);
/* Card with slightly lighter cream */
--card: oklch(0.98 0.008 85);
--card-foreground: oklch(0.25 0.02 250);
--popover: oklch(0.98 0.008 85);
--popover-foreground: oklch(0.25 0.02 250);
/* Deep ink blue primary */
--primary: oklch(0.35 0.08 250);
--primary-foreground: oklch(0.98 0.008 85);
/* Muted cream secondary */
--secondary: oklch(0.94 0.015 85);
--secondary-foreground: oklch(0.30 0.03 250);
--muted: oklch(0.92 0.012 85);
--muted-foreground: oklch(0.50 0.02 250);
/* Warm amber accent */
--accent: oklch(0.75 0.15 65);
--accent-foreground: oklch(0.25 0.02 250);
--destructive: oklch(0.577 0.245 27.325);
/* Graph paper blue lines */
--border: oklch(0.85 0.04 230);
--input: oklch(0.90 0.02 85);
--ring: oklch(0.55 0.12 250);
/* Circuit board green for charts */
--chart-1: oklch(0.55 0.15 145);
--chart-2: oklch(0.65 0.12 250);
--chart-3: oklch(0.70 0.14 65);
--chart-4: oklch(0.60 0.10 30);
--chart-5: oklch(0.50 0.08 300);
--sidebar: oklch(0.96 0.012 85);
--sidebar-foreground: oklch(0.25 0.02 250);
--sidebar-primary: oklch(0.35 0.08 250);
--sidebar-primary-foreground: oklch(0.98 0.008 85);
--sidebar-accent: oklch(0.92 0.015 85);
--sidebar-accent-foreground: oklch(0.30 0.03 250);
--sidebar-border: oklch(0.85 0.04 230);
--sidebar-ring: oklch(0.55 0.12 250);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
/* Graph paper background pattern */
.graph-paper {
background-image:
linear-gradient(to right, oklch(0.85 0.03 230 / 0.3) 1px, transparent 1px),
linear-gradient(to bottom, oklch(0.85 0.03 230 / 0.3) 1px, transparent 1px);
background-size: 20px 20px;
}
.graph-paper-large {
background-image:
linear-gradient(to right, oklch(0.85 0.03 230 / 0.2) 1px, transparent 1px),
linear-gradient(to bottom, oklch(0.85 0.03 230 / 0.2) 1px, transparent 1px),
linear-gradient(to right, oklch(0.80 0.04 230 / 0.4) 1px, transparent 1px),
linear-gradient(to bottom, oklch(0.80 0.04 230 / 0.4) 1px, transparent 1px);
background-size: 10px 10px, 10px 10px, 50px 50px, 50px 50px;
}
/* Card hover effect */
.book-card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.book-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px -8px oklch(0.3 0.02 250 / 0.15);
}
/* Cover image styling */
.book-cover {
aspect-ratio: 3/4;
object-fit: cover;
border: 1px solid oklch(0.85 0.04 230);
}
/* Nostalgic text styling */
.title-accent {
font-family: Georgia, 'Times New Roman', serif;
letter-spacing: -0.02em;
}
/* Circuit trace decoration */
.circuit-border {
border: 2px solid oklch(0.55 0.15 145);
border-radius: 4px;
position: relative;
}
.circuit-border::before {
content: '';
position: absolute;
top: -6px;
left: 20px;
width: 12px;
height: 12px;
background: oklch(0.55 0.15 145);
border-radius: 50%;
}
.circuit-border::after {
content: '';
position: absolute;
bottom: -6px;
right: 20px;
width: 12px;
height: 12px;
background: oklch(0.55 0.15 145);
border-radius: 50%;
}

18
site/tsconfig.json Normal file
View File

@ -0,0 +1,18 @@
{
"extends": "astro/tsconfigs/strict",
"include": [
".astro/types.d.ts",
"**/*"
],
"exclude": [
"dist"
],
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}