The Problem
I run a free puzzle generator site (JigsawMake.com) with 30+ tools — word search, crossword, bingo, sudoku, jigsaw. Teachers and event organizers kept asking the same question:
"Which puzzles should I use for my classroom / party / team event, and how do I set them up?"
I realized I could build a Claude Code skill that answers this automatically — not just with recommendations, but with pre-configured links that open the generator with everything already filled in.
The key insight: URL parameters turn a recommendation into a one-click solution.
What We're Building
A skill called puzzle-activity-planner that:
- Takes an event description (e.g., "45-minute science class about ocean animals, 25 students")
- Generates a structured activity plan with timing and materials
- Outputs generator links with URL parameters pre-filled — the user clicks and gets a ready-to-print puzzle
Here's what the output looks like:
Word Search: https://jigsawmake.com/word-search-maker?title=Ocean%20Animals&words=DOLPHIN,OCTOPUS,SEAHORSE,WHALE&gridSize=12
Crossword: https://jigsawmake.com/crossword-puzzle-maker?title=Ocean%20Animals&clues=DOLPHIN:Smart%20marine%20mammal|OCTOPUS:Has%20eight%20arms
Bingo: https://jigsawmake.com/bingo-card-generator?title=Ocean%20Bingo&items=Dolphin,Octopus,Seahorse&cardCount=25
The AI generates the content (words, clues, items) and bakes it right into the URL.
Step 1: Add URL Parameter Support to Your Web App
Before building the skill, your web app needs to accept URL parameters. Here's the pattern I used in React (Next.js):
// In your generator component's mount useEffect
useEffect(() => {
if (typeof window === 'undefined') return;
const params = new URLSearchParams(window.location.search);
const urlTitle = params.get('title');
const urlWords = params.get('words');
const urlGridSize = params.get('gridSize');
if (urlTitle) setTitle(decodeURIComponent(urlTitle));
if (urlGridSize) {
const size = parseInt(urlGridSize, 10);
if (size >= 5 && size <= 30) setGridSize(size);
}
if (urlWords) {
const words = decodeURIComponent(urlWords)
.split(',')
.map(w => w.trim().toUpperCase())
.filter(w => w.length > 0);
if (words.length > 0) {
setWordList(words);
setWordListText(words.join('\n'));
// Trigger puzzle generation
pendingGenerateRef.current = true;
}
}
}, []);
Key points:
- Always validate and bound numeric values (grid size, counts)
- Use
decodeURIComponent()for text values - Only accept known enum values for string options (e.g., difficulty must be "easy", "medium", or "hard")
- Invalid parameters should be silently ignored, not crash the page
For crossword puzzles, I used a pipe-separated format for word:clue pairs:
?clues=DOLPHIN:Smart%20marine%20mammal|OCTOPUS:Has%20eight%20arms
This keeps the URL readable while supporting structured data.
Step 2: Create the SKILL.md
A Claude Code skill is just a markdown file with YAML frontmatter. Create SKILL.md:
---
name: puzzle-activity-planner
description: "Plan puzzle-based activities for classrooms, parties, and events."
Use when someone says "plan a puzzle activity" or "classroom puzzle session".
---
The description field is critical — Claude reads it to decide when to activate the skill.
Step 3: Document URL Parameters in the Skill
This is where the magic happens. Instead of just linking to your tools, teach the AI your URL parameter schema so it can construct pre-filled links:
## URL Parameters
### Word Search
| Param | Values | Default |
|-------|--------|---------|
| `title` | URL-encoded text | "Word Search Puzzle" |
| `words` | Comma-separated | default list |
| `gridSize` | 5-30 | 15 |
| `diagonal` | true/false | true |
| `backward` | true/false | false |
### Crossword
| Param | Values | Default |
|-------|--------|---------|
| `title` | URL-encoded text | "Crossword Puzzle" |
| `difficulty` | easy, medium, hard | medium |
| `clues` | WORD:clue pairs separated by \| | default clues |
Then add a behavior rule:
## Rules
- Always use URL parameters in generator links with pre-filled content
- Generate word-clue pairs yourself and embed them in the URL
This tells Claude: "You are the AI — generate the content and put it in the URL. Don't make the user do it."
Step 4: Test It
Install the skill:
mkdir -p ~/.claude/skills/puzzle-activity-planner
cp SKILL.md ~/.claude/skills/puzzle-activity-planner/
Then in Claude Code:
/puzzle-activity-planner Plan a 30-minute puzzle activity for a 4th grade
science class about ocean animals, 25 students
Claude generates a complete plan with pre-configured links. The teacher clicks, gets a ready-to-print puzzle.
The URL Deep Linking Pattern
This pattern works for any web tool, not just puzzles:
- Add URL parameter support to your web app's form/generator
- Document the parameter schema in your SKILL.md
- Tell the AI to generate content and embed it in the URL
- User gets one-click links instead of manual configuration
The key is that the AI generates domain-specific content (vocabulary words, trivia clues, bingo items) and encodes it directly into the URL. The web app just reads the parameters and renders.
What I Learned
URL parameters are an underused interface. Most web tools accept them but don't document or promote them. By teaching an AI your URL schema, you turn a static link into a personalized, ready-to-use tool.
Skills are surprisingly simple. A SKILL.md file is just instructions + a parameter reference table. No API, no auth, no backend. The skill I built is ~200 lines of markdown.
The AI is the content engine. For crosswords, the AI generates word-clue pairs. For word searches, it picks theme-appropriate vocabulary. For bingo, it creates themed items. All embedded in the URL. The web app doesn't need its own AI — the skill handles content generation.
Try It
The skill is open source:
# Install with npx skills
npx skills add fruitwyatt/puzzle-activity-planner
# Or clone directly
git clone https://github.com/fruitwyatt/puzzle-activity-planner \
~/.claude/skills/puzzle-activity-planner
GitHub: fruitwyatt/puzzle-activity-planner
The generators are all free at JigsawMake.com — no signup, no watermarks, runs entirely in the browser.
Top comments (0)