Serving Behance Project Cards from a Build-Time Cache
Fetch public Behance project metadata once at build time, cache it statically, and fall back to direct project links when the API is unavailable.
29 Jun 2026, 00:07 UTC

The problem: live API calls make a portfolio fragile
A personal portfolio that calls Behance’s API on every page load depends on an external service for basic layout. If the key is missing, the rate limit is exhausted, or the endpoint changes, the project cards disappear or show errors. Embedding the key in frontend code also exposes it to anyone who inspects the page.
Thesis: fetch once at build time, cache statically, fall back to direct links
Use Behance’s read-only API during the build step, not at request time. Store the public project JSON in a static cache file, render HTML cards from that file, and link each card to the live Behance project page. If the API is unreachable, the site still shows the last cached data or a simple link.
Where the API key belongs
Behance’s public API is traditionally authenticated with an API key tied to a developer account. Treat the key as a secret: keep it in an environment variable on the build server and never commit it to the repository or send it to the browser.
Worked example: Node.js build script
Run this script on a build server or CI runner, not in the user’s browser. It requires read access to the project folder and write access to the cache directory.
#!/usr/bin/env node
const fs = require('fs');
const https = require('https');
const PROJECT_ID = process.env.BEHANCE_PROJECT_ID; // placeholder: replace with a real public project ID
const API_KEY = process.env.BEHANCE_API_KEY; // placeholder: set in CI secrets, never hardcode
const CACHE_FILE = './_cache/behance-project.json';
if (!PROJECT_ID || !API_KEY) {
console.error('Set BEHANCE_PROJECT_ID and BEHANCE_API_KEY before running.');
process.exit(1);
}
const url = `https://www.behance.net/api/v2/projects/${PROJECT_ID}?api_key=${API_KEY}`; // endpoint pattern; verify current path in Adobe/Behance docs
https.get(url, (res) => {
let data = '';
const remaining = res.headers['x-ratelimit-remaining'];
const reset = res.headers['x-ratelimit-reset'];
if (remaining !== undefined && parseInt(remaining, 10) <= 0) {
console.error(`Rate limit exhausted. Reset at ${reset}.`);
process.exit(1);
}
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => {
if (res.statusCode !== 200) {
console.error(`Unexpected status ${res.statusCode}`);
process.exit(1);
}
fs.mkdirSync('./_cache', { recursive: true });
fs.writeFileSync(CACHE_FILE, data);
console.log(`Wrote ${CACHE_FILE}`);
});
}).on('error', (err) => {
console.error(err.message);
process.exit(1);
});
Expected checks: the script exits with code 0, creates _cache/behance-project.json, and the file contains valid JSON with fields such as title, stats, and cover image data. Risks: writing the key to build logs if the environment is misconfigured, and exhausting the daily rate limit if the script runs on every commit.
Diagnostic decision: 429, 401, or missing cover image
- 429 Too Many Requests: pause builds and rely on the existing cache file until the limit resets.
- 401 or 403: verify the key is active and correctly passed; do not retry indefinitely.
- Missing cover image: render a placeholder and keep the direct Behance link so the project remains reachable.
Limitation: cached stats are stale
Appreciation, comment, and view counts change on Behance, but a build-time cache only reflects the last successful fetch. For a portfolio updated weekly, a per-build refresh is usually acceptable. If near-real-time stats are required, call the API at request time, but that reintroduces rate-limit risk and makes the page slower.
Practical verification
- Run the script in a terminal on the build machine with the environment variables set.
- Open
_cache/behance-project.jsonand confirm it parses as JSON. - Open the project’s Behance URL in an incognito window to confirm the public page loads and the link pattern works.
- Check Adobe or Behance developer documentation for the current endpoint, authentication method, and deprecation notices before deploying.
Actionable closing
Secure the API key server-side, fetch public project data at build time, write it to a cache file, render cards from that file, and always provide a direct link to the Behance project as a fallback. Review the API documentation periodically because endpoints and rate limits can change.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.