Extrapolate
Age transformation AI app powered by Next.js, Vercel, Replicate, Upstash, and Cloudflare R2 + Workers.
Install / Use
/learn @steven-tey/ExtrapolateREADME
--NEW README COMING SOON--
Introduction
Extrapolate is an app for you to see how well you age by transforming your face with Artificial Intelligence.
https://user-images.githubusercontent.com/28986134/213781048-d215894d-2286-4176-a200-f745b255ecbe.mp4
Features
- 3s GIF of your face as it ages through time 🧓
- Store & retrieve photos from Cloudflare R2 using Workers
Deploy Your Own
You can deploy this template to Vercel with the button below:
Note that you'll need to:
- Set up a ReplicateHQ account to get the
REPLICATE_API_TOKENenv var. - Set up an Upstash account to get the Upstash Redis env vars.
- Create a Cloudflare R2 instance and set up a Cloudflare Worker to handle uploads & reads (instructions below).
Cloudflare R2 setup instructions
- Go to Cloudflare and create an R2 bucket.
- Create a Cloudflare Worker using the code snippet below.
- Bind your worker to your R2 instance under Settings > R2 Bucket Bindings.
- For extra security, set an
AUTH_KEY_SECRETvariable under Settings > Environment Variables (you can generate a random secret here). - Replace all instances of
images.extrapolate.workers.devin the codebase with your Cloudflare Worker endpoint.
// Check requests for a pre-shared secret
const hasValidHeader = (request, env) => {
return request.headers.get("X-CF-Secret") === env.AUTH_KEY_SECRET;
};
function authorizeRequest(request, env, key) {
switch (request.method) {
case "PUT":
case "DELETE":
return hasValidHeader(request, env);
case "GET":
return true;
default:
return false;
}
}
export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
if (!authorizeRequest(request, env, key)) {
return new Response("Forbidden", { status: 403 });
}
switch (request.method) {
case "PUT":
await env.MY_BUCKET.put(key, request.body);
return new Response(`Put ${key} successfully!`);
case "GET":
const object = await env.MY_BUCKET.get(key);
if (object === null) {
return new Response("Object Not Found", { status: 404 });
}
const headers = new Headers();
object.writeHttpMetadata(headers);
headers.set("etag", object.httpEtag);
return new Response(object.body, {
headers,
});
case "DELETE":
await env.MY_BUCKET.delete(key);
return new Response("Deleted!");
default:
return new Response("Method Not Allowed", {
status: 405,
headers: {
Allow: "PUT, GET, DELETE",
},
});
}
},
};
</details>
Author
- Steven Tey (@steventey)
Related Skills
node-connect
341.6kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
341.6kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.6kCommit, push, and open a PR
