skills/360-panorama-viewer/SKILL.md
Build a fully self-contained 360° equirectangular panorama viewer as a single HTML file. The viewer uses Three.js to render immersive spherical panoramas with drag-to-look, zoom, auto-rotate, and a scene-switcher sidebar. All panorama images are embedded as base64 JPEG — no server needed. Use this skill whenever the user asks to create a 360 viewer, VR panorama app, immersive scene gallery, equirectangular image viewer, or wants to combine multiple AI-generated panoramas into an interactive webpage. Also trigger when the user says things like "make a 360 viewer", "VR world gallery", "360度全景", "全景查看器", "make scenes I can look around in", etc.
npx skillsauth add happycapy-ai/happycapy-skills 360-panorama-viewerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill creates a polished, self-contained 360° panorama viewer HTML file.
A single .html file (~3–6 MB depending on scene count) that:
| Asset | Purpose |
|---|---|
| assets/viewer_template.html | Complete viewer HTML with Three.js inlined; panorama data injected at build time |
| scripts/build_viewer.py | Loads images, applies seam fix, base64-encodes, injects into template |
Ask (or infer from context) for each scene:
🍄 Mario World)Typical count: 3–6 scenes. You can also accept user-provided image files directly (skip generation).
For each scene, generate a 360° equirectangular panorama image.
Model choice:
google/gemini-3.1-flash-image-preview via AI Gateway — reliable 2:1 output, no safety rejections for fictional themesgpt-image-2 via AI Gateway at size 1536x1024 — higher quality but may reject branded IP (Mario, Zelda, etc.)Generation code (Gemini route):
import os, requests, base64
from PIL import Image
import io
api_key = os.environ['AI_GATEWAY_API_KEY']
def generate_panorama(prompt: str, save_path: str):
payload = {
"model": "google/gemini-3.1-flash-image-preview",
"prompt": prompt,
"response_format": "b64_json",
"n": 1
}
resp = requests.post(
'https://ai-gateway.happycapy.ai/api/v1/images/generations',
headers={
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json',
'Origin': 'https://trickle.so'
},
json=payload,
timeout=180
)
resp.raise_for_status()
img_bytes = base64.b64decode(resp.json()['data'][0]['b64_json'])
img = Image.open(io.BytesIO(img_bytes)).convert('RGB')
img.save(save_path)
return save_path
Prompt formula for good equirectangular panoramas:
360 degree equirectangular panorama of [SCENE DESCRIPTION].
[Key visual elements]. [Style description].
Wide seamless landscape, 2:1 aspect ratio,
left and right edges must tile perfectly for 360 VR viewing.
Example prompts:
360 degree equirectangular panorama of a colorful cartoon mushroom kingdom platformer world. Bright blue sky, rolling green hills, red mushroom houses, floating brick blocks, gold coins, stone castle. Vibrant cartoon illustration, 2:1 aspect ratio, seamless tiling.360 degree equirectangular panorama of a futuristic underwater city. Bioluminescent buildings, schools of fish, coral reefs, deep ocean light shafts. Cinematic, 2:1 aspect ratio, seamless tiling.Save each generated image to a temp path (e.g. tmp/scene_N_raw.png).
Run the build script, passing all scenes as a JSON array:
SKILL_DIR=/home/node/.claude/skills/360-panorama-viewer
python3 "$SKILL_DIR/scripts/build_viewer.py" \
--template "$SKILL_DIR/assets/viewer_template.html" \
--output "outputs/360_viewer.html" \
--scenes '[
{"title":"🍄 Mario World","thumb_label":"Mario","image_path":"tmp/mario.png","initial_lon":90},
{"title":"🐚 Underwater City","thumb_label":"Deep City","image_path":"tmp/underwater.png","initial_lon":0}
]'
The script will:
np.rolls the image. No blending. This ensures the 360° seam is as clean as possible without distorting colors.Output the file to outputs/360_viewer.html (or user-specified path) and attach it as a static HTML deliverable.
If the user already has a viewer and wants to swap out one scene (e.g. regenerate Mario), do NOT rerun all scenes — just re-encode the new image and replace its b64 field in the HTML:
import re, base64, io, numpy as np
from PIL import Image
SKILL_DIR = '/home/node/.claude/skills/360-panorama-viewer'
# Load and fix the new image
img = Image.open('new_mario.png').convert('RGB')
img = img.resize((1774, 887), Image.LANCZOS)
arr = np.array(img)
# pure roll seam fix
f = arr.astype(np.float32)
h, w = arr.shape[:2]
best_roll, best_score = 0, float('inf')
for roll in range(w):
r = np.roll(f, roll, axis=1)
score = float(np.abs(r[:, :5] - r[:, w-5:]).mean())
if score < best_score:
best_score = score
best_roll = roll
fixed = np.roll(arr, best_roll, axis=1)
buf = io.BytesIO()
Image.fromarray(fixed).save(buf, format='JPEG', quality=90)
new_b64 = base64.b64encode(buf.getvalue()).decode('ascii')
# Replace in HTML by matching scene title
with open('outputs/360_viewer.html') as fh:
html = fh.read()
# Match the specific scene entry (adjust title keyword as needed)
pattern = r"(title:\s*'[^']*Mario[^']*',\s*initialLon:\s*[\d.]+,\s*b64:\s*')([^']+)(')"
html_new, n = re.subn(pattern, r'\g<1>' + new_b64 + r'\g<3>', html)
assert n == 1, f"Expected 1 replacement, got {n}"
with open('outputs/360_viewer.html', 'w') as fh:
fh.write(html_new)
print(f'Replaced Mario scene (roll={best_roll})')
Equirectangular panoramas wrap horizontally: x=0 and x=w-1 represent the same physical meridian. AI-generated images rarely place the seam at a natural boundary (e.g. open sky), so the default seam is often visible.
Pure roll: shift the whole image left/right to find the position where the 5-pixel columns at both edges are most similar (lowest mean absolute difference). np.roll() is a circular shift — no pixels are added or removed, no colors are changed. This is lossless and never creates artifacts.
Never use blending/color correction at the seam: it creates a visible "smeared" band where pixel values are artificially averaged, which looks worse than the original seam.
The template includes these controls, all functional out of the box:
initialLon of current sceneScene initialLon is the starting horizontal angle (0–360). Use it to face an interesting part of the panorama on load (e.g. 90 = face right, 180 = face backwards).
tools
Universal LaTeX document skill: create, compile, and convert any document to professional PDF with PNG previews. Supports resumes, reports, cover letters, invoices, academic papers, theses/dissertations, academic CVs, presentations (Beamer), scientific posters, formal letters, exams/quizzes, books, cheat sheets, reference cards, exam formula sheets, fillable PDF forms (hyperref form fields), conditional content (etoolbox toggles), mail merge from CSV/JSON (Jinja2 templates), version diffing (latexdiff), charts (pgfplots + matplotlib), tables (booktabs + CSV import), images (TikZ), Mermaid diagrams, AI-generated images, watermarks, landscape pages, bibliography/citations (BibTeX/biblatex), multi-language/CJK (auto XeLaTeX), algorithms/pseudocode, colored boxes (tcolorbox), SI units (siunitx), Pandoc format conversion (Markdown/DOCX/HTML ↔ LaTeX), and PDF-to-LaTeX conversion of handwritten or printed documents (math, business, legal, general). Compile script supports pdflatex, xelatex, lualatex with auto-detection, latexmk backend, texfot log filtering, PDF/A output, and verbosity control (--verbose/--quiet). Empirically optimized scaling: single agent 1-10 pages, split 11-20, batch-7 pipeline 21+. Use when user asks to: (1) create a resume/CV/cover letter, (2) write a LaTeX document, (3) create PDF with tables/charts/images, (4) compile a .tex file, (5) make a report/invoice/presentation, (6) anything involving LaTeX or pdflatex, (7) convert/OCR a PDF to LaTeX, (8) convert handwritten notes, (9) create charts/graphs/diagrams, (10) create slides, (11) write a thesis or dissertation, (12) create an academic CV, (13) create a poster, (14) create an exam/quiz, (15) create a book, (16) convert between document formats (Markdown, DOCX, HTML to/from LaTeX), (17) generate Mermaid diagrams for LaTeX, (18) create a formal business letter, (19) create a cheat sheet or reference card, (20) create an exam formula sheet or crib sheet, (21) condense lecture notes/PDFs into a cheat sheet, (22) create a fillable PDF form with text fields/checkboxes/dropdowns, (23) create a document with conditional content/toggles (show/hide sections), (24) generate batch/mail-merge documents from CSV/JSON data, (25) create a version diff PDF (latexdiff) highlighting changes between documents, (26) create a homework or assignment submission with problems and solutions, (27) create a lab report with data tables, graphs, and error analysis, (28) encrypt or password-protect a PDF, (29) merge multiple PDFs into one, (30) optimize/compress a PDF for web or email, (31) lint or check a LaTeX document for common issues, (32) count words in a LaTeX document, (33) analyze document statistics (figures, tables, citations), (34) fetch BibTeX from a DOI, (35) convert a Graphviz .dot file to PDF/PNG, (36) convert a PlantUML .puml file to PDF/PNG, (37) create a one-pager/fact sheet/executive summary, (38) create a datasheet or product specification sheet, (39) extract pages from a PDF (page ranges, odd/even), (40) check LaTeX package availability before compiling, (41) analyze citations and cross-reference with .bib files, (42) debug LaTeX compilation errors, (43) make a document accessible (PDF/A, tagged PDF), (44) create lecture notes or course handouts, (45) fill an existing PDF form (fillable fields or non-fillable with annotations), (46) extract text or tables from a PDF (pdfplumber, pypdf), (47) OCR a scanned PDF to text (pytesseract), (48) create a PDF programmatically with reportlab (Canvas, Platypus), (49) rotate or crop PDF pages (pypdf), (50) add a watermark to an existing PDF, (51) extract metadata from a PDF (title, author, subject).
testing
Improves the quality of images, especially screenshots, by enhancing resolution, sharpness, and clarity. Perfect for preparing images for presentations, documentation, or social media posts.
tools
HappyCapy-specific skill for publishing content to 13+ social media platforms (Instagram, Twitter, LinkedIn, Threads, Facebook, TikTok, YouTube, Pinterest, Reddit, Telegram, Discord, etc.) simultaneously with platform-optimized styles, optional AI-generated media (video/image), and smart error handling. Uses Late MCP integration available in HappyCapy environment. Use when you need to cross-post to social media, create multi-platform marketing content, share announcements across platforms, publish with platform-specific adaptations, generate AI media for posts, or manage social media publishing workflows. Supports interactive content creation with user-guided platform selection, media generation choices, preview before publish, and automatic retry with character limit adjustments.
development
Automate HappyCapy skill creation by finding and adapting existing skills from anthropics/skills repository. Handles environment constraints (Python 3.11, Node.js 24, no Docker). Use when user wants to create or adapt skills for specific tasks.