{"id":26611120,"url":"https://github.com/phun-ky/frameport","last_synced_at":"2026-02-24T09:13:07.781Z","repository":{"id":47957946,"uuid":"212891967","full_name":"phun-ky/frameport","owner":"phun-ky","description":"A zero dependency package to effortlessly create responsive component previews in documentation using real media queries. Frameport dynamically generates iframes containing your HTML/CSS/JS, mimicking natural device viewports to test responsiveness, without any build steps or dependencies.","archived":false,"fork":false,"pushed_at":"2026-02-17T10:18:52.000Z","size":1831,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-17T13:51:41.828Z","etag":null,"topics":["css","design-system","designsystem","documentation","documentation-examples","documentation-helpers","frame","frames","html","iframe","iframes","javascript","media-queries","responsive","style-guide","styleguide","viewport"],"latest_commit_sha":null,"homepage":"https://phun-ky.net/projects/frameport/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phun-ky.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"phun-ky"}},"created_at":"2019-10-04T19:51:44.000Z","updated_at":"2026-02-17T10:18:56.000Z","dependencies_parsed_at":"2025-04-15T07:33:29.229Z","dependency_job_id":"fcfe578b-a111-4208-84b2-0b9582061fbf","html_url":"https://github.com/phun-ky/frameport","commit_stats":null,"previous_names":["phun-ky/responsive-documentation-examples"],"tags_count":64,"template":false,"template_full_name":null,"purl":"pkg:github/phun-ky/frameport","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phun-ky%2Fframeport","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phun-ky%2Fframeport/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phun-ky%2Fframeport/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phun-ky%2Fframeport/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phun-ky","download_url":"https://codeload.github.com/phun-ky/frameport/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phun-ky%2Fframeport/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29777829,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-24T04:54:30.205Z","status":"ssl_error","status_checked_at":"2026-02-24T04:53:58.628Z","response_time":75,"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":["css","design-system","designsystem","documentation","documentation-examples","documentation-helpers","frame","frames","html","iframe","iframes","javascript","media-queries","responsive","style-guide","styleguide","viewport"],"created_at":"2025-03-24T02:25:38.052Z","updated_at":"2026-02-24T09:13:07.759Z","avatar_url":"https://github.com/phun-ky.png","language":"TypeScript","funding_links":["https://github.com/sponsors/phun-ky"],"categories":[],"sub_categories":[],"readme":"# @phun-ky/frameport\n\n![logo](./public/logo-frameport-colored-package.svg)\n\n\u003e ⚡ Create interactive, responsive component previews for your style guides using real device viewports and media queries.\n\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-green.svg)](http://makeapullrequest.com) [![SemVer 2.0](https://img.shields.io/badge/SemVer-2.0-green.svg)](http://semver.org/spec/v2.0.0.html) ![npm version](https://img.shields.io/npm/v/@phun-ky/frameport) ![issues](https://img.shields.io/github/issues/phun-ky/frameport) ![license](https://img.shields.io/npm/l/@phun-ky/frameport) ![size](https://img.shields.io/bundlephobia/min/@phun-ky/frameport) ![npm](https://img.shields.io/npm/dm/%40phun-ky/frameport) ![GitHub Repo stars](https://img.shields.io/github/stars/phun-ky/frameport) [![codecov](https://codecov.io/gh/phun-ky/frameport/graph/badge.svg?token=VA91DL7ZLZ)](https://codecov.io/gh/phun-ky/frameport)\n\n- [@phun-ky/frameport](#phun-kyframeport)\n  - [About](#about)\n  - [Installation \\\u0026 Setup](#installation--setup)\n  - [API](#api)\n  - [Demo](#demo)\n  - [Options](#options)\n  - [Usage](#usage)\n    - [Basic usage](#basic-usage)\n      - [Typescript](#typescript)\n      - [ESM](#esm)\n      - [Script](#script)\n    - [Advanced usage](#advanced-usage)\n      - [Lazy](#lazy)\n  - [Features](#features)\n    - [Via DOM](#via-dom)\n    - [Use templates as a target](#use-templates-as-a-target)\n    - [Use targets with different template](#use-targets-with-different-template)\n      - [Allowed tags](#allowed-tags)\n  - [Contributing](#contributing)\n  - [Sponsor me](#sponsor-me)\n\n## About\n\nFrameport helps you embed live, responsive component previews in your documentation or style guide. It works by generating iframes with your HTML/CSS/JS that respect real media queries—so your components behave just like they do in actual devices.\n\n✅ Zero dependencies  \n✅ Framework agnostic  \n✅ Real device viewport emulation  \n✅ Instant iframe-based previews\n\n## Installation \u0026 Setup\n\n```shell-session\nnpm i -S @phun-ky/frameport\n```\n\nor with yarn:\n\n```shell-session\nyarn add @phun-ky/frameport\n```\n\n## API\n\nGo [here](https://github.com/phun-ky/frameport/blob/main/api/README.md) to read the full API documentation.\n\n## Demo\n\nClick [here for a demo on codepen.io](https://codepen.io/phun-ky/full/MWWWvLm)\n\n## Options\n\n| Option           | Type             | Required | Description                                                                                                                                                                                                                                        |\n| ---------------- | ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|                  |                  |          |                                                                                                                                                                                                                                                    |\n| html             | string           | ✓        | The html you want to use in the viewport example                                                                                                                                                                                                   |\n| height           | string \\| number |          | The height of the viewport, either as a string (e.g., '400') or a number (e.g., 400)                                                                                                                                                               |\n| width            | string \\| number |          | The width of the viewport, either as a string (e.g., '600') or a number (e.g., 600)                                                                                                                                                                |\n| className        | string           |          | Class names to be given the generated iframe                                                                                                                                                                                                       |\n| style            | string           |          | Inline styles (CSS) to be inserted into a `\u003cstyle\u003e` -tag in the `\u003chead\u003e`-tag of the generated html                                                                                                                                                 |\n| css              | string           |          | A CSS file to be appended to the `\u003chead\u003e`-tag of the generated html. **NOTE! This needs to be on the same domain and relative to root!**                                                                                                           |\n| code             | string           |          | Custom JavaScript code to be inserted into a `\u003cscript\u003e`-tag in the `\u003cbody\u003e`-tag in the generated html                                                                                                                                              |\n| javascript       | string           |          | A JavaScript file to be inserted in the `\u003cbody\u003e`-tag of the generated html. **NOTE! This needs to be on the same domain and relative to root!**                                                                                                    |\n| headers          | string[]         |          | An array of HTTP headers to include when fetching the HTML content                                                                                                                                                                                 |\n| viewports        | string           |          | The viewports to generate for examples. This is a string `wxh` for example: `375x667`. If you want more viewports, you can separate them with a comma: `375x667,360x740,768x1024`. **NOTE!** If not `viewports` are used, you need to set `width`! |\n| templateSelector | string           |          | Selector to the template                                                                                                                                                                                                                           |\n| templateElement  | HTMLElement      |          | Template element                                                                                                                                                                                                                                   |\n| target           | string           |          | To identify this as a target to use to generate the frameports                                                                                                                                                                                     |\n\n## Usage\n\n### Basic usage\n\n#### Typescript\n\nTypes can be found in `@phun-ky/frameport/dist/frameport.d.ts`.\n\n#### ESM\n\nEither import and run the required functions:\n\n```javascript\nimport frameport from '@phun-ky/frameport';\n\n// do stuff\nframeport(document.getElementById('target'), {\n  width: 667,\n  html: '\u003ch1\u003eFOO\u003c/h1\u003e'\n});\n```\n\n#### Script\n\nOr place these `script` in your web page:\n\n```html\n\u003cscript src=\"../path/to/frameport.js\"\u003e\u003c/script\u003e\n```\n\nAnd then follow the steps below that suites your needs :)\n\n### Advanced usage\n\nIf you want to control frameport a bit more, you have some options. Apply one of these attributes to the script element for different types of initialization:\n\n```html\n\u003cscript src=\"../frameport.js\" data-\u003cmanual|instant|dom|lazy\u003e\u003c/script\u003e\n```\n\n| Tag            | Description                                                           |\n| -------------- | --------------------------------------------------------------------- |\n| `data-manual`  | Makes `window.frameport()` available to be used when you feel like it |\n| `data-instant` | fires off `frameport()` right away                                    |\n| `data-dom`     | Waits for `DOMContentLoaded`                                          |\n| `data-lazy`    | Lazy loads `frameport()` per specced element                          |\n\nIf no attribute is applied, it will default to `data-dom`, as in, it will initialize when `DOMContentLoaded` is fired.\n\n#### Lazy\n\nIf you're importing frameport instead of with a script tag, you can use the following approach to apply lazy loading:\n\n```javascript\nimport frameport from '@phun-ky/frameport';\n\nexport const lazy = (): void =\u003e {\n  const frameportObserverTarget = new IntersectionObserver((els, observer) =\u003e {\n    els.forEach((el: IntersectionObserverEntry) =\u003e {\n      if (el.intersectionRatio \u003e 0) {\n        const {\n          dataset: {\n            frameportTemplate: templateSelector,\n            frameportVh: height,\n            frameportVw: width,\n            frameportCss: css,\n            frameportStyle: style,\n            frameportCode: code,\n            frameportJs: javascript,\n            frameportClass: className,\n            frameportHeaders: headers,\n            frameportViewports: viewports,\n          },\n        } = el.target as HTMLElement;\n\n        let html = el.target.innerHTML;\n        let templateElementToUse = el.target as HTMLElement;\n\n        if (templateSelector) {\n          const templateElement = document.querySelector(templateSelector);\n\n          if (templateElement) {\n            html = templateElement.innerHTML;\n            templateElementToUse = templateElement as HTMLElement;\n          }\n        }\n\n        const options = {\n          templateSelector,\n          templateElement: templateElementToUse,\n          height,\n          width,\n          html,\n          css,\n          style,\n          code,\n          javascript,\n          className,\n          headers: getHeaders(headers),\n          viewports,\n        };\n        dom(el.target as HTMLElement, options);\n        observer.unobserve(el.target);\n      }\n    });\n  });\n\n  document.querySelectorAll('[data-frameport]').forEach((el) =\u003e {\n    frameportObserverTarget.observe(el);\n  });\n};\n```\n\n## Features\n\n### Via DOM\n\nPlace the `script` tag at the bottom of your page, right before the `\u003c/body\u003e`-tag:\n\n```html\n\u003cscript src=\"../path/to/@phun-ky/frameport/dist/frameport.js\"\u003e\u003c/script\u003e\n```\n\nOr with a CDN:\n\n```html\n\u003cscript src=\"https://unpkg.com/@phun-ky/frameport/dist/frameport.js\"\u003e\u003c/script\u003e\n```\n\nAnd then follow the steps below to display the frameports you want :)\n\n### Use templates as a target\n\nWith this approach, the script will locate given template and produce frameports based on that template and insert them right after the template. The original template will be hidden:\n\n```html\n\u003cdiv\n  data-frameport\n  data-frameport-css=\"/css/ph.css\"\n  data-frameport-style=\"body{background-color: #84a295 !important;}\"\n  data-frameport-target\n  data-frameport-template=\"#template\"\n  data-frameport-vw=\"667\"\n  data-frameport-vh=\"375\"\n\u003e\u003c/div\u003e\n\u003cdiv id=\"template\"\u003e\n  \u003cmain class=\"ph\" style=\"height: 100vh\"\u003e\n    \u003cbutton class=\"ph button\" type=\"button\"\u003ePrimary\u003c/button\u003e\n  \u003c/main\u003e\n\u003c/div\u003e\n```\n\nThe content of the `[data-frameport]`-container is the html you want to display in the frameport.\n\n### Use targets with different template\n\nWith this approach, you decide where the frameports are added. The script will locate given target and produce frameports based on the given template and insert them in that target. The original template will be hidden:\n\n```html\n\u003cdiv\n  data-frameport\n  data-frameport-css=\"/css/ph.css\"\n  data-frameport-style=\"body{background-color: #84a295 !important;}\"\n  data-frameport-viewports=\"375x667,360x740,768x1024\"\n\u003e\n  \u003cmain class=\"ph\" style=\"height: 100vh\"\u003e\n    \u003cdiv class=\"ph app\"\u003e\n      \u003cp class=\"ph lead\"\u003eLook mah, I'm in an iframe\u003c/p\u003e\n      \u003cbutton class=\"ph button\" type=\"button\"\u003ePrimary\u003c/button\u003e\n    \u003c/div\u003e\n  \u003c/main\u003e\n\u003c/div\u003e\n```\n\nThe above example code will generate 3 iframes with given viewports.\n\nThe content of the `#template`-container is the html you want to display in the frameport.\n\nThis approach is useful if you want to use a device decorator to mimic appearance of a device.\n\n#### Allowed tags\n\n| tag                          | description                                                                                                                                                                                     | Required |\n| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |\n| **data-frameport**           | To identify this as the template to use for generating the responsive examples. **Required**                                                                                                    | 🔸       |\n| **data-frameport-width**     | The viewport width. **Required**                                                                                                                                                                | 🔸       |\n| **data-frameport-viewports** | The viewports to generate for examples. This is a string `wxh` for example: `375x667`. If you want more viewports, you can separate them with a comma: `375x667,360x740,768x1024`. **Required** | 🔸       |\n| data-frameport-target        | To identify this as a target to use to generate the frameports                                                                                                                                  |          |\n| data-frameport-template      | Selector to the template                                                                                                                                                                        |          |\n| data-frameport-height        | The viewport height.                                                                                                                                                                            |          |\n| data-frameport-css           | A CSS file to be appended to the `\u003chead\u003e`-tag of the generated html. **NOTE! This needs to be on the same domain and relative to root!** For example: `/dist/yourcss.css`                       |          |\n| data-frameport-style         | Inline styles (CSS) to be inserted into a `\u003cstyle\u003e` -tag in the `\u003chead\u003e`-tag of the generated html                                                                                              |          |\n| data-frameport-code          | Custom JavaScript code to be inserted into a `\u003cscript\u003e`-tag in the `\u003cbody\u003e`-tag in the generated html                                                                                           |          |\n| data-frameport-js            | A JavaScript file to be inserted in the `\u003cbody\u003e`-tag of the generated html. **NOTE! This needs to be on the same domain and relative to root!** For example: `/dist/yourjs.js`                  |          |\n| data-frameport-class         | Class names to be given the generated iframe                                                                                                                                                    |          |\n| data-frameport-headers       | An array of HTTP headers to include when fetching the HTML content                                                                                                                              |          |\n\n## Contributing\n\nIf you want to contribute, please read the [CONTRIBUTING.md](https://github.com/phun-ky/frameport/blob/main/CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](https://github.com/phun-ky/frameport/blob/main/CODE_OF_CONDUCT.md)\n\n## Sponsor me\n\nI'm an Open Source evangelist, creating stuff that does not exist yet to help get rid of secondary activities and to enhance systems already in place, be it documentation or web sites.\n\nThe sponsorship is an unique opportunity to alleviate more hours for me to maintain my projects, create new ones and contribute to the large community we're all part of :)\n\n[Support me with GitHub Sponsors](https://github.com/sponsors/phun-ky).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphun-ky%2Fframeport","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphun-ky%2Fframeport","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphun-ky%2Fframeport/lists"}