{"id":14378854,"url":"https://github.com/morris/vanilla-prime","last_synced_at":"2025-04-04T18:05:38.185Z","repository":{"id":254849237,"uuid":"836458621","full_name":"morris/vanilla-prime","owner":"morris","description":"A simpler, more sustainable way of web development","archived":false,"fork":false,"pushed_at":"2025-02-15T19:35:25.000Z","size":162,"stargazers_count":212,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-28T17:06:05.838Z","etag":null,"topics":["css","html","javascript","vanilla"],"latest_commit_sha":null,"homepage":"https://morris.github.io/vanilla-prime","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/morris.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2024-07-31T22:37:59.000Z","updated_at":"2025-03-12T23:57:46.000Z","dependencies_parsed_at":"2024-12-21T09:06:16.391Z","dependency_job_id":"27941046-c62c-47a2-982b-c0cb25d5a466","html_url":"https://github.com/morris/vanilla-prime","commit_stats":null,"previous_names":["morris/vanilla-prime"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fvanilla-prime","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fvanilla-prime/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fvanilla-prime/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morris%2Fvanilla-prime/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/morris","download_url":"https://codeload.github.com/morris/vanilla-prime/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247226213,"owners_count":20904465,"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":["css","html","javascript","vanilla"],"created_at":"2024-08-28T11:01:03.951Z","updated_at":"2025-04-04T18:05:38.167Z","avatar_url":"https://github.com/morris.png","language":"TypeScript","readme":"# Vanilla Prime\n\nA simpler, more sustainable way of web development. A spiritual successor to [VANILLA TODO](https://github.com/morris/vanilla-todo), further into real-world practice.\n\nNo frameworks, no bundlers, no required dependencies.\nJust web standards, patterns, a unix-style toolset, and some elbow grease.\n\nVanilla Prime is not meant to be _easy_.\nFrom a developer's perspective,\nit is certainly less ergonomic than your fully integrated framework du jour.\n\nBut it can be learned,\nand you will acquire deep knowledge of the web platform,\nand your websites will be performant\nand lightweight\nand timeless\nand independent\nand hackable (in a good way),\nand respect your user's and the world's resources.\n\n\u003e Vanilla Prime is the Dark Souls of web development stacks:\u003cbr\u003e\n\u003e Difficult to get into, hard to master, but incredibly rewarding.\n\nThis repository serves as a guide to Vanilla Prime,\nas well as boilerplate for adopting it in new projects,\nlest we eternally suffer from framework churn,\nand never shake the ghastly, over-engineered coil\nof contemporary web development.\n\n## Quick Start\n\n- Install [Node.js](https://nodejs.org/) \u003e= 20.\n- Open a terminal.\n- Run `git clone --depth=1 https://github.com/morris/vanilla-prime.git my-website`.\n- Run `cd my-website`.\n- Run `npm install`.\n- Run `npm run dev`.\n- Visit http://localhost:8080.\n- Work on `./src`, `./public`, and anything else really.\n- Run `npm run build`.\n- Deploy `./dist` somewhere.\n\n---\n\nOnly differentiating or novel concepts are explained in this guide.\nIntermediate understanding of the web platform, and a curious mind, is wanted.\nInspect and experiment with the given boilerplate along the way.\n**Happy hacking!**\n\n## Toolset\n\n- [Node.js](https://nodejs.org/) to run most other tools listed here.\n- [TypeScript](https://www.typescriptlang.org/) for JavaScript type safety and correctness.\n- [SCSS](https://sass-lang.com/) for CSS preprocessing.\n- [s4d](https://github.com/morris/s4d) as a local development server with live reload and SPA support.\n- [exdom](https://github.com/morris/exdom) as a supporting runtime library.\n- [Playwright](https://playwright.dev/) for end-to-end and unit testing.\n- [c8](https://github.com/bcoe/c8) for test coverage.\n- [terser](https://terser.org/) for JavaScript minification.\n- [cbst](https://github.com/morris/cbst) for cache busting.\n- [Prettier](https://prettier.io/) for code formatting.\n- [ESLint](https://eslint.org/) for JavaScript/TypeScript linting.\n- [Stylelint](https://stylelint.io/) for CSS linting.\n\nAll of these are optional.\nIn particular, TypeScript and SCSS are not strictly vanilla,\nand may be dropped for even more purity.\n\nYou will need to get familiar with the terminal and shell scripting,\nwhich serves as the tooling's glue.\n\n## Public Directory\n\nThe `./public` directory is the root directory for standard static files and assets,\ne.g. HTML, CSS, JavaScript, images, and so on.\n\nThe public directory is served during local development,\nand should be deployable to a static web server as-is.\n\nSome files in the public directory may be generated from source files.\nFurther production optimizations may use the public directory as input.\n\n## Source Directory\n\nThe `./src` directory is for non-standard source files that need to be compiled (if any),\ne.g. TypeScript and SCSS files.\n\nThe source directory has the same structure as the public directory.\n\n## Scripts Directory\n\nThe `./scripts` directory contains shell scripts for development, testing and\nbuilding the project.\n\nIt is recommended reading through the shell scripts\n(and the various config files in the project root)\nto understand their purpose, and to be able to adapt them as you see fit.\n\n## Reasonable System for CSS Stylesheet Structure (rscss)\n\nFollow [rscss](https://rstacruz.github.io/rscss/) when authoring HTML and CSS.\nIt strikes a balance between structure and flexibility and aligns\nwell with the rest of Vanilla Prime's architecture.\n\n## Large Module Files\n\nWrite rather _large module files_, e.g. capturing a complete feature or domain.\nThis reduces network calls and simplifies\n[speculative loading](https://developer.mozilla.org/en-US/docs/Web/Performance/Speculative_loading).\n\nDo not create one file per function or class or other code unit.\nDo not use barrel indexes.\nUse code folding to navigate large files.\n\n## Mount Functions\n\nUse _mount functions_ to organize UI code,\ne.g. interactive components and dynamic behaviors.\n\nMount functions accept a DOM element as their first argument.\nTheir responsibility is to set up initial state, event listeners, and provide behavior\nand rendering for the target element (all of which are optional).\n\nMount functions do not create or own their target elements.\nTarget elements must be created before mounting.\n\nA mount function for a component will often set some rigid initial HTML\nand define an idempotent update function\nthat updates the dynamic parts of the component's DOM.\nThe update function is usually called in response to certain DOM events.\n\nAvoid manipulating the DOM directly from event handlers.\n\nConsider toggling visibility\ninstead of constructing different DOM trees based on some state.\n\n## Communicate via DOM Events\n\nUse [DOM events](https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events)\nto communicate across the user interface.\nUse `CustomEvent` with `detail` to transmit data.\n\n_Data events_ flow from parent components to child components\nand do not bubble up.\nData events are in noun-form.\n\n_Action events_ bubble up the DOM,\nusually resulting in some parent component state change,\nwhich is in turn propagated downwards through data events.\nAction events are in verb-form.\n\n## Reconciliation\n\n_Reconciliation_ is the rendering and re-rendering of a variable number of\ndynamic elements in a given container.\n\nAlas, for reconciliation we have not yet discovered an efficient vanilla form.\nFor now, use `reconcile` from [exdom](https://github.com/morris/exdom).\n\n## Vendoring\n\nUse _vendoring_ when importing third-party libraries,\ni.e. copy library files into a project's source or public directory\nso that there's no need for bundling.\n\nTo get pinned versions and type safety, install packages with `npm` first,\nand copy the necessary files from `./node_modules/\u003cpackage\u003e` to `./src/js/vendor`.\n\nThen, create a `./src/js/vendor/\u003cpackage\u003e.d.ts` file containing `export * from '\u003cpackage\u003e';`.\nAutomate this in `./scripts/vendor.sh`.\n\n## Tests\n\nUse [Playwright](https://playwright.dev/) for unit and end-to-end tests.\nThe provided test setup supports test coverage for both.\n\n- Run `npx playwright install` to install Playwright browsers (once).\n- Run `npm run test` for unit and E2E tests on Chromium.\n- Run `npm run test-coverage` for test coverage.\n- Run `npm run test-e2e` for E2E tests on mainstream browsers.\n- Run `npm run test-ui` for interactive tests via the Playwright UI.\n\nHack on scripts and config files as needed.\n\n## For Library Authors\n\n### JavaScript\n\nConsider writing your entire library in one large ES module file.\nOtherwise, provide individual ES modules, as well as a bundled ES module.\n\nProvide TypeScript typings (`*.d.ts`) or use [JSDoc](https://jsdoc.app/)\nto provide typings.\n\nAvoid dependencies. If necessary, accept dependencies as function or constructor arguments.\n\n### CSS\n\n- Find a unique prefix fitting to the library.\n- Prefix component and helper class names.\n- Do not prefix element and variant class names.\n- Prefix CSS variables.\n- Provide individual CSS files.\n- Provide a bundled CSS file.\n\n## Resources\n\n- [MDN Web Docs](https://developer.mozilla.org/) for all things web platform.\n- [Can I use...](https://caniuse.com) for checking feature compatibility.\n- [rscss](https://rstacruz.github.io/rscss/) for organizing CSS (and HTML).\n- [VANILLA TODO](https://github.com/morris/vanilla-todo) (supporting research).\n\n## Beyond\n\nVanilla Prime still has some gaps and rough edges.\nNotable open questions include:\n\n- Can routing be done reasonably well with vanilla means?\n- Can vendoring be reasonably automated?\n- What is our stance on server-side generation?\n- How could environment variables be passed?\n\nThe work continues...\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorris%2Fvanilla-prime","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmorris%2Fvanilla-prime","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorris%2Fvanilla-prime/lists"}