{"id":13776406,"url":"https://github.com/Phala-Network/framehub-template","last_synced_at":"2025-05-11T10:30:59.421Z","repository":{"id":220850465,"uuid":"751803909","full_name":"Phala-Network/framehub-template","owner":"Phala-Network","description":null,"archived":false,"fork":false,"pushed_at":"2024-02-29T02:14:09.000Z","size":356,"stargazers_count":13,"open_issues_count":0,"forks_count":6,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-11-17T12:43:57.580Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Phala-Network.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-02T11:11:30.000Z","updated_at":"2024-05-19T21:48:01.000Z","dependencies_parsed_at":"2024-02-29T03:26:22.196Z","dependency_job_id":"b9732f2a-66e9-411a-a2ff-15f5449fc472","html_url":"https://github.com/Phala-Network/framehub-template","commit_stats":null,"previous_names":["phala-network/framehub-template"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Phala-Network%2Fframehub-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Phala-Network%2Fframehub-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Phala-Network%2Fframehub-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Phala-Network%2Fframehub-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Phala-Network","download_url":"https://codeload.github.com/Phala-Network/framehub-template/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253551535,"owners_count":21926312,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T18:00:24.924Z","updated_at":"2025-05-11T10:30:59.116Z","avatar_url":"https://github.com/Phala-Network.png","language":"TypeScript","funding_links":[],"categories":["Useful Tools \u0026 Libraries"],"sub_categories":["Serverless Computing Providers"],"readme":"\u003cbr /\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/Phala-Network/framehub-template\"\u003e\n    \u003cimg src=\"https://i.imgur.com/WrGTAKp.jpeg\" alt=\"Logo\" width=\"80\" height=\"80\"\u003e\n  \u003c/a\u003e\n\n  \u003ch3 align=\"center\"\u003eFrameHub-Template\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    Host Farcaster Frames on decentralized serverless cloud.\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/Phala-Network/framehub-template\"\u003e\u003cstrong\u003eExplore the docs »\u003c/strong\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003ca href=\"https://warpcast.com/hashwarlock/0x28888657\"\u003eView Demo\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/Phala-Network/framehub-template/issues\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://t.me/framehubhq\"\u003eTelegram Discussion\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n## About The Project\n\n![](https://i.imgur.com/DqcisLn.png)\n\nFrameHub is a decentralized Farcaster Frame hosting protocol. Unlike Vercel or other FaaS, it allows you to publish your Frame to IPFS and hosts it on a fully decentralized FaaS cloud with the following benefits:\n\n- 💨 Ship Fast: Build and ship with familiar toolchain in minutes\n- ⛑️ Secure: Execution guarded by rock solid TEE / Intel SGX\n- 🔒 Private: Host API keys and user privacy at ease\n- 💎 Unstoppable: Powered by IPFS and [Phala](https://phala.network)'s 35k+ decentralized TEE workers\n\n## Getting Started\n\n### Prepare\n\n```bash\nnpm install\n```\n\n### Test Locally\n\n```bash\nnpx ts-node src/test.ts\n```\n\n### Compile\n\nBuild your frame and output at `dist/index.js`.\n\n```bash\nnpm run build\n# yarn build\n```\n\n### Publish to IPFS\n\nBuild your frame and upload to IPFS\n\n```bash\nnpm run publish\n# yarn publish\n```\n\nUpon a successful upload, the command should show the URL to access your frame.\n\u003e Frame deployed at: https://frames.phatfn.xyz/ipfs/Qma4ejJPfuB9ag63TrWWd379QA1rKf1HyXJmLE5k16dAYk\n\n\u003cdetails\u003e\n\u003csummary\u003eNew to thirdweb?\u003c/summary\u003e\nWe use \u003ca href=\"https://thirdweb.com/dashboard/infrastructure/storage\"\u003ethirdweb Storage\u003c/a\u003e to host IPFS contents. If you are new to thirdweb, the command will guide you to create your account or login to your existing account from the browser. (You may need to forward port 8976 if you are accessing a remote console via SSH.)\n\u003c/details\u003e\n\n### Access the Published Frame\n\nOnce published, your frame is availabe at the URL: `https://frames.phatfn.xyz/ipfs/\u003cyour-cid\u003e`. You can get it from the \"Publish to IPFS\" step.\n\nYou can test it with `curl`.\n\n```bash\ncurl https://frames.phatfn.xyz/ipfs/\u003cyour-cid\u003e\n```\n\nYou can test the frame with the [Warpcast frame simulator](https://warpcast.com/~/developers/frames) with the URL.\n\n## Advanced Usage\n\n### Add Secrets\n\nBy default, all of the compiled JS code is visible for anyone to view if they look at IPFS CID. This makes private info like API keys, signer keys, etc. vulnerable to be stolen. To protect devs from leaking keys, we have added a field called `secret` in the `Request` object. It allows you to store secrets in a vault for your Frame to access.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eHow to Add Secrets\u003c/b\u003e\u003c/summary\u003e\n\nThe steps to add a `secret` is simple. We will add the [Neynar](https://neynar.com) API Key in this example by creating a secret JSON object with the `apiKey`:\n\n```json\n{\"apiKey\": \"\u003cNEYNAR_API_KEY\u003e\"}\n```\n\nThen in your frame code, you will be able to access the secret key via `req.secret` object:\n\n```js\nasync function POST(req: Request): Promise\u003cResponse\u003e {\n    const apiKey = req.secret?.apiKey\n}\n```\n\n\u003e Note: Before continuing, make sure to publish your compiled JS code, so you can add secrets to the CID.\n\n**Open terminal**\nUse `curl` to `POST` your secrets to `https://frames.phatfn.xyz/vaults`. Replace `IPFS_CID` with the CID to the compile JS code in IPFS, and replace `\u003cNEYNAR_API_KEY\u003e` with your Neynar API key.\n\nThe command will look like this:\n```shell\ncurl https://frames.phatfn.xyz/vaults -H 'Content-Type: application/json' -d '{\"cid\": \"IPFS_CID\", \"data\": {\"apiKey\": \"\u003cNEYNAR_API_KEY\u003e\"}}'\n# Output:\n# {\"token\":\"e85ae53d2ba4ca8d\",\"key\":\"e781ef31210e0362\",\"succeed\":true}\n```\n\nThe API returns a `token` and a `key`. The `key` is the id of your secret. It can be used to specify which secret you are going to pass to your frame. The `token` can be used by the developer to access the raw secret. You should never leak the `token`.\n\nTo verify the secret, run the following command where `key` and `token` are replaced with the values from adding your `secret` to the vault.\n```shell\ncurl https://frames.phatfn.xyz/vaults/\u003ckey\u003e/\u003ctoken\u003e\n```\n\nExpected output:\n```shell\n{\"data\":{\"apiKey\":\"\u003cNEYNAR_API_KEY\u003e\"},\"succeed\":true}\n```\n\nTo see where the code is used in this template, check out [index.ts](./src/index.ts) line 36.\n\nIf you are using secrets, make sure that your Cast URL is set in the following syntax where `cid` is the IPFS CID of your compiled JS file and `key` is the `key` from adding secrets to your vault.\n```text\nhttps://frames.phatfn.xyz/ipfs/\u003ccid\u003e?key=\u003ckey\u003e\n```\n\nhttps://github.com/Phala-Network/phat-frame-template/assets/64296537/620ad981-73a8-46c0-8cfd-16d2e245abfc\n\n\u003c/details\u003e\n\n(TBD: instantiate, ...)\n\n## Roadmap\n\n- [x] Publish to IPFS command\n- [x] Support secrets\n- [ ] Free \"Publish to IPFS\" command\n- [ ] SVG generation\n- [ ] Database\n\n## FAQ\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eWhat packages can I use in the frame server?\u003c/b\u003e\u003c/summary\u003e\n\u003cul\u003e\n  \u003cli\u003eMost of the npm packages are supported: viem, onchainkit, ….\u003c/li\u003e\n  \u003cli\u003eSome packages with some advanced features are not supported:\u003c/li\u003e\n  \u003cul\u003e\n    \u003cli\u003eLarge code size. Compiled bundle should be less than 500kb.\u003c/li\u003e\n    \u003cli\u003eLarge memory usage, like image generation\u003c/li\u003e\n    \u003cli\u003eWeb Assembly\u003c/li\u003e\n    \u003cli\u003eBrowser only features: local storage, service workers, etc\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eWhat’s the spec of the Javascript runtime?\u003c/b\u003e\u003c/summary\u003e\n\u003cul\u003e\n  \u003cli\u003eThe code runs inside a tailored \u003ca href=\"https://bellard.org/quickjs/\"\u003eQuickJS engine\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003eAvailable features: ES2023, async, fetch, setTimeout, setInterval, bigint\u003c/li\u003e\n  \u003cli\u003eResource limits\u003c/li\u003e\n  \u003cul\u003e\n    \u003cli\u003eMax execution time 10s\u003c/li\u003e\n    \u003cli\u003eMax memory usage: 16 mb\u003c/li\u003e\n    \u003cli\u003eMax code size: 500 kb\u003c/li\u003e\n    \u003cli\u003eLimited CPU burst: CPU time between async calls is limited. e.g. Too complex for-loop may hit the burst limit.\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eWhy is the serverless platform secure?\u003c/b\u003e\u003c/summary\u003e\n\u003cul\u003e\n  \u003cli\u003eYour code on FrameHub is fully secure, private, and permissionless. Nobody can manipulate your program, steal any data from it, or censor it.\u003c/li\u003e\n  \u003cli\u003eSecurity: The code is executed in the decentralized TEE network running on Phala Network. It runs code inside a secure blackbox (called enclave) created by the CPU. It generates cryptographic proofs verifiable on Phala blockchain. It proves that the hosted code is exactly the one you deployed.\u003c/li\u003e\n  \u003cli\u003ePrivacy: You can safely put secrets like API keys or user privacy on FrameHub. The code runs inside TEE hardware blackboxs. The memory of the program is fully encrypted by the TEE. It blocks any unauthorized access to your data.\u003c/li\u003e\n  \u003cli\u003eLearn more at \u003ca href=\"https://phala.network\"\u003ePhala Network Homepage\u003c/a\u003e\u003c/li\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eWhat's TEE / Intel SGX?\u003c/b\u003e\u003c/summary\u003e\n\u003cul\u003e\n  \u003cli\u003e\u003ca href=\"https://collective.flashbots.net/t/tee-sgx-wiki/2019\"\u003eTEE/SGX wiki\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"https://collective.flashbots.net/t/debunking-tee-fud-a-brief-defense-of-the-use-of-tees-in-crypto/2931\"\u003eDebunking TEE FUD: A Brief Defense of The Use of TEEs in Crypto\u003c/a\u003e\u003c/li\u003e\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPhala-Network%2Fframehub-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FPhala-Network%2Fframehub-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FPhala-Network%2Fframehub-template/lists"}