Hey there, fellow JavaScript enthusiasts! Ready to dive into the world of Product Hunt's API? Let's get our hands dirty and build an awesome user-facing integration that'll make your app the talk of the town.
Product Hunt's API is a goldmine for developers looking to tap into the latest and greatest in tech products. We'll be focusing on creating a seamless sync between your app and Product Hunt, giving your users a taste of that sweet, sweet product discovery goodness.
First things first, let's get you authenticated. Head over to Product Hunt's developer portal and snag those API credentials. We'll be using OAuth 2.0, so buckle up!
const axios = require('axios'); async function getAccessToken(code) { const response = await axios.post('https://api.producthunt.com/v2/oauth/token', { client_id: YOUR_CLIENT_ID, client_secret: YOUR_CLIENT_SECRET, code, grant_type: 'authorization_code', redirect_uri: YOUR_REDIRECT_URI }); return response.data.access_token; }
Now that we're in, let's grab some user data. We'll fetch the user's profile, upvotes, and submissions. Keep an eye on those rate limits, though!
async function getUserProfile(accessToken) { const response = await axios.get('https://api.producthunt.com/v2/me', { headers: { Authorization: `Bearer ${accessToken}` } }); return response.data.user; } async function getUserUpvotes(accessToken, cursor = null) { const query = ` query { viewer { votedPosts(first: 10${cursor ? `, after: "${cursor}"` : ''}) { edges { node { id name } } pageInfo { endCursor hasNextPage } } } } `; const response = await axios.post('https://api.producthunt.com/v2/api/graphql', { query }, { headers: { Authorization: `Bearer ${accessToken}` } } ); return response.data.data.viewer.votedPosts; }
Time to give your users some power! Let's implement upvoting and posting.
async function upvoteProduct(accessToken, productId) { const mutation = ` mutation { createVote(input: { postId: "${productId}" }) { vote { id } } } `; await axios.post('https://api.producthunt.com/v2/api/graphql', { query: mutation }, { headers: { Authorization: `Bearer ${accessToken}` } } ); } async function createPost(accessToken, postData) { const mutation = ` mutation { createPost(input: { name: "${postData.name}", tagline: "${postData.tagline}", url: "${postData.url}" }) { post { id slug } } } `; const response = await axios.post('https://api.producthunt.com/v2/api/graphql', { query: mutation }, { headers: { Authorization: `Bearer ${accessToken}` } } ); return response.data.data.createPost.post; }
Let's set up a webhook to keep everything in sync. This way, your app will always be up-to-date with the latest Product Hunt action.
const express = require('express'); const app = express(); app.post('/webhook', express.json(), (req, res) => { const event = req.body; switch (event.type) { case 'post.created': // Handle new post break; case 'vote.created': // Handle new vote break; // Add more cases as needed } res.sendStatus(200); }); app.listen(3000, () => console.log('Webhook listener running on port 3000'));
Cache those API responses and use batch operations where possible. Your users will thank you for the lightning-fast experience!
const NodeCache = require('node-cache'); const cache = new NodeCache({ stdTTL: 600 }); // Cache for 10 minutes async function getCachedUserProfile(accessToken) { const cacheKey = `user_profile_${accessToken}`; let profile = cache.get(cacheKey); if (!profile) { profile = await getUserProfile(accessToken); cache.set(cacheKey, profile); } return profile; }
Don't let those pesky errors catch you off guard. Implement robust error handling and logging to keep your sanity intact.
const winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }) ] }); async function safeApiCall(fn) { try { return await fn(); } catch (error) { logger.error('API call failed', { error: error.message, stack: error.stack }); throw error; } }
Always test your API calls. Mock responses for consistent testing and catch those edge cases before they catch you!
const nock = require('nock'); describe('Product Hunt API', () => { beforeEach(() => { nock('https://api.producthunt.com') .post('/v2/api/graphql') .reply(200, { data: { viewer: { votedPosts: { edges: [] } } } }); }); it('should fetch user upvotes', async () => { const upvotes = await getUserUpvotes('fake_token'); expect(upvotes.edges).toEqual([]); }); });
And there you have it, folks! You're now armed with the knowledge to create a killer Product Hunt integration. Remember to keep an eye on the official docs for any updates, and don't be afraid to experiment. Happy coding, and may your products always hunt successfully!