├── .changeset
└── config.json
├── .github
├── FUNDING.yml
└── workflows
│ ├── auto-release.yml
│ ├── changeset-release.yml
│ ├── docs-deploy.yml
│ └── test-docs-deploy.yml
├── .gitignore
├── .npmignore
├── .prettierignore
├── .prettierrc
├── .vscode
├── css_custom_data.json
└── settings.json
├── LICENSE.md
├── README.md
├── apps
├── lambda-examples
│ ├── .gitignore
│ ├── .npmignore
│ ├── .npmrc
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── bin
│ │ └── liveviewjs-lambda.ts
│ ├── cdk.json
│ ├── lib
│ │ └── liveviewjs-lambda-stack.ts
│ ├── package.json
│ ├── public
│ │ └── favicon.ico
│ ├── src
│ │ ├── client
│ │ │ └── index.ts
│ │ ├── example
│ │ │ ├── index.ts
│ │ │ ├── indexHandler.ts
│ │ │ └── liveTemplates.ts
│ │ ├── lambda
│ │ │ └── server.ts
│ │ └── lambdas
│ │ │ ├── http.ts
│ │ │ └── websocket.ts
│ ├── tsconfig-client.json
│ └── tsconfig.json
└── liveviewjs.com
│ ├── .gitignore
│ ├── .prettierrc
│ ├── README.md
│ ├── babel.config.js
│ ├── blog
│ ├── 2019-05-28-first-blog-post.md
│ ├── 2019-05-29-long-blog-post.md
│ ├── 2021-08-01-mdx-blog-post.mdx
│ ├── 2021-08-26-welcome
│ │ ├── docusaurus-plushie-banner.jpeg
│ │ └── index.md
│ └── authors.yml
│ ├── docs
│ ├── 01-overview
│ │ ├── _category_.json
│ │ ├── feedback.md
│ │ ├── gratitude.md
│ │ ├── introduction.md
│ │ ├── paradigm.md
│ │ └── runtimes.md
│ ├── 02-quick-starts
│ │ ├── _category_.json
│ │ ├── deno-build-first-liveview.md
│ │ ├── deno-run-examples.md
│ │ ├── get-liveviewjs-repo.md
│ │ ├── nodejs-build-first-liveview.md
│ │ └── nodejs-run-examples.md
│ ├── 03-anatomy-of-a-liveview
│ │ ├── _category_.json
│ │ ├── handle-event-details.md
│ │ ├── handle-info-background-task.md
│ │ ├── handle-info-pub-sub.md
│ │ ├── handle-info-user-initiated.md
│ │ ├── handle-info.md
│ │ ├── handle-params.md
│ │ ├── liveview-api.md
│ │ ├── mount-details.md
│ │ └── render-details.md
│ ├── 04-liveview-socket
│ │ ├── _category_.json
│ │ ├── liveviewsocket-api-context.md
│ │ ├── liveviewsocket-api-infos.md
│ │ ├── liveviewsocket-api-misc.md
│ │ ├── liveviewsocket-api-push.md
│ │ ├── liveviewsocket-api-uploads.md
│ │ ├── liveviewsocket-api.md
│ │ └── raw-liveviewsocket-api.md
│ ├── 05-lifecycle-of-a-liveview
│ │ ├── _category_.json
│ │ └── intro.md
│ ├── 06-user-events-slash-bindings
│ │ ├── _category_.json
│ │ ├── additional-bindings.md
│ │ ├── bindings-table.md
│ │ ├── overview.md
│ │ └── rate-limiting-bindings.md
│ ├── 07-forms-and-changesets
│ │ ├── _category_.json
│ │ ├── changesets.md
│ │ ├── overview.md
│ │ └── use-with-forms.md
│ ├── 08-file-upload
│ │ ├── _category_.json
│ │ ├── drag-and-drop.md
│ │ ├── image-preview.md
│ │ ├── overview.md
│ │ └── upload-config-options.md
│ ├── 09-real-time-multi-player-pub-sub
│ │ ├── _category_.json
│ │ ├── example-pub-sub.md
│ │ └── overview.md
│ ├── 10-client-javascript
│ │ ├── _category_.json
│ │ ├── client-hooks.md
│ │ ├── example-hook.md
│ │ └── overview.md
│ ├── 11-js-commands
│ │ ├── _category_.json
│ │ ├── add-remove-class.md
│ │ ├── dispatch-cmd.md
│ │ ├── overview.md
│ │ ├── push-cmd.md
│ │ ├── set-remove-attr.md
│ │ ├── show-hide-toggle-el.md
│ │ └── transition-cmd.md
│ ├── 12-webserver-integration
│ │ ├── _category_.json
│ │ ├── liveview-server-adaptor.md
│ │ ├── overview.md
│ │ └── support-webserver-x.md
│ └── 13-misc
│ │ ├── _category_.json
│ │ ├── debugging-wire.md
│ │ ├── flash.md
│ │ ├── livecomponents.md
│ │ ├── root-and-page-renderers.md
│ │ ├── security-topics.md
│ │ └── statics-and-dynamics.md
│ ├── docusaurus.config.js
│ ├── package-lock.json
│ ├── package.json
│ ├── sidebars.js
│ ├── src
│ ├── components
│ │ └── HomepageFeatures
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ ├── css
│ │ └── custom.css
│ └── pages
│ │ ├── index.module.css
│ │ └── index.tsx
│ ├── static
│ ├── .nojekyll
│ ├── CNAME
│ ├── fonts
│ │ ├── LibreFranklin-Italic-VariableFont_wght.ttf
│ │ └── LibreFranklin-VariableFont_wght.ttf
│ └── img
│ │ ├── diagrams
│ │ ├── liveview-lifecycle-heartbeat.svg
│ │ ├── liveview-lifecycle-http-phase.svg
│ │ ├── liveview-lifecycle-shutdown.svg
│ │ ├── liveview-lifecycle-user-and-server-events.svg
│ │ ├── liveview-lifecycle-websocket-join.svg
│ │ └── liveviewjs-lifecycle.svg
│ │ ├── favicon.ico
│ │ ├── features
│ │ ├── multiplayer.svg
│ │ ├── nirvana.svg
│ │ └── simple.svg
│ │ ├── logo.svg
│ │ └── screenshots
│ │ ├── liveviewjs_counter_liveview_rec.gif
│ │ ├── liveviewjs_examples_rec.gif
│ │ ├── liveviewjs_hello_liveview.png
│ │ ├── liveviewjs_hello_liveview_deno.png
│ │ ├── liveviewjs_hello_toggle_liveview_deno_rec.gif
│ │ └── liveviewjs_hello_toggle_liveview_rec.gif
│ ├── tailwind.config.js
│ └── tsconfig.json
├── liveviewjs-logo.png
├── old_docs
├── README.md
├── app-directory-structure.md
├── changesets.md
├── file-uploads.md
├── js-commands.md
├── liveview_lifecycle.md
├── routing.md
├── server_options.md
├── temp-assign.md
└── updating-html-title.md
├── package-lock.json
├── package.json
├── packages
├── core
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .npmignore
│ ├── .npmrc
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── CHANGELOG.md
│ ├── coverage
│ │ ├── clover.xml
│ │ └── coverage-final.json
│ ├── dist
│ │ ├── liveview.d.ts
│ │ ├── liveview.js
│ │ └── liveview.mjs
│ ├── jest.config.js
│ ├── mod.ts
│ ├── package-lock.json
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── index.ts
│ │ └── server
│ │ │ ├── adaptor
│ │ │ ├── __snapshots__
│ │ │ │ └── http.test.ts.snap
│ │ │ ├── csrfGen.ts
│ │ │ ├── files.ts
│ │ │ ├── flash.ts
│ │ │ ├── http.test.ts
│ │ │ ├── http.ts
│ │ │ ├── idGen.ts
│ │ │ ├── index.ts
│ │ │ ├── jsonSerDe.ts
│ │ │ ├── serDe.ts
│ │ │ ├── sessionFlashAdaptor.ts
│ │ │ ├── testFilesAdatptor.ts
│ │ │ └── websocket.ts
│ │ │ ├── changeset
│ │ │ ├── changeset.test.ts
│ │ │ ├── changeset.ts
│ │ │ └── index.ts
│ │ │ ├── fetch.d.ts
│ │ │ ├── index.ts
│ │ │ ├── live
│ │ │ ├── baseLiveView.test.ts
│ │ │ ├── index.ts
│ │ │ ├── liveComponent.test.ts
│ │ │ ├── liveComponent.ts
│ │ │ ├── liveView.test.ts
│ │ │ ├── liveView.ts
│ │ │ ├── router.test.ts
│ │ │ ├── router.ts
│ │ │ └── types.ts
│ │ │ ├── mime
│ │ │ ├── index.ts
│ │ │ └── mime.test.ts
│ │ │ ├── protocol
│ │ │ ├── phx.test.ts
│ │ │ ├── phx.ts
│ │ │ └── reply.ts
│ │ │ ├── pubsub
│ │ │ ├── index.ts
│ │ │ ├── pubSub.ts
│ │ │ └── singleProcessPubSub.ts
│ │ │ ├── server.ts
│ │ │ ├── session.ts
│ │ │ ├── socket
│ │ │ ├── index.ts
│ │ │ ├── liveSocket.test.ts
│ │ │ ├── liveSocket.ts
│ │ │ ├── liveViewManager-Uploads.test.ts
│ │ │ ├── liveViewManager.test.ts
│ │ │ ├── liveViewManager.ts
│ │ │ ├── structuredClone.ts
│ │ │ ├── types.ts
│ │ │ ├── util.test.ts
│ │ │ ├── util.ts
│ │ │ ├── ws
│ │ │ │ ├── wsEventHandler.ts
│ │ │ │ ├── wsHandler.test.ts
│ │ │ │ ├── wsHandler.ts
│ │ │ │ ├── wsLiveComponents.ts
│ │ │ │ └── wsUploadHandler.ts
│ │ │ ├── wsMessageRouter.test.ts
│ │ │ └── wsMessageRouter.ts
│ │ │ ├── templates
│ │ │ ├── diff.test.ts
│ │ │ ├── diff.ts
│ │ │ ├── helpers
│ │ │ │ ├── form_for.test.ts
│ │ │ │ ├── form_for.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── inputs.test.ts
│ │ │ │ ├── inputs.ts
│ │ │ │ ├── live_file_input.test.ts
│ │ │ │ ├── live_file_input.ts
│ │ │ │ ├── live_img_preview.test.ts
│ │ │ │ ├── live_img_preview.ts
│ │ │ │ ├── live_patch.test.ts
│ │ │ │ ├── live_patch.ts
│ │ │ │ ├── live_title.ts
│ │ │ │ ├── live_title_tag.test.ts
│ │ │ │ ├── live_title_tag.ts
│ │ │ │ ├── options_for_select.test.ts
│ │ │ │ ├── options_for_select.ts
│ │ │ │ ├── submit.test.ts
│ │ │ │ └── submit.ts
│ │ │ ├── htmlSafeString.test.ts
│ │ │ ├── htmlSafeString.ts
│ │ │ ├── index.ts
│ │ │ ├── jsCommands.test.ts
│ │ │ └── jsCommands.ts
│ │ │ ├── test
│ │ │ ├── liveviews.ts
│ │ │ └── wsAdaptor.ts
│ │ │ └── upload
│ │ │ ├── binaryUploadSerDe.test.ts
│ │ │ ├── binaryUploadSerDe.ts
│ │ │ ├── index.ts
│ │ │ ├── uploadConfig.test.ts
│ │ │ ├── uploadConfig.ts
│ │ │ ├── uploadEntry.test.ts
│ │ │ └── uploadEntry.ts
│ └── tsconfig.json
├── create-liveviewjs
│ ├── .gitignore
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ └── create
│ │ │ ├── cli.ts
│ │ │ └── index.ts
│ ├── templates
│ │ └── liveviewjs-app
│ │ │ ├── README.md
│ │ │ ├── app
│ │ │ ├── assets
│ │ │ │ ├── css
│ │ │ │ │ └── app.css
│ │ │ │ └── js
│ │ │ │ │ └── app.ts
│ │ │ ├── controllers
│ │ │ │ └── root
│ │ │ │ │ └── rootController.ts
│ │ │ ├── liveviews
│ │ │ │ └── demos
│ │ │ │ │ └── clickLiveView.ts
│ │ │ ├── middleware
│ │ │ │ └── demoTimestamp.ts
│ │ │ ├── models
│ │ │ │ └── counter.ts
│ │ │ ├── services
│ │ │ │ └── inMemory.ts
│ │ │ └── views
│ │ │ │ ├── liveviews
│ │ │ │ └── root.ejs
│ │ │ │ └── root
│ │ │ │ └── index.ejs
│ │ │ ├── config
│ │ │ └── app.ts
│ │ │ ├── env
│ │ │ ├── gitignore
│ │ │ ├── package-lock.json
│ │ │ ├── package.json
│ │ │ ├── tailwind.config.js
│ │ │ └── tsconfig.json
│ └── tsconfig.json
├── deno
│ ├── .gitignore
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── .vscode
│ │ └── settings.json
│ ├── README.md
│ ├── import_map.json
│ ├── mod.ts
│ ├── package.json
│ ├── public
│ │ ├── .keep
│ │ └── favicon.ico
│ ├── src
│ │ ├── client
│ │ │ └── index.ts
│ │ ├── deno
│ │ │ ├── broadcastChannelPubSub.ts
│ │ │ ├── fsAdaptor.ts
│ │ │ ├── index.ts
│ │ │ ├── jwtSerDe.ts
│ │ │ ├── server.ts
│ │ │ └── wsAdaptor.ts
│ │ ├── deps.ts
│ │ └── example
│ │ │ ├── autorun.ts
│ │ │ ├── index.ts
│ │ │ ├── indexHandler.ts
│ │ │ ├── liveTemplates.ts
│ │ │ ├── liveview
│ │ │ ├── router.ts
│ │ │ └── rtcounter.ts
│ │ │ └── oak.ts
│ └── tsconfig-client.json
├── examples
│ ├── .npmrc
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── CHANGELOG.md
│ ├── dist
│ │ ├── liveviewjs-examples.browser.js
│ │ ├── liveviewjs-examples.browser.js.map
│ │ ├── liveviewjs-examples.d.ts
│ │ ├── liveviewjs-examples.js
│ │ └── liveviewjs-examples.mjs
│ ├── mod.ts
│ ├── package-lock.json
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── datastore
│ │ │ └── InMemory.ts
│ │ ├── fetch.d.ts
│ │ ├── liveviews
│ │ │ ├── autoComplete
│ │ │ │ ├── data.test.ts
│ │ │ │ ├── data.ts
│ │ │ │ └── index.ts
│ │ │ ├── books
│ │ │ │ └── index.ts
│ │ │ ├── counter
│ │ │ │ ├── index.ts
│ │ │ │ └── realtime.ts
│ │ │ ├── dashboard
│ │ │ │ └── index.ts
│ │ │ ├── decarbonize
│ │ │ │ ├── data.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── liveComponent.ts
│ │ │ ├── fetch
│ │ │ │ ├── data.ts
│ │ │ │ └── index.ts
│ │ │ ├── hello
│ │ │ │ ├── helloName.ts
│ │ │ │ └── helloToggleEmoji.ts
│ │ │ ├── jsCommands
│ │ │ │ └── index.ts
│ │ │ ├── liveNav
│ │ │ │ └── index.ts
│ │ │ ├── liveSearch
│ │ │ │ ├── data.test.ts
│ │ │ │ ├── data.ts
│ │ │ │ └── index.ts
│ │ │ ├── pagination
│ │ │ │ ├── data.ts
│ │ │ │ └── index.ts
│ │ │ ├── photos
│ │ │ │ └── index.ts
│ │ │ ├── prints
│ │ │ │ └── index.ts
│ │ │ ├── servers
│ │ │ │ ├── data.ts
│ │ │ │ └── index.ts
│ │ │ ├── sorting
│ │ │ │ ├── data.ts
│ │ │ │ └── index.ts
│ │ │ ├── utils
│ │ │ │ └── index.ts
│ │ │ ├── volume
│ │ │ │ └── index.ts
│ │ │ └── volunteers
│ │ │ │ ├── data.test.ts
│ │ │ │ ├── data.ts
│ │ │ │ └── index.ts
│ │ ├── rollupEntry.ts
│ │ └── routeDetails.ts
│ └── tsconfig.json
├── express
│ ├── .gitignore
│ ├── .npmrc
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── dist
│ │ ├── liveviewjs-express.d.ts
│ │ ├── liveviewjs-express.js
│ │ └── liveviewjs-express.mjs
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── .keep
│ │ ├── favicon.ico
│ │ └── images
│ │ │ └── cats
│ │ │ ├── clenil.jpg
│ │ │ ├── flippers.jpg
│ │ │ ├── jorts.jpg
│ │ │ ├── kipper.jpg
│ │ │ ├── lemmy.jpg
│ │ │ ├── lissy.jpg
│ │ │ ├── mikkel.jpg
│ │ │ ├── minka.jpg
│ │ │ ├── misty.jpg
│ │ │ ├── nelly.jpg
│ │ │ ├── ninj.jpg
│ │ │ ├── pollito.jpg
│ │ │ ├── siegfried.jpg
│ │ │ ├── truman.jpg
│ │ │ └── washy.jpg
│ ├── rollup.config.js
│ ├── src
│ │ ├── client
│ │ │ └── index.ts
│ │ ├── example
│ │ │ ├── autorun.ts
│ │ │ ├── autorun_ios.ts
│ │ │ ├── express.ts
│ │ │ ├── index.ts
│ │ │ ├── indexHandler.ts
│ │ │ ├── ios.ts
│ │ │ ├── iosTemplates.ts
│ │ │ ├── liveTemplates.ts
│ │ │ └── liveview
│ │ │ │ ├── ios
│ │ │ │ ├── cat.ts
│ │ │ │ ├── catList.ts
│ │ │ │ └── data.ts
│ │ │ │ └── router.ts
│ │ ├── index.ts
│ │ └── node
│ │ │ ├── fsAdaptor.ts
│ │ │ ├── index.ts
│ │ │ ├── jwtSerDe.ts
│ │ │ ├── redisPubSub.ts
│ │ │ ├── server.ts
│ │ │ └── wsAdaptor.ts
│ ├── tsconfig-client.json
│ └── tsconfig.json
└── gen
│ ├── .gitignore
│ ├── .npmrc
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── _templates
│ ├── deno-project
│ │ └── new
│ │ │ ├── .gitignore.ejs.t
│ │ │ ├── .prettierignore.ejs.t
│ │ │ ├── .prettierrc.ejs.t
│ │ │ ├── README.md.ejs.t
│ │ │ ├── import_map.json.ejs.t
│ │ │ ├── package.json.ejs.t
│ │ │ ├── public
│ │ │ └── .keep.ejs.t
│ │ │ ├── src
│ │ │ ├── client
│ │ │ │ └── index.ts.ejs.t
│ │ │ ├── deps.ts.ejs.t
│ │ │ └── server
│ │ │ │ ├── autorun.ts.ejs.t
│ │ │ │ ├── index.ts.ejs.t
│ │ │ │ ├── liveTemplates.ts.ejs.t
│ │ │ │ ├── liveview
│ │ │ │ ├── hello.ts.ejs.t
│ │ │ │ └── router.ts.ejs.t
│ │ │ │ └── oak.ts.ejs.t
│ │ │ └── tsconfig-client.json.ejs.t
│ └── node-project
│ │ └── new
│ │ ├── .gitignore.ejs.t
│ │ ├── .npmrc.ejs.t
│ │ ├── .prettierignore.ejs.t
│ │ ├── .prettierrc.ejs.t
│ │ ├── README.md.ejs.t
│ │ ├── package.json.ejs.t
│ │ ├── public
│ │ └── .keep.ejs.t
│ │ ├── src
│ │ ├── client
│ │ │ └── index.ts.ejs.t
│ │ └── server
│ │ │ ├── autorun.ts.ejs.t
│ │ │ ├── express.ts.ejs.t
│ │ │ ├── index.ts.ejs.t
│ │ │ ├── liveTemplates.ts.ejs.t
│ │ │ └── liveview
│ │ │ ├── hello.ts.ejs.t
│ │ │ └── router.ts.ejs.t
│ │ ├── tsconfig-client.json.ejs.t
│ │ └── tsconfig.json.ejs.t
│ ├── dist
│ ├── cli.d.mts
│ ├── cli.mjs
│ ├── null_logger.d.mts
│ ├── null_logger.mjs
│ ├── post_exec.d.mts
│ ├── post_exec.mjs
│ ├── project_helper.d.mts
│ ├── project_helper.mjs
│ ├── prompts.d.mts
│ ├── prompts.mjs
│ ├── yargs.d.mts
│ └── yargs.mjs
│ ├── package.json
│ ├── src
│ ├── cli.mts
│ ├── null_logger.mts
│ ├── post_exec.mts
│ ├── project_helper.mts
│ ├── prompts.mts
│ └── yargs.mts
│ └── tsconfig.json
└── turbo.json
/.changeset/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/@changesets/config@2.0.1/schema.json",
3 | "changelog": "@changesets/cli/changelog",
4 | "commit": false,
5 | "fixed": [
6 | ["liveviewjs", "@liveviewjs/examples", "@liveviewjs/express", "@liveviewjs/gen", "@liveviewjs/lambda-examples"]
7 | ],
8 | "linked": [],
9 | "access": "public",
10 | "baseBranch": "main",
11 | "updateInternalDependencies": "patch",
12 | "ignore": ["@liveviewjs/deno-client", "liveviewjs-com"]
13 | }
14 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [floodfx]
2 |
--------------------------------------------------------------------------------
/.github/workflows/auto-release.yml:
--------------------------------------------------------------------------------
1 | name: AutoRelease
2 | on:
3 | push:
4 | branches:
5 | - main
6 |
7 | jobs:
8 | build:
9 | name: AutoRelease
10 | runs-on: ubuntu-latest
11 | steps:
12 | # checkout the code
13 | - name: Checkout
14 | uses: actions/checkout@v3
15 | with:
16 | fetch-depth: 0
17 | # setup node version
18 | - uses: actions/setup-node@v3.0.0
19 | with:
20 | node-version: 17
21 | # install dependencies and test
22 | - run: npm ci
23 | # - run: npm test
24 | # run rollup and save dist updates back to repo
25 | - run: npm run dist
26 | # commit back changes to dist
27 | - uses: stefanzweifel/git-auto-commit-action@v4
28 | with:
29 | commit_message: "automatically committing rollup output to dist"
30 | file_pattern: dist/*
31 | # publish to npm if version is different
32 | - uses: JS-DevTools/npm-publish@v1
33 | with:
34 | token: ${{ secrets.NPM_PUBLISH_TOKEN }}
35 | - name: Automatic GitHub Release
36 | uses: justincy/github-action-npm-release@2.0.2
37 | id: release
38 | - name: Print release output
39 | if: ${{ steps.release.outputs.released == 'true' }}
40 | run: echo Release ID ${{ steps.release.outputs.release_id }}
41 |
--------------------------------------------------------------------------------
/.github/workflows/changeset-release.yml:
--------------------------------------------------------------------------------
1 | name: Changeset Release
2 | on:
3 | push:
4 | branches:
5 | - main
6 |
7 | jobs:
8 | build:
9 | name: AutoRelease
10 | runs-on: ubuntu-latest
11 | steps:
12 | # checkout the code
13 | - name: Checkout
14 | uses: actions/checkout@v3
15 | with:
16 | fetch-depth: 0
17 | # setup node version
18 | - name: Setup Node
19 | uses: actions/setup-node@v3.0.0
20 | with:
21 | node-version: 18
22 | # install dependencies
23 | - name: Install dependencies
24 | run: npm ci
25 |
26 | # run turbo publish
27 | - name: Install dependencies
28 | run: npm run publish
29 |
30 | - name: Create Release Pull Request or Publish to npm
31 | id: changesets
32 | uses: changesets/action@v1
33 | with:
34 | publish: npm run cs:publish
35 | env:
36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37 | NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
38 |
39 | - name: Print Release
40 | if: ${{ steps.release.outputs.released == 'true' }}
41 | run: echo Release ID ${{ steps.release.outputs.release_id }}
42 |
--------------------------------------------------------------------------------
/.github/workflows/docs-deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to GitHub Pages
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | deploy:
10 | name: Deploy to GitHub Pages
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v3
14 | - uses: actions/setup-node@v3
15 | with:
16 | node-version: 18
17 |
18 | - name: Install dependencies in apps/liveviewjs.com
19 | run: npm install -w apps/liveviewjs.com
20 | - name: Build docusaurus website
21 | run: npm run build -w apps/liveviewjs.com
22 |
23 | # Popular action to deploy to GitHub Pages:
24 | # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
25 | - name: Deploy to GitHub Pages
26 | uses: peaceiris/actions-gh-pages@v3
27 | with:
28 | github_token: ${{ secrets.GITHUB_TOKEN }}
29 | # Build output to publish to the `gh-pages` branch:
30 | publish_dir: ./apps/liveviewjs.com/build
31 | user_name: floodfx
32 | user_email: donnie@floodfx.com
33 |
--------------------------------------------------------------------------------
/.github/workflows/test-docs-deploy.yml:
--------------------------------------------------------------------------------
1 | name: Test Docs Deploy
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - "*"
10 |
11 | jobs:
12 | test-deploy:
13 | name: Test Docs Build
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v3
17 | - uses: actions/setup-node@v3
18 | with:
19 | node-version: 18
20 | - name: Install dependencies in apps/liveviewjs.com
21 | run: npm install -w apps/liveviewjs.com
22 | - name: Build docusaurus website
23 | run: npm run build -w apps/liveviewjs.com
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .cache/
3 | .env
4 | .parcel-cache/
5 | .DS_Store
6 | coverage/lcov-report/
7 | coverage/lcov.info
8 | diffs/
9 | build/
10 | *.tgz
11 | .turbo
12 | .todo.md
13 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .parcel-cache/
2 | .vscode/
3 | coverage/
4 | node_modules/
5 | .editorconfig
6 | .eslintrc.js
7 | .gitignore
8 | .gitattributes
9 | .npmignore
10 | jest.config.js
11 | package-lock.json
12 | tsconfig.json
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .cache/
3 | .env
4 | dist/
5 | .parcel-cache/
6 | .DS_Store
7 | coverage/
8 | package-lock.json
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "useTabs": false,
4 | "printWidth": 120,
5 | "bracketSameLine": true
6 | }
--------------------------------------------------------------------------------
/.vscode/css_custom_data.json:
--------------------------------------------------------------------------------
1 | {
2 | "atDirectives": [
3 | {
4 | "name": "@tailwind",
5 | "description": "Use the @tailwind directive to insert Tailwind’s `base`, `components`, `utilities`, and `screens` styles into your CSS.",
6 | "references": [
7 | {
8 | "name": "Tailwind’s “Functions & Directives” documentation",
9 | "url": "https://tailwindcss.com/docs/functions-and-directives/#tailwind"
10 | }
11 | ]
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.watcherExclude": {
3 | "**/.git/objects/**": true,
4 | "**/.git/subtree-cache/**": true,
5 | "**/node_modules/**": true,
6 | "env-*": true
7 | },
8 | "files.exclude": {
9 | "**/.git": true,
10 | "**/.DS_Store": true
11 | },
12 | "css.customData": [".vscode/css_custom_data.json"],
13 | "[typescript]": {
14 | "editor.defaultFormatter": "esbenp.prettier-vscode",
15 | "editor.formatOnSave": true,
16 | "editor.tabSize": 2,
17 | "editor.codeActionsOnSave": {
18 | "source.organizeImports": true,
19 | "source.fixAll": true
20 | }
21 | },
22 | "deno.importMap": "packages/deno/import_map.json",
23 | "deno.enablePaths": ["packages/deno/mod.ts", "packages/deno/src/deno", "packages/deno/src/example"],
24 | "typescript.tsdk": "node_modules/typescript/lib"
25 | }
26 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021-2022 Donald Flood
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## LiveViewJS
2 |
3 | 
4 |
5 | *An HTML-first, "Get Stuff Done"-focused library for building LiveViews in NodeJS and Deno*
6 |
7 | Learn more at [LiveViewJS.com](https://www.liveviewjs.com)
8 |
--------------------------------------------------------------------------------
/apps/lambda-examples/.gitignore:
--------------------------------------------------------------------------------
1 | public/*.png
2 | public/*.gif
3 | public/*.jpg
4 | public/*.jpeg
5 | public/*.pdf
6 | public/js/
7 |
8 | *.js
9 | !jest.config.js
10 | *.d.ts
11 | node_modules
12 |
13 | # CDK asset staging directory
14 | .cdk.staging
15 | cdk.out
16 |
--------------------------------------------------------------------------------
/apps/lambda-examples/.npmignore:
--------------------------------------------------------------------------------
1 | *.ts
2 | !*.d.ts
3 |
4 | # CDK asset staging directory
5 | .cdk.staging
6 | cdk.out
7 |
--------------------------------------------------------------------------------
/apps/lambda-examples/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
--------------------------------------------------------------------------------
/apps/lambda-examples/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .cache/
3 | .env
4 | dist/
5 | .parcel-cache/
6 | .DS_Store
7 | coverage/
8 | package-lock.json
--------------------------------------------------------------------------------
/apps/lambda-examples/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "useTabs": false,
4 | "printWidth": 120,
5 | "bracketSameLine": true
6 | }
--------------------------------------------------------------------------------
/apps/lambda-examples/README.md:
--------------------------------------------------------------------------------
1 | # 🖼 LiveViewJS for AWS Lambda (NodeJS)
2 |
3 | The is a proof-of-concept that shows how you can host a "serverless" LiveViewJS application on AWS Lambda and API Gateway. The project loads the examples from the [LiveViewJS](https://liveviewjs.com) but you can adapt this to host your own LiveViewJS application.
4 |
5 | ## Status
6 | This is a proof-of-concept and is NOT production ready for large volumes. In particular, the following issues need to be addressed:
7 | - API Gateway Websocket requests may not be handled in order that they were received (thus race conditions can occur)
8 | - LiveViewJS currently keeps LiveView state in memory which may break in the
9 | case multiple lambda functions attempt to handle requests from the same LiveView
10 |
11 | We can address these issue by storing LiveView state in a different data store (e.g. DynamoDB) and using a queue to ensure that requests are handled in order.
12 |
13 | ## Summary AWS Architecture
14 | The set of AWS resources that are created are pretty simple:
15 | - API Gateway Websocket API passing requests to a Single Lambda function
16 | - API Gateway HTTP API passing requests to a Single Lambda function
17 |
18 | ## Pre-requisites
19 | You should have an AWS account and have the AWS CLI installed and configured with your credentials.
20 |
21 | Run `npm install` to install dependencies.
22 |
23 | ## Deploy
24 | This project uses AWS CDK to setup the infrastructure and deploy the code.
25 |
26 | Deploy to AWS Lambda using `cdk deploy [--profile YOUR_AWS_PROFILE]`.
27 |
28 | When the
29 |
30 | ## Teardown
31 | After you are done with the project you can remove the stack from your AWS account by running:
32 |
33 | `cdk destroy [--profile YOUR_AWS_PROFILE]`
34 |
--------------------------------------------------------------------------------
/apps/lambda-examples/bin/liveviewjs-lambda.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import * as cdk from "aws-cdk-lib";
3 | import "source-map-support/register";
4 | import { LiveViewJSLambdaStack } from "../lib/liveviewjs-lambda-stack";
5 |
6 | const app = new cdk.App();
7 | new LiveViewJSLambdaStack(app, "LiveViewJSLambdaStack", {
8 | /* If you don't specify 'env', this stack will be environment-agnostic.
9 | * Account/Region-dependent features and context lookups will not work,
10 | * but a single synthesized template can be deployed anywhere. */
11 | /* Uncomment the next line to specialize this stack for the AWS Account
12 | * and Region that are implied by the current CLI configuration. */
13 | // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
14 | /* Uncomment the next line if you know exactly what Account and Region you
15 | * want to deploy the stack to. */
16 | // env: { account: '123456789012', region: 'us-east-1' },
17 | /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
18 | });
19 |
--------------------------------------------------------------------------------
/apps/lambda-examples/cdk.json:
--------------------------------------------------------------------------------
1 | {
2 | "app": "npx ts-node --prefer-ts-exts bin/liveviewjs-lambda.ts",
3 | "watch": {
4 | "include": [
5 | "**"
6 | ],
7 | "exclude": [
8 | "README.md",
9 | "cdk*.json",
10 | "**/*.d.ts",
11 | "**/*.js",
12 | "tsconfig.json",
13 | "package*.json",
14 | "yarn.lock",
15 | "node_modules",
16 | "test"
17 | ]
18 | },
19 | "context": {
20 | "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
21 | "@aws-cdk/core:stackRelativeExports": true,
22 | "@aws-cdk/aws-rds:lowercaseDbIdentifier": true,
23 | "@aws-cdk/aws-lambda:recognizeVersionProps": true,
24 | "@aws-cdk/aws-lambda:recognizeLayerVersion": true,
25 | "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true,
26 | "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
27 | "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
28 | "@aws-cdk/core:checkSecretUsage": true,
29 | "@aws-cdk/aws-iam:minimizePolicies": true,
30 | "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
31 | "@aws-cdk/core:validateSnapshotRemovalPolicy": true,
32 | "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
33 | "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
34 | "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
35 | "@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
36 | "@aws-cdk/core:enablePartitionLiterals": true,
37 | "@aws-cdk/core:target-partitions": [
38 | "aws",
39 | "aws-cn"
40 | ]
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/apps/lambda-examples/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/floodfx/liveviewjs/52633f3d03d0c23d8fff7fb290c54f28e7fc14da/apps/lambda-examples/public/favicon.ico
--------------------------------------------------------------------------------
/apps/lambda-examples/src/client/index.ts:
--------------------------------------------------------------------------------
1 | import NProgress from "nprogress";
2 | import { Socket } from "phoenix";
3 | import "phoenix_html";
4 | import { LiveSocket, ViewHook } from "phoenix_live_view";
5 |
6 | /**
7 | * Define custom LiveView Hooks that can tap into browser events.
8 | * See: https://hexdocs.pm/phoenix_live_view/js-interop.html#client-hooks-via-phx-hook
9 | */
10 | let Hooks = {
11 | /**
12 | * This hook can be used by an input element to prevent input other than numbers.
13 | * e.g.
14 | */
15 | NumberInput: {
16 | mounted() {
17 | this.el.addEventListener("input", () => {
18 | // replace all non-numeric characters with empty string
19 | this.el.value = this.el.value.replace(/\D/g, "");
20 | });
21 | },
22 | } as ViewHook,
23 | };
24 |
25 | // WS_APIG_ID in the URL below will be replaced with the API Gateway ID at runtime
26 | // See: src/lambdas/http.ts route handler for "/js/index.js"
27 | const url = "wss://WS_APIG_ID.execute-api.us-west-2.amazonaws.com";
28 | let csrfToken = document.querySelector("meta[name='csrf-token']")?.getAttribute("content");
29 | let liveSocket = new LiveSocket(url, Socket, { params: { _csrf_token: csrfToken }, hooks: Hooks });
30 |
31 | // Show progress bar on live navigation and form submits
32 | window.addEventListener("phx:page-loading-start", (info) => NProgress.start());
33 | window.addEventListener("phx:page-loading-stop", (info) => NProgress.done());
34 |
35 | // connect if there are any LiveViews on the page
36 | liveSocket.connect();
37 |
38 | // expose liveSocket on window for web console debug logs and latency simulation:
39 | // liveSocket.enableDebug();
40 | // liveSocket.enableLatencySim(1000)
41 | (window as any).liveSocket = liveSocket;
42 |
--------------------------------------------------------------------------------
/apps/lambda-examples/src/example/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | autocompleteLiveView,
3 | booksLiveView,
4 | counterLiveView,
5 | dashboardLiveView,
6 | decarbLiveView,
7 | helloToggleEmojiLiveView,
8 | jsCmdsLiveView,
9 | paginateLiveView,
10 | photosLiveView,
11 | printLiveView,
12 | rtCounterLiveView,
13 | searchLiveView,
14 | serversLiveView,
15 | sortLiveView,
16 | volumeLiveView,
17 | volunteerLiveView,
18 | xkcdLiveView,
19 | } from "@liveviewjs/examples";
20 | import { LiveViewRouter } from "liveviewjs";
21 | import { LambdaLiveViewServer } from "../lambda/server";
22 | import { htmlPageTemplate, wrapperTemplate } from "./liveTemplates";
23 |
24 | // LiveViewRouter that maps the path to the LiveView
25 | const router: LiveViewRouter = {
26 | "/autocomplete": autocompleteLiveView,
27 | "/decarbonize": decarbLiveView,
28 | "/prints": printLiveView,
29 | "/volume": volumeLiveView,
30 | "/paginate": paginateLiveView,
31 | "/dashboard": dashboardLiveView,
32 | "/search": searchLiveView,
33 | "/servers": serversLiveView,
34 | "/sort": sortLiveView,
35 | "/volunteers": volunteerLiveView,
36 | "/counter": counterLiveView,
37 | "/jscmds": jsCmdsLiveView,
38 | "/photos": photosLiveView,
39 | "/xkcd": xkcdLiveView,
40 | "/rtcounter": rtCounterLiveView,
41 | "/books": booksLiveView,
42 | "/helloToggle": helloToggleEmojiLiveView,
43 | };
44 |
45 | // Configure the LambdaLiveViewServer which generates handlers for HTTP
46 | // and WebSocket requests from API Gateway and AWS Lambda
47 | export const liveView = new LambdaLiveViewServer(
48 | router,
49 | htmlPageTemplate,
50 | { title: "Lambda Demo", suffix: " · LiveViewJS" },
51 | {
52 | serDeSigningSecret: "signingSecret",
53 | wrapperTemplate,
54 | }
55 | );
56 |
--------------------------------------------------------------------------------
/apps/lambda-examples/src/lambdas/websocket.ts:
--------------------------------------------------------------------------------
1 | import { liveView } from "src/example";
2 |
3 | /**
4 | * Use the liveView middleware to handle Websocket requests
5 | */
6 | export const handler = liveView.wsMiddleware();
7 |
--------------------------------------------------------------------------------
/apps/lambda-examples/tsconfig-client.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "noEmitOnError": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "experimentalDecorators": true,
8 | "emitDecoratorMetadata": true,
9 | "strictPropertyInitialization": false,
10 | "declaration": true,
11 | "resolveJsonModule": true,
12 | "strict": true,
13 | "skipLibCheck": true,
14 | "target": "ES2020",
15 | "moduleResolution": "node",
16 | "lib": ["DOM"],
17 | "types": ["node"],
18 | "outDir": "./build",
19 | "baseUrl": "."
20 | },
21 | "include": ["./src/client/*"],
22 | "exclude": ["build", "node_modules", "./**/*.test.ts", "cdk.out", "./src/**/*"]
23 | }
24 |
--------------------------------------------------------------------------------
/apps/lambda-examples/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "noEmitOnError": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "experimentalDecorators": true,
8 | "emitDecoratorMetadata": true,
9 | "strictPropertyInitialization": false,
10 | "declaration": true,
11 | "resolveJsonModule": true,
12 | "strict": true,
13 | "skipLibCheck": true,
14 | "target": "es2019",
15 | "moduleResolution": "node",
16 | "lib": ["es2019", "esnext.asynciterable"],
17 | "types": ["node"],
18 | "outDir": "./build",
19 | "baseUrl": "."
20 | },
21 | "include": ["./src/**/*", "lib/**/*"],
22 | "exclude": ["build", "node_modules", "./**/*.test.ts", "./src/client/**/*", "cdk.out"]
23 | }
24 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "useTabs": false,
4 | "printWidth": 120,
5 | "bracketSameLine": true,
6 | "proseWrap": "always"
7 | }
8 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
4 |
5 | ## Installation
6 |
7 | ```
8 | $ npm install
9 | ```
10 |
11 | ### Local Development
12 |
13 | ```
14 | $ npm run start
15 | ```
16 |
17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without
18 | having to restart the server.
19 |
20 | ### Build
21 |
22 | ```
23 | $ npm run build
24 | ```
25 |
26 | This command generates static content into the `docs` directory and can be served using any static contents hosting
27 | service.
28 |
29 | ### Deployment
30 |
31 | Using SSH:
32 |
33 | ```
34 | $ USE_SSH=true npm run deploy
35 | ```
36 |
37 | Not using SSH:
38 |
39 | ```
40 | $ GIT_USER= npm run deploy
41 | ```
42 |
43 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the
44 | `gh-pages` branch.
45 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve("@docusaurus/core/lib/babel/preset")],
3 | };
4 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/blog/2019-05-28-first-blog-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: first-blog-post
3 | title: First Blog Post
4 | authors: [floodfx]
5 | tags: [hola, docusaurus]
6 | ---
7 |
8 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum
9 | tempor eros aliquam consequat. Lorem ipsum dolor sit amet
10 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/blog/2021-08-01-mdx-blog-post.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | slug: mdx-blog-post
3 | title: MDX Blog Post
4 | authors: [floodfx]
5 | tags: [docusaurus]
6 | ---
7 |
8 | Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
9 |
10 | :::tip
11 |
12 | Use the power of React to create interactive blog posts.
13 |
14 | ```js
15 |
16 | ```
17 |
18 |
19 |
20 | :::
21 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/floodfx/liveviewjs/52633f3d03d0c23d8fff7fb290c54f28e7fc14da/apps/liveviewjs.com/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg
--------------------------------------------------------------------------------
/apps/liveviewjs.com/blog/2021-08-26-welcome/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | slug: welcome
3 | title: Welcome
4 | authors: [floodfx]
5 | tags: [facebook, hello, docusaurus]
6 | ---
7 |
8 | [Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the
9 | [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
10 |
11 | Simply add Markdown files (or folders) to the `blog` directory.
12 |
13 | Regular blog authors can be added to `authors.yml`.
14 |
15 | The blog post date can be extracted from filenames, such as:
16 |
17 | - `2019-05-30-welcome.md`
18 | - `2019-05-30-welcome/index.md`
19 |
20 | A blog post folder can be convenient to co-locate blog post images:
21 |
22 | 
23 |
24 | The blog supports tags as well!
25 |
26 | **And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
27 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/blog/authors.yml:
--------------------------------------------------------------------------------
1 | floodfx:
2 | name: Donnie Flood
3 | title: LiveViewJS Author
4 | url: https://github.com/floodfx
5 | image_url: https://github.com/floodfx.png
6 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/01-overview/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Overview",
3 | "position": 1,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "LiveViewJS is an open-source framework for \"LiveView\"-based, full-stack applications in NodeJS and Deno."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/01-overview/feedback.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 |
5 | # Getting Involved
6 |
7 | ## Feedback is a 🎁
8 |
9 | Like all software, this is a work in progress. If you have any feedback, please let us know by opening an issue on the
10 | [GitHub repository](https://github.com/floodfx/liveviewjs/issues).
11 |
12 | ## Contributing is ❤️
13 |
14 | We welcome questions, comments, documentation, and code contributions. If you'd like to contribute, please feel free to
15 | open an issue or a pull request. We'll do our best to respond quickly and get it merged!
16 |
17 | ## Sponsorship is ⛽️
18 |
19 | If you'd like to support the project, please consider sponsoring us on [GitHub](https://github.com/sponsors/floodfx).
20 | We'll use the funds to pay for coffee, hosting, domain names, therapy, and other expenses related to the project.
21 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/01-overview/gratitude.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | ---
4 |
5 | # Gratitude
6 |
7 | 🙌 Thanks to the Phoenix LiveView team for the genius conceptualization and implementation of LiveViews and all the code
8 | we can reuse on the client side.
9 |
10 | 🙌 Thanks to [@ogrodnek](https://github.com/ogrodnek) for the early support, feedback, and the idea to reuse the Phoenix
11 | client code instead of reinventing!
12 |
13 | 🙌 Thanks to [@blimmer](https://github.com/blimmer/) for the awesome feedback, documentation suggestions, and support!
14 |
15 | Thanks to you for checking out **LiveViewJS**! We hope you enjoy it as much as we do!
16 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/02-quick-starts/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Quick Starts",
3 | "position": 2,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Run the examples and build your first LiveView"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/02-quick-starts/deno-run-examples.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 |
5 | # Deno - Run the Examples
6 |
7 | **LiveViewJS** ships with over a dozen example LiveViews that show everything from simple button-based events to
8 | real-time, multi-player views. It takes approximately 1 minute to get these examples up and running and is a good way to
9 | get a feel for the user experience of a LiveView. Let's get started!
10 |
11 | ## Prerequisite
12 |
13 | [Deno](https://deno.land/) version 1.24.x or above. (Older versions may work but haven't been tested.)
14 |
15 | If you haven't already, [download the **LiveViewJS** repo](get-liveviewjs-repo).
16 |
17 | ## Run the Examples
18 |
19 | Navigate to the `packages/deno` directory:
20 |
21 | ```bash
22 | # cd to the deno directory
23 | cd packages/deno
24 | ```
25 |
26 | Install dependencies:
27 |
28 | ```bash
29 | npm install
30 | ```
31 |
32 | Then, start the Deno server with the examples:
33 |
34 | ```bash
35 | deno run --allow-run --allow-read --allow-write --allow-net --allow-env src/example/autorun.ts
36 | ```
37 |
38 | Point your browser to [http://localhost:9001](http://localhost:9001)
39 |
40 | ## Explore the Examples
41 |
42 | You should see something like the screenshot below including a list of examples with a brief description, a link to the
43 | running LiveView, and a link to the source code for each example.
44 |
45 | 
46 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/02-quick-starts/nodejs-run-examples.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # NodeJS - Run the Examples
6 |
7 | **LiveViewJS** ships with over a dozen example LiveViews that show everything from simple button-based events to
8 | real-time, multi-player views. It takes approximately ⏱ 1 minute to get these examples up and running and is a good way
9 | to get a feel for the user experience of a LiveView. Let's get started!
10 |
11 | ## Prerequisite
12 |
13 | [Node.js](https://nodejs.org/en/download/) version 18.x or above.
14 |
15 | :::note
16 |
17 | We rely on the NodeJS Fetch API, which is only available in 18+.
18 |
19 | :::
20 |
21 | If you haven't already, [download the **LiveViewJS** repo](get-liveviewjs-repo).
22 |
23 | ## Run the Examples
24 |
25 | First, load the NPM dependencies:
26 |
27 | ```bash
28 | # install the NPM dependencies
29 | npm install
30 | ```
31 |
32 | Then, start the express server with the examples:
33 |
34 | ```bash
35 | # run the examples
36 | npm run start -w packages/express
37 | ```
38 |
39 | Point your browser to [http://localhost:4001](http://localhost:4001)
40 |
41 | ## Explore the Examples
42 |
43 | You should see something like the screenshot below including a list of examples with a brief description, a link to the
44 | running LiveView, and a link to the source code for each example.
45 |
46 | 
47 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/03-anatomy-of-a-liveview/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Anatomy of a LiveView",
3 | "position": 3,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Deep dive into the LiveView API and lifecycle functions"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/03-anatomy-of-a-liveview/handle-info.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 6
3 | ---
4 |
5 | # LiveView API - `handleInfo`
6 |
7 | `handleInfo` is how server-side events (a.k.a `Info`) are handled. These server-side events are initiated by processes
8 | that are happening on the server for example: database updates, background jobs, pub/sub messages, or some other
9 | asynchronous process. Just like `handleEvent` and `handleParams`, `handleInfo` is automatically passed the `info` event
10 | (i.e., server event) along with the `socket` and can use it to manipulate the `context` of the LiveView or otherwise
11 | respond to the `info` messages it receives.
12 |
13 | ## `handleInfo` Signature
14 |
15 | ```ts
16 | handleInfo(info: TInfos, socket: LiveViewSocket): void | Promise;
17 | ```
18 |
19 | ## `handleInfo` Use Cases
20 |
21 | There are three main use cases for `handleInfo`:
22 |
23 | - Handling an asynchronous process initiated from a user event without blocking the UI
24 | - Handling an asynchronous process initiated from a background process
25 | - Handling a pub/sub message
26 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/04-liveview-socket/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "LiveViewSocket",
3 | "position": 4,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "The swiss army knife of LiveViewJS that connects the dots across a LiveView lifecycle."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/05-lifecycle-of-a-liveview/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Lifecycle of a LiveView",
3 | "position": 5,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "More details on the LiveView lifecycle including diagrams 📐"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/06-user-events-slash-bindings/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "User Events",
3 | "position": 6,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "How LiveViews listen for user events and the HTML attributes that trigger them "
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/06-user-events-slash-bindings/additional-bindings.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Additional Bindings
6 |
7 | There are additional bindings outside of the four main bindings for User Events that you will find extremely useful and
8 | that you will use often.
9 |
10 | ## Value Bindings
11 |
12 | When you need to send along additional data with an event binding you can use a "value binding" which looks something
13 | like `phx-value-[NAME]` where `[NAME]` is replaced by the key of the value you want to pass. This binding can be used in
14 | conjunction with other click, key, and focus bindings.
15 |
16 | ### Value Binding Example
17 |
18 | For example let's say you want to send the `mark_complete` event to the server along with and `id` value
19 | (e.g., `{id: "myId"}`) when the user clicks on the "Complete" button. To do this you do the following:
20 |
21 | ```html
22 |
23 | ```
24 |
25 | Note the `[NAME]` part of `phx-value-[NAME]` is `id` used as the object key while the attribute value (i.e., `"myId"`) is
26 | used as the object value.
27 |
28 | This example would send the following event to the server:
29 |
30 | ```ts
31 | {
32 | type: "mark_complete",
33 | id: "myId"
34 | }
35 | ```
36 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/07-forms-and-changesets/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Forms & Changesets",
3 | "position": 7,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "How LiveViewJS makes form validation and submission easy with Changesets"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/07-forms-and-changesets/overview.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | ---
4 |
5 | # Overview
6 |
7 | Forms are obviously extremely important for any web application that needs user input. Building, validating, and
8 | handling form submission is built into **LiveViewJS** forms .
9 |
10 | ## Form Bindigs
11 |
12 | We've already reviewed the form event bindings that are available in LiveViewJS. Here is a quick summary:
13 |
14 | - `phx-change` - This event is sent to the server along with all the form values when any form input is changed.
15 | - `phx-submit` - This event is sent to the server when the form is submitted alog with all the form values.
16 |
17 | Feel free to review form events in more detail in the
18 | [User Events and Bindings](/docs/user-events-slash-bindings/overview) section.
19 |
20 | ## Changesets
21 |
22 | We have not yet discussed the concept of a "changeset" in LiveViewJS. At a high level a changeset is a way to parse and
23 | validate that incoming JSON data maps to the expected constraints. You will see it is a very powerful concept that
24 | allows you to build and validate complex forms with ease.
25 |
26 | :::note
27 |
28 | Changesets are a concept that is taken from an Elixir library called
29 | [Ecto](https://hexdocs.pm/ecto/Ecto.Changeset.html). Ecto changesets are used to validate and persist data to a
30 | database. While **LiveViewJS** changeset are not ORM or DB releated, we've taken the concept of a changeset and adapted
31 | it to the Typescript world for parsing and validation.
32 |
33 | :::
34 |
35 | We will take a deep dive into Changesets in a more detail in the next section.
36 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/08-file-upload/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Uploading Files",
3 | "position": 8,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Magically powerful file uploads with previews, progress, drag & drop, and more ✨"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/08-file-upload/drag-and-drop.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | ---
4 |
5 | # Built-in Drag and Drop
6 |
7 | LiveViewJS ships with built-in support for drag and drop file uploads. It is incredibly easy to use. All you need to do
8 | is add a `` that has the `phx-drop-target` attribute set to the upload config ref you want to target. For
9 | example, if you want to allow users to drag and drop files into a `photos` upload config, you would do the following:
10 |
11 | ```ts
12 | ...
13 | render: (context, meta) => {
14 | ...
15 |
16 | Drop files here
17 |
18 | ...
19 | }
20 | ```
21 |
22 | That's it! **LiveViewJS** will automatically handle the rest. The user will be able to drag and drop files into the div
23 | and they will be added to the entries of that upload config. 🤯
24 |
25 | ## Credit where credit is due
26 |
27 | Thanks to the Phoenix LiveView folks that built this! 🙌 This is a great example of why we built on top of the existing
28 | LiveView client-side JS.
29 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/08-file-upload/image-preview.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | ---
4 |
5 | # Built-in Image Preview
6 |
7 | LiveViewJS ships with build-in support for image previews when uploading files.
8 |
9 | ## Getting Entries from `meta.uploads`
10 |
11 | The list of `UploadEntry` objects for a given upload config can be found in the `meta.uploads` object based on the name
12 | you provided when configuring it using the `allowUpload` method. For example, if you configured an upload config named
13 | `photos`, you can access the list of `UploadEntry` objects using `meta.uploads.photos`. Here is an example of accessing
14 | the list of `UploadEntry` objects for a given upload config:
15 |
16 | ```ts
17 | ...
18 | render: (context, meta) => {
19 | ...
20 |
27 | ...
28 | }
29 | ```
30 |
31 | ## `live_img_preview` Tag
32 |
33 | In order to use the built-in image preview, you must use the `live_img_preview` tag. This tag takes a `UploadEntry` and
34 | renders an image preview of it.
35 |
36 | ```ts
37 | ...
38 | render: (context, meta) => {
39 | ...
40 |
58 | ...
59 | }
60 | ```
61 |
62 | That's it! 🤯
63 |
64 | ## Credit where credit is due
65 |
66 | Thanks to the Phoenix LiveView folks that built this! 🙌 This is a great example of why we built on top of the existing
67 | LiveView client-side JS.
68 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/08-file-upload/upload-config-options.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 |
5 | # Upload Config Options
6 |
7 | These are the options you can pass into the `allowUpload` method to configure the upload.
8 |
9 | - `accept`: an array of strings that represent the file extensions and/or mime types that are allowed to be uploaded.
10 | For example, `[".png", ".jpg", ".jpeg", ".gif"]` will only allow images to be uploaded. See
11 | [unique file type specifiers](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers)
12 | for more information. Defaults to `[]` (no restrictions)
13 | - `maxEntries`: the maximum number of files that can be uploaded. If the user tries to upload more than this number of
14 | files, an error will be present in the upload config. Defaults to `1`.
15 | - `maxFileSize`: the maximum file size (in bytes) that can be uploaded. If the user tries to upload a file that is
16 | larger than this number, an error will be present in the upload config. Defaults to `10 * 1024 * 1024` (10MB).
17 | - `autoUpload`: if `true`, the file will be uploaded as soon as it is selected by the user. If `false`, the file will
18 | not be uploaded until the user initiates the form's save event. The default is `false`.
19 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/09-real-time-multi-player-pub-sub/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Real-time / Multi-player",
3 | "position": 9,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Easy real-time, multi-player support with LiveViewJS Pub/Sub"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/10-client-javascript/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Client-side Javascript",
3 | "position": 10,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "How LiveView client-side Javascript works and how to use it"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/10-client-javascript/example-hook.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | ---
4 |
5 | # Example Hook
6 |
7 | Let's create a hook that will format a text input into a phone number as a user types.
8 |
9 | ## Hook Definition
10 |
11 | ```ts
12 | // Define the hook
13 | const PhoneNumber: ViewHook = {
14 | mounted() {
15 | this.el.addEventListener("input", (e) => {
16 | let match = this.el.value.replace(/\D/g, "").match(/^(\d{3})(\d{3})(\d{4})$/);
17 | if (match) {
18 | this.el.value = `${match[1]}-${match[2]}-${match[3]}`;
19 | }
20 | });
21 | },
22 | };
23 | // Add the hook to the LiveSocket
24 | let liveSocket = new LiveSocket("/live", Socket, {
25 | hooks: { PhoneNumber },
26 | });
27 | ```
28 |
29 | ## Hook Usage
30 |
31 | ```html
32 |
33 | ```
34 |
35 | ## Credit 🙌
36 |
37 | Credit for this example goes to the
38 | [Phoenix LiveView docs](https://hexdocs.pm/phoenix_live_view/js-interop.html#client-hooks-via-phx-hook). I didn't want
39 | to reinvent the wheel, so I just copied the example from the Phoenix LiveView docs, added some types, and simplified it
40 | a bit.
41 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/11-js-commands/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "JS Commands",
3 | "position": 11,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Additional utilities for more dynamic, client-side experiences"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/11-js-commands/dispatch-cmd.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | ---
4 |
5 | # Dispatch Command
6 |
7 | The `dispatch` command dispatches a DOM event from the target element
8 |
9 | ```typescript
10 | new JS().dispatch(event: string, options?: DispatchOptions)
11 | ```
12 |
13 | - `event` - The name of the event to dispatch
14 | - `options` - Options for the command (optional)
15 | - `to` - An optional css selector to identify the element from which to dispatch. Defaults to the element that the JS
16 | Command is attached to.
17 | - `detail` - A optional map of key/value pairs to include in the event's `detail` property
18 | - `bubbles` - A optional boolean indicating whether the event should bubble up the DOM. Defaults to `true`
19 |
20 | **Note**: All events dispatched are of a type CustomEvent, with the exception of "click". For a "click", a MouseEvent is
21 | dispatched to properly simulate a UI click.
22 |
23 | For emitted CustomEvent's, the event detail will contain a dispatcher, which references the DOM node that dispatched the
24 | JS event to the target element.
25 |
26 | Examples
27 |
28 | ```html
29 | //... in your render function of a LiveView
30 |
31 | // dispatch a click
32 |
33 |
34 | // dispatch a custom event
35 |
38 |
Dispatch Target
39 | ```
40 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/11-js-commands/push-cmd.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 7
3 | ---
4 |
5 | # Push Command
6 |
7 | The `push` command sends an event to the server
8 |
9 | ```typescript
10 | new JS().push(event: string, options?: PushOptions)
11 | ```
12 |
13 | - `event` - The name of the event to send to the server
14 | - `options` - Options for the command (optional)
15 | - `target` - An optional selector or component ID to push to
16 | - `loading` - An optional selector to apply the phx loading classes to
17 | - `page_loading` - An optional boolean indicating whether to trigger the "phx:page-loading-start" and
18 | "phx:page-loading-stop" events. Defaults to `false`
19 | - `value` An optional map of key/value pairs to include in the event's `value` property
20 |
21 | Examples
22 |
23 | ```html
24 | //... in your render function of a LiveView
25 |
26 | // push increment event to server
27 |
28 |
29 | // push decrement event to server
30 |
31 |
32 | // push increment event to server with a payload then hide the button
33 |
36 |
37 | // hide the button then push increment event
38 |
39 |
40 | // push incremenet and show page loading indicator
41 |
44 | ```
45 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/11-js-commands/transition-cmd.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 6
3 | ---
4 |
5 | # Transition Command
6 |
7 | The `transition` command dispatches a DOM event from the target element
8 |
9 | ```typescript
10 | new JS().transition(transition: Transition, options?: TransitionOptions)
11 | ```
12 |
13 | - `transition` - The string of classes to apply to the element, or a 3-tuple containing the transition class, the class
14 | to apply to start the transition, and the class to apply to end the transition. e.g., ["ease-out duration-300",
15 | "opacity-100", "opacity-0"]
16 | - `options` - Options for the command (optional)
17 | - `to` - An optional css selector to identify the element from which to transition. Defaults to the element that the
18 | JS Command is attached to.
19 | - `time` - The time (in milliseconds) over which to apply the transition options. Defaults to 200
20 |
21 | Examples
22 |
23 | ```html
24 | //... in your render function of a LiveView
25 |
26 | // transition the target element
27 |
35 |
43 |
Transition Target
44 |
45 | // transition button with a shake
46 |
47 | ```
48 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/12-webserver-integration/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Webserver Integrations",
3 | "position": 12,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "How LiveViewJS integrates with webservers and how to add support for other webservers"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/12-webserver-integration/support-webserver-x.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | ---
4 |
5 | # Support Webserver "X"
6 |
7 | If you want to use LiveViewJS with a webserver that is not supported out of the box, you can implement the
8 | `LiveViewServerAdaptor` interface and plug it into your webserver.
9 |
10 | Essentially, you'll need to be able to intercept HTTP and websocket requests and pass them to the LiveViewJS library.
11 | The LiveViewJS library will then handle the requests and return the appropriate responses.
12 |
13 | ## Look at the existing integrations
14 |
15 | Checkout the LiveViewJS source code and look at the
16 | [`NodeExpressLiveViewServer`](https://github.com/floodfx/liveviewjs/blob/main/packages/express/src/node/server.ts) and
17 | [`DenoOakLiveViewServer`](https://github.com/floodfx/liveviewjs/blob/main/packages/deno/src/deno/server.ts) classes.
18 | These are the two webserver integrations that are supported out of the box.
19 |
20 | ## Open an issue
21 |
22 | We are happy to help you get LiveViewJS working with your webserver. If you
23 | [open an issue](https://github.com/floodfx/liveviewjs/issues) on the LiveViewJS GitHub repo, we'll be happy to support
24 | you.
25 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/13-misc/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Miscellaneous",
3 | "position": 13,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "A potpourri of topics that don't fit elsewhere or are not large enough to warrant their own category"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/13-misc/debugging-wire.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 4
3 | ---
4 |
5 | # Debugging LiveViews
6 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/13-misc/flash.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 6
3 | ---
4 |
5 | # Flash Messages
6 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/docs/13-misc/root-and-page-renderers.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 5
3 | ---
4 |
5 | # Root and Page Renderers
6 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "liveviewjs-com",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "docusaurus": "docusaurus",
7 | "start": "docusaurus start",
8 | "build": "docusaurus build",
9 | "swizzle": "docusaurus swizzle",
10 | "deploy": "docusaurus deploy",
11 | "clear": "docusaurus clear",
12 | "serve": "docusaurus serve",
13 | "write-translations": "docusaurus write-translations",
14 | "write-heading-ids": "docusaurus write-heading-ids",
15 | "typecheck": "tsc",
16 | "format": "prettier --write '**/*.{ts,js,json,html,css,md}'"
17 | },
18 | "dependencies": {
19 | "@docusaurus/core": "2.0.1",
20 | "@docusaurus/plugin-google-gtag": "^2.1.0",
21 | "@docusaurus/preset-classic": "2.0.1",
22 | "@mdx-js/react": "^1.6.22",
23 | "clsx": "^1.2.1",
24 | "prism-react-renderer": "^1.3.5",
25 | "react": "^17.0.2",
26 | "react-dom": "^17.0.2"
27 | },
28 | "devDependencies": {
29 | "@docusaurus/module-type-aliases": "2.0.1",
30 | "@tsconfig/docusaurus": "^1.0.5",
31 | "autoprefixer": "^10.4.8",
32 | "postcss": "^8.4.16",
33 | "prettier": "^2.5.1",
34 | "tailwindcss": "^3.1.8",
35 | "typescript": "^4.7.4"
36 | },
37 | "browserslist": {
38 | "production": [
39 | ">0.5%",
40 | "not dead",
41 | "not op_mini all"
42 | ],
43 | "development": [
44 | "last 1 chrome version",
45 | "last 1 firefox version",
46 | "last 1 safari version"
47 | ]
48 | },
49 | "engines": {
50 | "node": ">=16.14"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/sidebars.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Creating a sidebar enables you to:
3 | - create an ordered group of docs
4 | - render a sidebar for each doc of that group
5 | - provide next/previous navigation
6 |
7 | The sidebars can be generated from the filesystem, or explicitly defined here.
8 |
9 | Create as many sidebars as you want.
10 | */
11 |
12 | // @ts-check
13 |
14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
15 | const sidebars = {
16 | // By default, Docusaurus generates a sidebar from the docs folder structure
17 | tutorialSidebar: [{ type: "autogenerated", dirName: "." }],
18 |
19 | // But you can create a sidebar manually
20 | /*
21 | tutorialSidebar: [
22 | {
23 | type: 'category',
24 | label: 'Tutorial',
25 | items: ['hello'],
26 | },
27 | ],
28 | */
29 | };
30 |
31 | module.exports = sidebars;
32 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/src/components/HomepageFeatures/styles.module.css:
--------------------------------------------------------------------------------
1 | .features {
2 | display: flex;
3 | align-items: center;
4 | padding: 2rem 0;
5 | width: 100%;
6 | }
7 |
8 | .featureSvg {
9 | height: 200px;
10 | width: 200px;
11 | }
12 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/src/pages/index.module.css:
--------------------------------------------------------------------------------
1 | /**
2 | * CSS files with the .module.css suffix will be treated as CSS modules
3 | * and scoped locally.
4 | */
5 |
6 | .heroBanner {
7 | padding: 4rem 0;
8 | text-align: center;
9 | position: relative;
10 | overflow: hidden;
11 | }
12 |
13 | @media screen and (max-width: 996px) {
14 | .heroBanner {
15 | padding: 2rem;
16 | }
17 | }
18 |
19 | .buttons {
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | }
24 |
--------------------------------------------------------------------------------
/apps/liveviewjs.com/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import clsx from 'clsx';
3 | import Link from '@docusaurus/Link';
4 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
5 | import Layout from '@theme/Layout';
6 | import HomepageFeatures from '@site/src/components/HomepageFeatures';
7 |
8 | import styles from './index.module.css';
9 |
10 | function HomepageHeader() {
11 | const {siteConfig} = useDocusaurusContext();
12 | return (
13 |
14 |