{"id":15414436,"url":"https://github.com/crutchcorn/the-fun-framework","last_synced_at":"2025-04-19T12:35:23.395Z","repository":{"id":172446438,"uuid":"649305204","full_name":"crutchcorn/the-fun-framework","owner":"crutchcorn","description":"🛝 An experimental homegrown JS framework.","archived":false,"fork":false,"pushed_at":"2023-07-20T06:33:03.000Z","size":821,"stargazers_count":23,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-12-20T07:48:06.974Z","etag":null,"topics":["alpinejs","framework","javascript","solidjs","vue"],"latest_commit_sha":null,"homepage":"https://crutchcorn.github.io/the-fun-framework/","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/crutchcorn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2023-06-04T12:49:15.000Z","updated_at":"2023-12-17T06:54:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"46992777-c6f0-4dcd-81a6-eaeb00491d61","html_url":"https://github.com/crutchcorn/the-fun-framework","commit_stats":{"total_commits":34,"total_committers":1,"mean_commits":34.0,"dds":0.0,"last_synced_commit":"362fafaa3dfd9e594329d39fc40ad5c597e73c7e"},"previous_names":["crutchcorn/framework-fun","crutchcorn/the-fun-framework"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crutchcorn%2Fthe-fun-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crutchcorn%2Fthe-fun-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crutchcorn%2Fthe-fun-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crutchcorn%2Fthe-fun-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crutchcorn","download_url":"https://codeload.github.com/crutchcorn/the-fun-framework/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231570302,"owners_count":18394110,"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":["alpinejs","framework","javascript","solidjs","vue"],"created_at":"2024-10-01T17:03:28.678Z","updated_at":"2024-12-28T00:03:43.961Z","avatar_url":"https://github.com/crutchcorn.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003ch1\u003eThe Fun Framework\u003c/h1\u003e\n\n\u003ca href=\"https://joypixels.com/profiles/emoji/playground-slide\"\u003e\n  \u003cimg\n    height=\"80\"\n    width=\"80\"\n    alt=\"playground slide\"\n    src=\"./other/slide.png\"\n  /\u003e\n\u003c/a\u003e\n\n\u003cp\u003eAn experimental homegrown JS framework.\u003c/p\u003e\n\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/crutchcorn/the-fun-framework/build.yml?branch=main)](https://github.com/crutchcorn/the-fun-framework/actions/workflows/build.yml?query=branch%3Amain)\n[![Test Status](https://img.shields.io/github/actions/workflow/status/crutchcorn/the-fun-framework/test.yml?branch=main\u0026label=tests)](https://github.com/crutchcorn/the-fun-framework/actions/workflows/test.yml?query=branch%3Amain)\n[![Pre-release](https://img.shields.io/npm/v/the-fun-framework.svg)](https://npm.im/the-fun-framework)\n[![gzip size](https://img.badgesize.io/https://unpkg.com/the-fun-framework@latest/dist/the-fun-framework.cjs?compression=gzip)](https://unpkg.com/browse/the-fun-framework@latest/dist/the-fun-framework.cjs)\n[![license](https://badgen.now.sh/badge/license/MIT)](./LICENSE.md)\n\n\u003c/div\u003e\n\nThe goals of this project are:\n\n- HTML-first templating\n- No VDOM\n- Implicit re-renders (instead of calling an update function manually, \"mutate\")\n\n## Installation\n\n```shell\nnpm install the-fun-framework\n```\n\n## Usage\n\n```html\n\u003c!-- index.html --\u003e\n\n\u003c!-- You can have multiple islands in one HTML file --\u003e\n\u003cdiv data-island-comp=\"App\"\u003e\n  \u003cp\u003e{{message}}\u003c/p\u003e\n\u003c/div\u003e\n```\n\n```typescript\n// index.ts\nimport { createState, registerComponent, render } from \"the-fun-framework\";\n\nfunction App() {\n  return {\n    message: \"Hello, world\",\n  };\n}\n\n// Register with the same name as `data-island-comp`\nApp.selector = \"App\";\nregisterComponent(App);\nrender();\n```\n\n### Conditional Display\n\n```html\n\u003c!-- index.html --\u003e\n\u003cdiv data-island-comp=\"Counter\"\u003e\n  \u003cbutton data-on-click=\"updateCount()\"\u003eCount\u003c/button\u003e\n  \u003cp\u003eCount: {{count.value}}\u003c/p\u003e\n  \u003cp data-if=\"count.value % 2 === 0\"\u003e{{count.value}} is even\u003c/p\u003e\n\u003c/div\u003e\n```\n\n```typescript\n// index.ts\nimport { createState, registerComponent, render } from \"the-fun-framework\";\n\nfunction Counter() {\n  let count = createState(0);\n\n  function updateCount() {\n    count.value++;\n  }\n\n  return {\n    count,\n    updateCount,\n  };\n}\n\n// Register with the same name as `data-island-comp`\nCounter.selector = \"Counter\";\nregisterComponent(Counter);\nrender();\n```\n\n### Loop Display\n\n```html\n\u003c!-- index.html --\u003e\n\u003cdiv data-island-comp=\"People\"\u003e\n  \u003ch1\u003eNames\u003c/h1\u003e\n  \u003cul\u003e\n    \u003cli data-for=\"item of list.value\" data-key=\"item.key\"\u003e{{item.name}}\u003c/li\u003e\n  \u003c/ul\u003e\n  \u003cbutton data-on-click=\"addPerson()\"\u003eAdd person\u003c/button\u003e\n\u003c/div\u003e\n```\n\n```typescript\n// index.ts\nfunction People() {\n  const list = createState([\n    {\n      name: \"Corbin\",\n      key: \"corbin\",\n    },\n    {\n      name: \"Ade\",\n      key: \"ade\",\n    },\n  ]);\n\n  let personCount = 0;\n  function addPerson() {\n    const newList = [...list.value];\n    ++personCount;\n    newList.push({\n      name: `Person ${personCount}`,\n      key: `person_${personCount}`,\n    });\n    list.value = newList;\n  }\n\n  return {\n    list,\n    addPerson,\n  };\n}\n\nPeople.selector = \"People\";\nregisterComponent(People);\nrender();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrutchcorn%2Fthe-fun-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrutchcorn%2Fthe-fun-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrutchcorn%2Fthe-fun-framework/lists"}