{"id":16253125,"url":"https://github.com/vgrichina/web4","last_synced_at":"2025-04-06T02:08:54.390Z","repository":{"id":40493115,"uuid":"355485808","full_name":"vgrichina/web4","owner":"vgrichina","description":"Web4 is a new way to distribute decentralized apps. Deploy single WASM smart contract to deploy whole web app.","archived":false,"fork":false,"pushed_at":"2025-02-17T09:07:48.000Z","size":1128,"stargazers_count":96,"open_issues_count":1,"forks_count":18,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-30T01:12:11.472Z","etag":null,"topics":["assemblyscript","blockchain","ipfs","nearprotocol","permaweb","rust","web3","web4"],"latest_commit_sha":null,"homepage":"https://web4.near.page","language":"JavaScript","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/vgrichina.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":"2021-04-07T09:26:28.000Z","updated_at":"2025-02-17T09:07:52.000Z","dependencies_parsed_at":"2024-06-18T00:21:30.061Z","dependency_job_id":"c67bf08e-e574-4c29-abd4-c097a8db499c","html_url":"https://github.com/vgrichina/web4","commit_stats":{"total_commits":244,"total_committers":4,"mean_commits":61.0,"dds":"0.016393442622950838","last_synced_commit":"0c28bfcb4c9f6495b42130876e1a8744f980f902"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vgrichina%2Fweb4","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vgrichina%2Fweb4/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vgrichina%2Fweb4/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vgrichina%2Fweb4/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vgrichina","download_url":"https://codeload.github.com/vgrichina/web4/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247423515,"owners_count":20936626,"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":["assemblyscript","blockchain","ipfs","nearprotocol","permaweb","rust","web3","web4"],"created_at":"2024-10-10T15:16:03.167Z","updated_at":"2025-04-06T02:08:54.361Z","avatar_url":"https://github.com/vgrichina.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Coverage Status](https://coveralls.io/repos/github/vgrichina/web4/badge.svg?branch=main)](https://coveralls.io/github/vgrichina/web4?branch=main)\n\n# web4\n\n## Table of Contents\n- [TL;DR](#tldr)\n- [What is web4?](#what-is-web4)\n- [How it works?](#how-it-works)\n  - [Authentication](#authentication)\n- [Known web4 sites](#known-web4-sites)\n- [Useful tools](#useful-tools)\n- [Example contract](#example-contract-in-assemblyscript)\n  - [Request](#request)\n  - [Response](#response)\n  - [Loading data](#loading-data)\n  - [Posting transactions](#posting-transactions)\n  - [Caching considerations](#caching-considerations)\n- [Rust support](#rust-support)\n- [Deployment](#deployment)\n  - [near.page](#nearpage)\n  - [testnet.page](#testnetpage)\n- [Running locally](#running-locally)\n- [FAQ](#frequently-asked-questions)\n- [Priorities](#priorities)\n- [Roadmap](#roadmap)\n- [Contributing](#contributing)\n\n## TL;DR\n\n* Manage website frontend in smart contract\n* Every `.near` account receives a subdomain under [https://near.page](https://near.page)\n    * E.g. `thewiki.near` serves [https://thewiki.near.page](https://thewiki.near.page)\n* Use IPFS with Filecoin to host larger files\n\nQuick Start:\n```bash\n# Create a simple website\nmkdir my-web4-site \u0026\u0026 cd my-web4-site\necho '\u003ch1\u003eHello Web4!\u003c/h1\u003e' \u003e index.html\n\n# Deploy to your account\nnpx web4-deploy . --accountId your-account.near\n```\n\nYour site will be live at `https://your-account.near.page` 🎉\n\n## What is web4?\n\n- Decentralised ownership and hosting\n- Content permanence by default, no more expired links\n- Offline friendly\n- Web presence controlled by user\n- Interactive mobile apps linked together as websites, no appstores\n\n## How it works?\n\nYou only need to deploy single smart contract using WebAssembly to host your app HTTP backend,\nstatic resources and blockchain logic. See [Example contract](#example-contract-in-assemblyscript) or \n[Rust support](#rust-support) for implementation details.\n\nThere is an [HTTP gateway](https://github.com/vgrichina/web4) to NEAR blockchain which allows smart contract to handle arbitrary GET requests.\n\nEvery smart contract on NEAR also gets corresponding API endpoint which can be accessed through regular HTTP requests.\n\n### Authentication\n\nWeb4 provides simplified authentication flow:\n\n- Login via `/web4/login` endpoint\n- Logout via `/web4/logout` endpoint \n- Current account ID is available via `web4_account_id` cookie\n- App-specific private key, if used, is stored in `web4_private_key` cookie\n- Transactions can be submitted via POST requests to `/web4/contract/{contract_id}/{method_name}`\n\nExample usage in JavaScript:\n\n```javascript\n// Login\nwindow.location.href = '/web4/login'\n\n// Check if user is logged in\nconst accountId = Cookies.get('web4_account_id');\n\n// Logout\nwindow.location.href = '/web4/logout'\n\n// Submit transaction\nawait fetch('/web4/contract/example.near/someMethod', {\n    method: 'POST',\n    body: JSON.stringify({ param1: 'value1' })\n})\n```\n\nThis allows seamless integration with existing web frameworks while maintaining security through NEAR wallet.\n\nSee also:\n- [FAQ: How does authentication work?](#how-does-authentication-work-with-web4)\n- [FAQ: web4/login vs wallet integration](#whats-the-difference-between-web4login-and-integrating-a-wallet-directly)\n\n## Known web4 sites\n\nFeatured sites:\n- https://devhub.near.page - NEAR Developer Hub\n- https://web4.near.page - Web4 project homepage\n- https://treasury-auroralabs.near.page - NEAR Treasury DAOs\n- https://svelt.near.page - Svelte starter template\n- https://awesomeweb4.near.page - Web4 app catalog\n- https://thewiki.near.page - Decentralized wiki\n\nCommunity sites:\n- https://slimebook.near.page\n- https://lands.near.page\n- https://zavodil.near.page\n- https://psalomo.near.page\n- https://oracle-prices.near.page\n- https://orangejoe.near.page\n- https://orderly.near.page\n- https://theegg.near.page\n- https://twelvetone.near.page\n- https://sotg.near.page\n- https://pcards.near.page\n- https://aclot.near.page\n- https://wlog.near.page\n- https://1chess.near.page\n- https://vlad.near.page\n\nSee more examples at https://awesomeweb4.near.page\n\n## Useful tools\n\n- HTTP gateway https://github.com/vgrichina/web4\n- High performance RPC https://github.com/vgrichina/fast-near\n- Deploy tool https://github.com/vgrichina/web4-deploy\n- Rust starter projects:\n  - https://github.com/zavodil/near-web4-contract\n  - https://github.com/frol/near-web4-demo\n- Self-hosted Linktree  https://github.com/vgrichina/web4-littlelink\n- Svelte starter http://svelt.near.page\n- Web4 app catalog https://awesomeweb4.near.page\n\n## Example contract (in AssemblyScript)\n\n```ts\nexport function web4_get(request: Web4Request): Web4Response {\n    if (request.path == '/test') {\n        // Render HTML with form to submit a message\n        return htmlResponse(form({ action: \"/web4/contract/guest-book.testnet/addMessage\" }, [\n            textarea({ name: \"text\" }),\n            button({ name: \"submit\" }, [\"Post\"])\n        ]));\n    }\n\n\n    if (request.path == '/messages') {\n        const getMessagesUrl = '/web4/contract/guest-book.testnet/getMessages';\n        // Request preload of dependency URLs\n        if (!request.preloads) {\n            return preloadUrls([getMessagesUrl]);\n        }\n\n        // Render HTML with messages\n        return htmlResponse('messages: ' + util.bytesToString(request.preloads.get(getMessagesUrl).body)!);\n    }\n\n    if (request.accountId) {\n        // User is logged in, we can welcome them\n        return htmlResponse('Hello to \u003cb\u003e' +  request.accountId! + '\u003c/b\u003e from \u003ccode\u003e' + request.path + '\u003c/code\u003e');\n    }\n\n    // Demonstrate serving content from IPFS\n    if (request.path == \"/\") {\n        return bodyUrl('ipfs://bafybeib72whzo2qiore4q6sumdteh6akewakrvukvqmx4n6kk7nwzinpaa/')\n    }\n\n    // By default return 404 Not Found\n    return status(404);\n}\n\n```\n\nBasically smart contract just needs to implement `web4_get` method to take in and return data in specific format.\n\n### Request\n\n```ts\n@nearBindgen\nclass Web4Request {\n    accountId: string | null;\n    path: string;\n    params: Map\u003cstring, string\u003e;\n    query: Map\u003cstring, Array\u003cstring\u003e\u003e;\n    preloads: Map\u003cstring, Web4Response\u003e;\n}\n```\n\n### Response\n\n```ts\n@nearBindgen\nclass Web4Response {\n    contentType: string;\n    status: u32;\n    body: Uint8Array;\n    bodyUrl: string;\n    preloadUrls: string[] = [];\n    cacheControl: string;\n}\n```\n\n### Loading data\n\nYou can load any required data in `web4_get` by returning list of URLs to preload in `preloadUrls` field.\n\nE.g. contract above preloads `/web4/contract/guest-book.testnet/getMessages`. This class `getMessages` view method on `guest-book.testnet` contract.\n\nAfter data is preloaded `web4_get` gets called again with loaded data injected into `preloads`.\n\n### Posting transactions\n\nYou can post transaction by making a POST request to corresponding URL.\n\nE.g contract above preloads has form that gets posted to `/web4/contract/guest-book.testnet/addMessage` URL. This URL submits transaction which calls `addMessage` method on `guest-book.testnet` contract.\n\nNote that both JSON and form data are supported. When transaction is processed by server user gets redirected to wallet for signing this transaction.\n\nIn future there is a plan to allow sending app-specific key as a cookie to sign limited subset of transactions without confirmation in wallet.\n\n### Caching considerations\n\nBy default all HTML responses can be cached for 1 minute (assumed dynamic content). \nAll images, videos, audio and CSS can be cached for 1 day (assumed static content).\n\nYou can override this by setting `cacheControl` field in response.\n\nIt's not recommended to cache content for too long as then it not going to be hot on IPFS gateway.\n\nSee also:\n- [Rust support](#rust-support)\n- [Known web4 sites](#known-web4-sites) for real-world examples\n\n## Rust support\n\nCheck out [sample web4 project made with Rust](https://github.com/frol/near-web4-demo).\n\n# near.page\n\nYou can access your deployed smart contract on https://near.page. This is hosted web4 gateway provided to all `.near` accounts. For now it's free, but in future you might have to pay depending on how much traffic you get.\n\nEvery contract gets corresponding domain, e.g. check out https://web4.near.page rendered by `web4.near` contract.\n\n# testnet.page\n\nThis works same as `near.page` but for contracts deployed on testnet. Every `account.testnet` gets corresponding `account.testnet.page` domain.\n\n# Running locally\n\n1. Install [mkcert](https://mkcert.dev/).\n2. Install local certificate authority (this allows browser to trust self-signed certificates):\n    ```bash\n    mkcert -install\n    ```\n3. Create `*.near.page` SSL certificate:\n    ```bash\n    mkcert \"*.near.page\"\n    ```\n3. Run `web4` man-in-the-middle proxy locally:\n    ```bash\n    IPFS_GATEWAY_URL=https://ipfs.near.social NODE_ENV=mainnet WEB4_KEY_FILE=./_wildcard.near.page-key.pem WEB4_CERT_FILE=./_wildcard.near.page.pem npx web4-near\n    ```\n4. Setup browser to use [automatic proxy configuration file](https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file) at `http://localhost:8080/` or to use `localhost:8080` as an HTTPS proxy server. \n\nSee also:\n- [FAQ: How can I access my local app bundle?](#how-can-i-access-my-local-app-bundle)\n- [near.page](#nearpage) and [testnet.page](#testnetpage) for production deployment\n\n## Environment variables\n\n- `NODE_ENV` - `mainnet` or `testnet` to select network ID to use with NEAR config and key store\n- `IPFS_GATEWAY_URL` - URL of IPFS gateway to use for `ipfs://` URLs\n- `WEB4_KEY_FILE` - path to SSL key file\n- `WEB4_CERT_FILE` - path to SSL certificate file\n- `PORT` - port to listen on (default: `3000`)\n- `PROXY_PORT` - port to listen on for proxy requests (default: `8080`). HTTPS MITM proxy is run on this port when `WEB4_KEY_FILE` and `WEB4_CERT_FILE` are provided.\n- `FAST_NEAR_URL` - URL of [fast-near](https://github.com/vgrichina/fast-near) RPC server to use for NEAR API. Overrides NEAR RPC config selected by `NODE_ENV`.\n\n# Frequently Asked Questions\n\n## What are the key advantages of web4?\n* Censorship resistance through decentralized blockchain hosting\n* Low cost - only pay for transactions\n* Permanent availability via NEAR blockchain\n\n## How does authentication work with web4?\nAuthentication is handled through `/web4/login` and `/web4/logout` endpoints. Account information is stored in cookies, with the current account ID available in `web4_account_id` cookie. Example usage:\n\n```javascript\n// Login\nwindow.location.href = '/web4/login'\n// Get current user\nconst accountId = Cookies.get('web4_account_id')\n```\n\nSee the Authentication section above for more details.\n\n## What's the difference between web4/login and integrating a wallet directly?\nUsing web4's authentication endpoints allows your application to remain wallet-agnostic. Your app will continue working without modifications as wallet implementations change. See [wallet integration guide](https://docs.near.org/tools/wallet-selector) for comparison.\n\n## How do I handle large files?\nNEARFS is the recommended way to store large files on web4. Deploy files using:\n```bash\nnpx web4-deploy --nearfs ./path/to/files\n```\nSee [web4-deploy docs](https://github.com/vgrichina/web4-deploy#readme) for more options.\n\n## Can I use web4 with Rust?\nYes! Start with the [Rust starter project](https://github.com/zavodil/near-web4-contract):\n```bash\ngit clone https://github.com/zavodil/near-web4-contract\ncd near-web4-contract\n./build.sh\n```\n\n## How do I deploy my web4 site?\nUse web4-deploy:\n```bash\nnpx web4-deploy ./dist\n```\nThis uploads files to IPFS/NEARFS and updates your smart contract. See [deployment guide](https://github.com/vgrichina/web4-deploy#readme).\n\n## How can I fetch account state?\nUse the web4 RPC endpoint:\n```bash\ncurl https://rpc.web4.near.page/account/your-account.near/state\n```\n\n## How can I store NFTs on web4?\nDeploy a web4 contract implementing the [NEP-171 standard](https://nomicon.io/Standards/NonFungibleToken/Core). Example:\n```bash\ngit clone https://github.com/near-examples/NFT\ncd NFT\nyarn deploy\n```\n\n## How can I access my local app bundle?\nRun local web4 gateway:\n```bash\nnpx web4-near\n```\nThen access your app at `https://your-account.near.page`\n\n## Can the web4 RPC return different data than direct contract calls?\nYes, if the RPC indexer falls behind the latest blocks. Check indexer status:\n```bash\ncurl https://rpc.web4.near.page/status\n```\n\n## How do I deploy to subaccounts?\nSubaccounts are not currently supported by web4. Use custom domains instead - see [custom domain setup guide](https://github.com/vgrichina/web4/wiki/Custom-Domains).\n\n# Priorities\n\nThis project aims to make trade offs based on these priorities:\n\n- Performance\n- Ease of deployment at scale\n- Hackability\n- Correctness\n- Completeness\n\n# Roadmap\n\n- Serve websites\n    - [x] Serve arbitrary GET requests\n    - [ ] Serve arbitrary POST requests\n    - [x] Load content from HTTP URLs\n    - [x] Load content from IPFS URLs\n    - [x] Load content from [NEARFS](https://github.com/vgrichina/nearfs) URLs\n    - [ ] Load content from ArWeave URLs\n    - [ ] Route configuration for better caching, etc\n- Access NEAR\n    - [x] Access view calls via GET requests\n    - [ ] Access view calls via POST requests\n    - [x] Post transactions with POST through wallet redirect\n    - [ ] Polish login and transaction flow with wallet\n    - [ ] Support different wallets from wallet-selector\n- Decentralization\n    - [x] Standalone server to run\n    - [x] .near domain support through HTTPS MITM proxy\n    - [x] Proxy auto-configuration file\n    - [ ] User-friendly installer\n    - [ ] Expose IPFS gateway on every .near.page website\n    - [ ] Expose fast-near RPC on every .near.page website\n- Prepare for wider use\n    - [x] Publish standalone package runnable with `npx`\n    - [ ] Tests\n    - [ ] Documentation\n    - [ ] Landing page\n    - [ ] Examples on different languages\n    - [ ] More efficient binary-based API (`web4_raw_get`)\n    - [x] Custom domain support\n    - [ ] Abuse report system (token curated registry or smth like that)\n    - [ ] Billing\n- Future direction\n    - [x] Upload to IPFS and pin (see [web4-deploy](https://github.com/vgrichina/web4-deploy))\n    - [ ] Upload to ArWeave\n    - [ ] Built-in per user statsd, including over http\n    - [ ] Pubsub protocol\n    - [ ] Direct messages protocol\n    - [ ] Indexer API\n    - [ ] Private storage\n    - [ ] Private messages\n    - [ ] Voice API\n    - [ ] web4 wallet\n    - [ ] App launcher for wallet (pre-selecting necessary account in app)\n    - [ ] Instant mobile apps using WebAssembly\n\n# Contributing\n\nWe welcome contributions to web4! Here's how you can help:\n\n## Join the Community\nJoin our [Telegram group](https://t.me/web4near) to discuss ideas, ask questions, and connect with other developers.\n\n## Share Your Examples\nWe need more example applications, especially:\n- Templates for different frameworks (React, Vue, Angular, etc.)\n- Apps in different languages (Rust, AssemblyScript, JavaScript)\n- Integration examples with various NEAR protocols\n- Real-world applications showcasing web4 capabilities\n\n## Development\n- Check out [open issues](https://github.com/vgrichina/web4/issues)\n- Submit bug reports and feature requests\n- Improve documentation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvgrichina%2Fweb4","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvgrichina%2Fweb4","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvgrichina%2Fweb4/lists"}