
Producthunt
Query Product Hunt via GraphQL for posts, topics, users, and collections when researching what launches in your space or planning distribution.
Overview
producthunt is an agent skill most often used in Idea (also Launch distribution) that queries Product Hunt’s GraphQL API for posts, topics, users, and collections.
Install
npx skills add https://github.com/resciencelab/opc-skills --skill producthuntWhat is this skill?
- Product Hunt GraphQL API access for posts, topics, users, and collections
- Python scripts for collection lookup by slug and related queries
- Credential helper reads PRODUCTHUNT_ACCESS_TOKEN from environment
- MIT-licensed opc-skills package with documented script entrypoints
- Useful for studying vote counts, taglines, and featured launch narratives
- GraphQL coverage: posts, topics, users, collections
Adoption & trust: 2.3k installs on skills.sh; 920 GitHub stars; 1/3 security scanners passed (skills.sh audits).
What problem does it solve?
You need structured launch and competitor data from Product Hunt without hand-copying posts and metrics from the website.
Who is it for?
Solo founders doing launch landscape research and pre-launch competitive scans with a PH developer token already configured.
Skip if: Builders without API credentials who only need one-off browsing, or teams needing automated posting and campaign management on PH.
When should I use this skill?
You need to search or retrieve Product Hunt posts, topics, users, or collections via the API for launch or market research.
What do I get? / Deliverables
Authenticated GraphQL calls return post, collection, and user payloads your agent can summarize for positioning, timing, or distribution planning.
- Structured JSON API responses for PH entities
- Collection and post metadata suitable for agent summaries
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Product Hunt is a primary discovery surface for new products—cataloged under Idea → research for market and launch-pattern reconnaissance. Scripts wrap GraphQL search and retrieval of posts and collections, which supports opportunity and competitive launch research before you build positioning.
Where it fits
Pull recent posts in your topic to see saturation and positioning patterns before you narrow the idea.
Fetch collections featuring adjacent tools to list names, taglines, and vote totals for a comparison table.
Study featured launches’ copy and follower counts to draft your own PH listing structure.
How it compares
Read-only PH GraphQL integration skill—not a launch checklist generator or App Store optimization pack.
Common Questions / FAQ
Who is producthunt for?
Solo and indie builders researching what ships on Product Hunt and agents that need scriptable retrieval of posts, collections, and profiles.
When should I use producthunt?
In idea research to map category launches, in validate scope to compare taglines and traction signals, and at launch distribution to study successful PH narratives before your go-live.
Is producthunt safe to install?
It uses your API token from the environment for network calls; review the Security Audits panel on this page and never commit PRODUCTHUNT_ACCESS_TOKEN to git.
SKILL.md
READMESKILL.md - Producthunt
{ "name": "producthunt", "version": "1.0.0", "description": "Search and retrieve content from Product Hunt. Get posts, topics, users, and collections via the GraphQL API.", "author": { "name": "ReScienceLab" }, "homepage": "https://github.com/ReScienceLab/opc-skills/tree/main/skills/producthunt", "repository": "https://github.com/ReScienceLab/opc-skills", "license": "MIT", "keywords": [ "producthunt", "product hunt", "PH", "launch" ], "skills": [ "./SKILL.md" ], "commands": [ "./scripts/" ] } #!/usr/bin/env python3 """ ProductHunt API credential management. Reads from environment: PRODUCTHUNT_ACCESS_TOKEN """ import os def get_access_token() -> str | None: """Get ProductHunt access token""" return os.environ.get("PRODUCTHUNT_ACCESS_TOKEN") def has_token() -> bool: """Check if access token is available""" return get_access_token() is not None #!/usr/bin/env python3 """ Get collection by ID or slug Usage: python3 scripts/get_collection.py COLLECTION_SLUG """ import argparse import json from producthunt_api import graphql, clean_collection, format_count QUERY = """ query GetCollection($id: ID, $slug: String) { collection(id: $id, slug: $slug) { id name tagline description url followersCount featuredAt createdAt user { name username } posts(first: 10) { totalCount edges { node { id name tagline votesCount } } } } } """ def main(): parser = argparse.ArgumentParser(description="Get ProductHunt collection") parser.add_argument("identifier", help="Collection ID or slug") parser.add_argument("--json", "-j", action="store_true", help="Output as JSON") args = parser.parse_args() variables = {} if args.identifier.isdigit(): variables["id"] = args.identifier else: variables["slug"] = args.identifier data = graphql(QUERY, variables) collection = data.get("collection") if not collection: print(f"Collection not found: {args.identifier}") return if args.json: print(json.dumps(collection, indent=2)) return print(f"id: {collection.get('id')}") print(f"name: {collection.get('name')}") print(f"tagline: {collection.get('tagline')}") print(f"followers: {format_count(collection.get('followersCount'))}") print(f"url: {collection.get('url')}") user = collection.get("user", {}) if user: print(f"creator: @{user.get('username')} ({user.get('name')})") if collection.get("description"): print(f"description: {collection['description'][:200]}") posts_data = collection.get("posts", {}) posts = [e["node"] for e in posts_data.get("edges", [])] if posts: print(f"---") print(f"posts[{posts_data.get('totalCount', len(posts))}]{{name,votes}}:") for p in posts: print(f" {p['name']},{format_count(p['votesCount'])}") if __name__ == "__main__": main() #!/usr/bin/env python3 """ Get collections with filters Usage: python3 scripts/get_collections.py --featured --limit 20 """ import argparse from producthunt_api import graphql, clean_collection, format_count, print_pagination QUERY = """ query GetCollections($first: Int, $after: String, $featured: Boolean, $userId: ID) { collections(first: $first, after: $after, featured: $featured, userId: $userId, order: FOLLOWERS_COUNT) { totalCount pageInfo { hasNextPage endCursor } edges { node { id name tagline url followersCount featuredAt } } } } """ def main(): parser = argparse.ArgumentParser(description="Get ProductHunt collections") parser.add_argument("--limit", "-l", type=int, default=20, help="Max collections") parser.add_argument("--featured", "-f", action="store_true", help="Featured collections only") parser.add