{"id":40380361,"url":"https://github.com/dsp-testing/stunning-sniffle","last_synced_at":"2026-01-20T12:02:07.263Z","repository":{"id":68387227,"uuid":"500367064","full_name":"dsp-testing/stunning-sniffle","owner":"dsp-testing","description":"Lovely Block","archived":false,"fork":false,"pushed_at":"2023-10-20T07:39:38.000Z","size":91,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2023-10-20T13:32:24.851Z","etag":null,"topics":["github-blocks"],"latest_commit_sha":null,"homepage":"","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/dsp-testing.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}},"created_at":"2022-06-06T09:19:30.000Z","updated_at":"2022-06-08T08:31:59.000Z","dependencies_parsed_at":"2023-02-27T21:45:52.083Z","dependency_job_id":null,"html_url":"https://github.com/dsp-testing/stunning-sniffle","commit_stats":null,"previous_names":[],"tags_count":3,"template":null,"template_full_name":null,"purl":"pkg:github/dsp-testing/stunning-sniffle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsp-testing%2Fstunning-sniffle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsp-testing%2Fstunning-sniffle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsp-testing%2Fstunning-sniffle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsp-testing%2Fstunning-sniffle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dsp-testing","download_url":"https://codeload.github.com/dsp-testing/stunning-sniffle/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsp-testing%2Fstunning-sniffle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28603299,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T12:01:53.233Z","status":"ssl_error","status_checked_at":"2026-01-20T12:01:46.545Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["github-blocks"],"created_at":"2026-01-20T12:02:06.389Z","updated_at":"2026-01-20T12:02:07.243Z","avatar_url":"https://github.com/dsp-testing.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitHub Blocks Template\n\n\u003e 📣 Use this repository as a starter template if you're a GitHub user interested in building your own custom Blocks!\n\n**Beware!** The videos on this page cover an earlier version of Blocks; the text of this page has the latest information.\n\nThe project is built with [React](https://reactjs.org/), [Typescript](https://www.typescriptlang.org/), and [Vite](https://vitejs.dev/). We'll guide you through how to use it.\n\nHere's a short tutorial video on how to get started creating your own block:\n\n[Tutorial Video](https://user-images.githubusercontent.com/8978670/156399836-96acfff1-e44d-4047-b508-6e3e4e83f68c.mp4)\n\nHere's a short tutorial video on the Blocks API:\n\n[Blocks API](https://user-images.githubusercontent.com/8978670/156633540-64d90ce8-9df6-48ce-98ee-6d99a796227a.mp4)\n\n#### GitHub Blocks API\n\nA Block is a React component; it receives props and returns JSX. The Blocks application provides props describing the content to render, and also callback props that Blocks can use to update content or metadata, or call the GitHub API.\n\nThere are two kinds of of Blocks: File Blocks and Folder Blocks. Their API is mostly the same, except that File Blocks receive file content and Folder Blocks receive folder content.\n\nAll blocks receive the following props:\n\n```ts\ninterface CommonBlockProps {\n  // metadata from `blocks.config.json`\n  block: {\n    id: string;\n    type: string;\n    title: string;\n    description: string;\n    entry: string;\n    matches?: string[];\n  };\n\n  // context about the repo, file / folder, and version\n  context: {\n    path: string;\n    file: string; // for File Blocks\n    folder: string; // for Folder Blocks\n    repo: string;\n    owner: string;\n    sha: string;\n  };\n\n  // arbitrary metadata for Blocks to store configuration etc.\n  metadata: any;\n  onUpdateMetadata: (newMetadata: any) =\u003e void;\n\n  // callback to call any GET endpoint in the GitHub API:\n  // https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps\n  // e.g. `/repos/{owner}/{repo}/contributors`\n  onRequestGitHubData: (\n    path: string,\n    params: Record\u003cstring, any\u003e\n  ) =\u003e Promise\u003cany\u003e;\n\n  onNavigateToPath: (path: string) =\u003e void;\n}\n```\n\nFile Blocks additionally receive\n\n```ts\ninterface FileBlockProps {\n  // the file content\n  content: string;\n  // callback to update the file content\n  onUpdateContent: (newContent: string) =\u003e void;\n\n  // the original file content\n  originalContent: string;\n\n  // whether or not the user can edit the content\n  isEditable: boolean;\n}\n```\n\nFolder Blocks additionally receive\n\n```ts\ninterface FolderBlockProps {\n  // flat list of files and folders in the tree\n  tree: {\n    path?: string;\n    mode?: string;\n    type?: string;\n    sha?: string;\n    size?: number;\n    url?: string;\n  }[];\n}\n```\n\n`metadata` is a free-form prop that can be used to store arbitrary data about the file. It's up to you to decide what you want to store in this object: anywhere from definitions of data visualizations in a charts Block to annotations for a code Block. This is unique per file/folder per Block and stored within a [`.github/blocks/file/`](https://github.com/githubnext/blocks-tutorial/tree/main/.github/blocks) folder within the viewed repo. To update the metadata, you can call the `onUpdateMetadata` prop with the updated data; the user will be prompted to accept the change and create a new commit in the repo.\n\nFile Blocks can implement editable content by calling `onUpdateContent` to update the current content. The Blocks application has a Save button which prompts the user to accept the change and create a new commit (or branch) in the repo. When content has been updated but not yet committed, the `originalContent` prop contains the original file content, so the block can show a diff. When the `isEditable` flag is false, the user does not have permission to edit the file, so the block should disable editing.\n\nA few caveats and callouts:\n\n- You can import CSS files or split your block into multiple TypeScript files, and everything will be bundled with your block.\n- You can use any third-party dependencies from NPM; just add them with `yarn add` and import them as usual, and they'll be bundled with your block.\n- The [GitHub Primer React components](https://primer.style/react/) are already included as a dependency\n- Your Block entry file **must have the Block component as its default export** so the GitHub Blocks application can find it.\n- To make authenticated requests to the GitHub API, create a [personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) (with `repo` scope) and pass it when you start the dev server:\n\n```\nVITE_GITHUB_PAT=${your personal access token} yarn start\n```\n\nor put it in your [`.env`](https://vitejs.dev/guide/env-and-mode.html#env-files) file in the project root directory.\n\n##### Relevant repos\n\n[Blocks examples](https://github.com/githubnext/blocks-examples)\n\nExample blocks that we've built to showcase the API.\n\n[Blocks utility library](https://github.com/githubnext/blocks-dev)\n\nThis template project includes a dependency on the GitHub Blocks utility library, which contains types and functions to make it easier to build Blocks. You can import them from `@githubnext/blocks`; see [the repository page](https://github.com/githubnext/blocks-dev) for more detail.\n\n## Setup\n\nThis repo is a template! To use it just click on the \"Use this template\" button on the top right to set it up for your use.\n\n\u003cimg width=\"495\" alt=\"Screen Shot 2021-12-06 at 12 29 29 PM\" src=\"https://user-images.githubusercontent.com/8978670/144893319-5d45ab5c-12c0-42b4-99f8-97f658deb03b.png\" /\u003e\n\nThe button will take you to a screen to specify what you want to name your own repo.\n\n\u003cimg width=\"801\" alt=\"Screen Shot 2021-12-06 at 12 29 17 PM\" src=\"https://user-images.githubusercontent.com/8978670/144893351-25b24bfa-3400-4e92-9a2a-618b3ac06a5e.png\" /\u003e\n\n## Step 1. Develop locally\n\n```bash\ngit clone \u003crepo URL\u003e\nyarn # install dependencies\nyarn start # start the dev server\n```\n\nA development server should now be running on [localhost:4000](localhost:4000).\n\n## Step 2. View your Blocks within a sandbox\n\nWhen you visit [localhost:4000](localhost:4000) in your browser, you'll see an interface where you can test out your Block.\n\nThis starter project has one example folder block and one example file block.\n\n[Sandbox video](https://user-images.githubusercontent.com/8978670/144666304-b9012177-aed6-4c26-afc3-3de8c8d6d0ad.mov)\n\nYou can play with two bits of the interface to view your Blocks:\n\n1. **Input file or folder**: An input that accepts the path to a file or a folder on github.com. Here are some valid file/folder paths.\n\n- https://github.com/facebook/react/blob/main/README.md (file)\n- https://github.com/facebook/react/blob/0.3-stable/README.md (file)\n- https://github.com/facebook/react/blob/main/packages/react-dom/index.js (file)\n- https://github.com/facebook/react/ (folder)\n- https://github.com/facebook/react/tree/0.3-stable (folder)\n- https://github.com/facebook/react/tree/main/packages (folder)\n\n2. **List of custom blocks**: A menu of the blocks that you have defined in `blocks.config.json` (see below; for now this contains the example file and folder blocks)\n\nOnce you've entered a valid path, choose a block from the menu; the file or folder content should be rendered beneath. Check your console for errors if something isn't working!\n\n## Step 3. Build your custom Blocks with the GitHub Blocks API\n\nTo create your own custom blocks you need to do two things:\n\n### Step 3.1: Define your custom block\n\nIf you open up `/blocks.config.json`, you'll notice an array of block objects with the definitions for each custom block. It looks like this:\n\n```ts\ninterface BlockDefinition {\n  type: \"file\" | \"folder\";\n  id: string;\n  title: string;\n  description: string;\n  entry: string;\n  matches?: string[]; // An array of globs written in picomatch syntax. See https://github.com/micromatch/picomatch for examples.\n}\n```\n\nYou have to define these properties for your own custom Block.\n\nFrom top to bottom:\n\n- `type` determines whether this block applies to files or folders.\n- `id` is an identifier string for this block, like `\"code-block\"`. GitHub Blocks uses this to determine which block to render; it needs to be unique within your project.\n- `title` and `description` control how your block appears within the GitHub Blocks application.\n- `entry` is the path (relative to the project root) to the block's entry point, like `\"blocks/example-file-block/index.tsx\"`.\n- `matches` is an array of globs describing filenames for which GitHub Blocks should show this block as an option, like `[\"*.json\"]` for a block that handles JSON files, or `[\"*\"]` for one that handles any file. (The glob syntax follows https://github.com/micromatch/picomatch)\n\n### Step 3.2: Code your Block\n\nYour code goes in the `blocks/` directory. Here you'll find the two example blocks as a starting point. You can modify them, rename them (don't forget to update `blocks.config.json`), or just delete them.\n\n## Step 4. Deploy your Blocks to production\n\nTo make your custom block accessible to the GitHub Blocks application, there are a few steps you need to take:\n\n### Step 4.1: Add the topic `github-blocks` to your repo (optional)\n\nIf you want your blocks to show up in the block picker in GitHub Blocks, you need to tag this repository with the topic `github-blocks` so the application can find it.\n\n\u003cimg width=\"323\" alt=\"Screen Shot 2021-12-03 at 2 54 55 PM\" src=\"https://user-images.githubusercontent.com/8978670/144665902-63543c98-2486-4e13-9c54-f1d4bc6544a4.png\" /\u003e\n\n**This step is optional!** If you aren't ready to share your block with others, don't tag the repo. Your blocks won't show up in the block picker by default, but you can paste the repo URL (`https://github.com/{owner}/{repo}`) into the search box at the top of the block picker to search blocks in the repo.\n\n### Step 4.2: Push a new tag\n\nThis template includes a GitHub Action to build a production version of your block. All you need to do to kick off the build process is create a new tag:\n\n```bash\ngit tag 0.9.0 # Create a new tag with your own version number\ngit push --tags # Push the tag to GitHub\n```\n\n### Step 4.3: Wait for the build process to finish\n\nLook under Actions for your repo to see that your build has finished. The latest successful build should now be accessible in the GitHub Blocks application.\n\nFrom the repository settings page, make sure that your workflow has **Read and write** permissions or the action will fail with a 403 error.\n\n\u003cimg width=\"805\" alt=\"Screen Shot 2022-05-11 at 8 14 06 AM\" src=\"https://user-images.githubusercontent.com/5148596/167847856-22ad190a-d73c-4b97-a0e2-c3c854db0d4f.png\"\u003e\n\n\u003cimg width=\"1097\" alt=\"Screen Shot 2021-12-03 at 3 03 33 PM\" src=\"https://user-images.githubusercontent.com/8978670/144665796-cb1ff450-c872-47c5-90b3-f74aea10286b.png\" /\u003e\n\n\u003cimg width=\"152\" alt=\"Screen Shot 2021-12-03 at 3 02 10 PM\" src=\"https://user-images.githubusercontent.com/8978670/144665673-431e28f9-9e9d-43b3-87f8-1e5d98bed92c.png\" /\u003e\n\n## Troubleshooting\n\n- When developing folder blocks you might hit a \"Something went wrong\" message if you reach the rate limit of the GitHub API. This is because we're hitting the API unauthenticated. You can avoid this by configuring a personal access token (see above).\n\n- If your Actions build fails, try running `yarn build` locally.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsp-testing%2Fstunning-sniffle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdsp-testing%2Fstunning-sniffle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsp-testing%2Fstunning-sniffle/lists"}