diff --git a/AI/fasthtml.md b/AI/fasthtml.md
new file mode 100644
index 0000000..cfedeac
--- /dev/null
+++ b/AI/fasthtml.md
@@ -0,0 +1,2619 @@
+
+Things to remember when writing FastHTML apps:
+
+- Although parts of its API are inspired by FastAPI, it is *not* compatible with FastAPI syntax and is not targeted at creating API services
+- FastHTML includes support for Pico CSS and the fastlite sqlite library, although using both are optional; sqlalchemy can be used directly or via the fastsql library, and any CSS framework can be used. Support for the Surreal and css-scope-inline libraries are also included, but both are optional
+- FastHTML is compatible with JS-native web components and any vanilla JS library, but not with React, Vue, or Svelte
+- Use `serve()` for running uvicorn (`if __name__ == "__main__"` is not needed since it's automatic)
+- When a title is needed with a response, use `Titled`; note that that already wraps children in `Container`, and already includes both the meta title as well as the H1 element.
+
+ # Web Devs Quickstart
+
+
+## Installation
+
+``` bash
+pip install python-fasthtml
+```
+
+## A Minimal Application
+
+A minimal FastHTML application looks something like this:
+
+
+
+Line 1
+We import what we need for rapid development! A carefully-curated set of
+FastHTML functions and other Python objects is brought into our global
+namespace for convenience.
+
+Line 3
+We instantiate a FastHTML app with the `fast_app()` utility function.
+This provides a number of really useful defaults that we’ll take
+advantage of later in the tutorial.
+
+Line 5
+We use the `rt()` decorator to tell FastHTML what to return when a user
+visits `/` in their browser.
+
+Line 6
+We connect this route to HTTP GET requests by defining a view function
+called `get()`.
+
+Line 7
+A tree of Python function calls that return all the HTML required to
+write a properly formed web page. You’ll soon see the power of this
+approach.
+
+Line 9
+The `serve()` utility configures and runs FastHTML using a library
+called `uvicorn`.
+
+Run the code:
+
+``` bash
+python main.py
+```
+
+The terminal will look like this:
+
+``` bash
+INFO: Uvicorn running on http://0.0.0.0:5001 (Press CTRL+C to quit)
+INFO: Started reloader process [58058] using WatchFiles
+INFO: Started server process [58060]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+Confirm FastHTML is running by opening your web browser to
+[127.0.0.1:5001](http://127.0.0.1:5001). You should see something like
+the image below:
+
+![](quickstart-web-dev/quickstart-fasthtml.png)
+
+
+
+> **Note**
+>
+> While some linters and developers will complain about the wildcard
+> import, it is by design here and perfectly safe. FastHTML is very
+> deliberate about the objects it exports in `fasthtml.common`. If it
+> bothers you, you can import the objects you need individually, though
+> it will make the code more verbose and less readable.
+>
+> If you want to learn more about how FastHTML handles imports, we cover
+> that [here](https://docs.fastht.ml/explains/faq.html#why-use-import).
+
+
+
+## A Minimal Charting Application
+
+The
+[`Script`](https://AnswerDotAI.github.io/fasthtml/api/xtend.html#script)
+function allows you to include JavaScript. You can use Python to
+generate parts of your JS or JSON like this:
+
+``` python
+import json
+from fasthtml.common import *
+
+app, rt = fast_app(hdrs=(Script(src="https://cdn.plot.ly/plotly-2.32.0.min.js"),))
+
+data = json.dumps({
+ "data": [{"x": [1, 2, 3, 4],"type": "scatter"},
+ {"x": [1, 2, 3, 4],"y": [16, 5, 11, 9],"type": "scatter"}],
+ "title": "Plotly chart in FastHTML ",
+ "description": "This is a demo dashboard",
+ "type": "scatter"
+})
+
+
+@rt("/")
+def get():
+ return Titled("Chart Demo", Div(id="myDiv"),
+ Script(f"var data = {data}; Plotly.newPlot('myDiv', data);"))
+
+serve()
+```
+
+## Debug Mode
+
+When we can’t figure out a bug in FastHTML, we can run it in `DEBUG`
+mode. When an error is thrown, the error screen is displayed in the
+browser. This error setting should never be used in a deployed app.
+
+``` python
+from fasthtml.common import *
+
+app, rt = fast_app(debug=True)
+
+@rt("/")
+def get():
+ 1/0
+ return Titled("FastHTML Error!", P("Let's error!"))
+
+serve()
+```
+
+Line 3
+`debug=True` sets debug mode on.
+
+Line 7
+Python throws an error when it tries to divide an integer by zero.
+
+## Routing
+
+FastHTML builds upon FastAPI’s friendly decorator pattern for specifying
+URLs, with extra features:
+
+
+
+Line 5
+The “/” URL on line 5 is the home of a project. This would be accessed
+at [127.0.0.1:5001](http://127.0.0.1:5001).
+
+Line 9
+“/hello” URL on line 9 will be found by the project if the user visits
+[127.0.0.1:5001/hello](http://127.0.0.1:5001/hello).
+
+
+
+> **Tip**
+>
+> It looks like `get()` is being defined twice, but that’s not the case.
+> Each function decorated with `rt` is totally separate, and is injected
+> into the router. We’re not calling them in the module’s namespace
+> (`locals()`). Rather, we’re loading them into the routing mechanism
+> using the `rt` decorator.
+
+
+
+You can do more! Read on to learn what we can do to make parts of the
+URL dynamic.
+
+## Variables in URLs
+
+You can add variable sections to a URL by marking them with
+`{variable_name}`. Your function then receives the `{variable_name}` as
+a keyword argument, but only if it is the correct type. Here’s an
+example:
+
+
+
+Line 5
+We specify two variable names, `name` and `age`.
+
+Line 6
+We define two function arguments named identically to the variables. You
+will note that we specify the Python types to be passed.
+
+Line 7
+We use these functions in our project.
+
+Try it out by going to this address:
+[127.0.0.1:5001/uma/5](http://127.0.0.1:5001/uma/5). You should get a
+page that says,
+
+> “Hello Uma, age 5”.
+
+### What happens if we enter incorrect data?
+
+The [127.0.0.1:5001/uma/5](http://127.0.0.1:5001/uma/5) URL works
+because `5` is an integer. If we enter something that is not, such as
+[127.0.0.1:5001/uma/five](http://127.0.0.1:5001/uma/five), then FastHTML
+will return an error instead of a web page.
+
+
+
+> **FastHTML URL routing supports more complex types**
+>
+> The two examples we provide here use Python’s built-in `str` and `int`
+> types, but you can use your own types, including more complex ones
+> such as those defined by libraries like
+> [attrs](https://pypi.org/project/attrs/),
+> [pydantic](https://pypi.org/project/pydantic/), and even
+> [sqlmodel](https://pypi.org/project/sqlmodel/).
+
+
+
+## HTTP Methods
+
+FastHTML matches function names to HTTP methods. So far the URL routes
+we’ve defined have been for HTTP GET methods, the most common method for
+web pages.
+
+Form submissions often are sent as HTTP POST. When dealing with more
+dynamic web page designs, also known as Single Page Apps (SPA for
+short), the need can arise for other methods such as HTTP PUT and HTTP
+DELETE. The way FastHTML handles this is by changing the function name.
+
+
+
+Line 6
+On line 6 because the `get()` function name is used, this will handle
+HTTP GETs going to the `/` URI.
+
+Line 10
+On line 10 because the `post()` function name is used, this will handle
+HTTP POSTs going to the `/` URI.
+
+## CSS Files and Inline Styles
+
+Here we modify default headers to demonstrate how to use the [Sakura CSS
+microframework](https://github.com/oxalorg/sakura) instead of FastHTML’s
+default of Pico CSS.
+
+
+
+Line 4
+By setting `pico` to `False`, FastHTML will not include `pico.min.css`.
+
+Line 7
+This will generate an HTML `` tag for sourcing the css for Sakura.
+
+Line 8
+If you want an inline styles, the `Style()` function will put the result
+into the HTML.
+
+## Other Static Media File Locations
+
+As you saw,
+[`Script`](https://AnswerDotAI.github.io/fasthtml/api/xtend.html#script)
+and `Link` are specific to the most common static media use cases in web
+apps: including JavaScript, CSS, and images. But it also works with
+videos and other static media files. The default behavior is to look for
+these files in the root directory - typically we don’t do anything
+special to include them. We can change the default directory that is
+looked in for files by adding the `static_path` parameter to the
+[`fast_app`](https://AnswerDotAI.github.io/fasthtml/api/fastapp.html#fast_app)
+function.
+
+``` python
+app, rt = fast_app(static_path='public')
+```
+
+FastHTML also allows us to define a route that uses `FileResponse` to
+serve the file at a specified path. This is useful for serving images,
+videos, and other media files from a different directory without having
+to change the paths of many files. So if we move the directory
+containing the media files, we only need to change the path in one
+place. In the example below, we call images from a directory called
+`public`.
+
+``` python
+@rt("/{fname:path}.{ext:static}")
+async def get(fname:str, ext:str):
+ return FileResponse(f'public/{fname}.{ext}')
+```
+
+## Rendering Markdown
+
+``` python
+from fasthtml.common import *
+
+hdrs = (MarkdownJS(), HighlightJS(langs=['python', 'javascript', 'html', 'css']), )
+
+app, rt = fast_app(hdrs=hdrs)
+
+content = """
+Here are some _markdown_ elements.
+
+- This is a list item
+- This is another list item
+- And this is a third list item
+
+**Fenced code blocks work here.**
+"""
+
+@rt('/')
+def get(req):
+ return Titled("Markdown rendering example", Div(content,cls="marked"))
+
+serve()
+```
+
+## Code highlighting
+
+Here’s how to highlight code without any markdown configuration.
+
+``` python
+from fasthtml.common import *
+
+# Add the HighlightJS built-in header
+hdrs = (HighlightJS(langs=['python', 'javascript', 'html', 'css']),)
+
+app, rt = fast_app(hdrs=hdrs)
+
+code_example = """
+import datetime
+import time
+
+for i in range(10):
+ print(f"{datetime.datetime.now()}")
+ time.sleep(1)
+"""
+
+@rt('/')
+def get(req):
+ return Titled("Markdown rendering example",
+ Div(
+ # The code example needs to be surrounded by
+ # Pre & Code elements
+ Pre(Code(code_example))
+ ))
+
+serve()
+```
+
+## Defining new `ft` components
+
+We can build our own `ft` components and combine them with other
+components. The simplest method is defining them as a function.
+
+``` python
+from fasthtml.common import *
+```
+
+``` python
+def hero(title, statement):
+ return Div(H1(title),P(statement), cls="hero")
+
+# usage example
+Main(
+ hero("Hello World", "This is a hero statement")
+)
+```
+
+``` html
+
+
+
Hello World
+
This is a hero statement
+
+
+```
+
+### Pass through components
+
+For when we need to define a new component that allows zero-to-many
+components to be nested within them, we lean on Python’s `*args` and
+`**kwargs` mechanism. Useful for creating page layout controls.
+
+``` python
+def layout(*args, **kwargs):
+ """Dashboard layout for all our dashboard views"""
+ return Main(
+ H1("Dashboard"),
+ Div(*args, **kwargs),
+ cls="dashboard",
+ )
+
+# usage example
+layout(
+ Ul(*[Li(o) for o in range(3)]),
+ P("Some content", cls="description"),
+)
+```
+
+``` html
+
+
Dashboard
+
+
+
0
+
1
+
2
+
+
Some content
+
+
+```
+
+### Dataclasses as ft components
+
+While functions are easy to read, for more complex components some might
+find it easier to use a dataclass.
+
+``` python
+from dataclasses import dataclass
+
+@dataclass
+class Hero:
+ title: str
+ statement: str
+
+ def __ft__(self):
+ """ The __ft__ method renders the dataclass at runtime."""
+ return Div(H1(self.title),P(self.statement), cls="hero")
+
+# usage example
+Main(
+ Hero("Hello World", "This is a hero statement")
+)
+```
+
+``` html
+
+
+
Hello World
+
This is a hero statement
+
+
+```
+
+## Testing views in notebooks
+
+Because of the ASGI event loop it is currently impossible to run
+FastHTML inside a notebook. However, we can still test the output of our
+views. To do this, we leverage Starlette, an ASGI toolkit that FastHTML
+uses.
+
+``` python
+# First we instantiate our app, in this case we remove the
+# default headers to reduce the size of the output.
+app, rt = fast_app(default_hdrs=False)
+
+# Setting up the Starlette test client
+from starlette.testclient import TestClient
+client = TestClient(app)
+
+# Usage example
+@rt("/")
+def get():
+ return Titled("FastHTML is awesome",
+ P("The fastest way to create web apps in Python"))
+
+print(client.get("/").text)
+```
+
+
+
+
+
+ FastHTML is awesome
+
+
+
+
FastHTML is awesome
+
The fastest way to create web apps in Python
+
+
+
+
+## Forms
+
+To validate data coming from users, first define a dataclass
+representing the data you want to check. Here’s an example representing
+a signup form.
+
+``` python
+from dataclasses import dataclass
+
+@dataclass
+class Profile: email:str; phone:str; age:int
+```
+
+Create an FT component representing an empty version of that form. Don’t
+pass in any value to fill the form, that gets handled later.
+
+``` python
+profile_form = Form(method="post", action="/profile")(
+ Fieldset(
+ Label('Email', Input(name="email")),
+ Label("Phone", Input(name="phone")),
+ Label("Age", Input(name="age")),
+ ),
+ Button("Save", type="submit"),
+ )
+profile_form
+```
+
+``` html
+
+```
+
+Once the dataclass and form function are completed, we can add data to
+the form. To do that, instantiate the profile dataclass:
+
+``` python
+profile = Profile(email='john@example.com', phone='123456789', age=5)
+profile
+```
+
+ Profile(email='john@example.com', phone='123456789', age=5)
+
+Then add that data to the `profile_form` using FastHTML’s
+[`fill_form`](https://AnswerDotAI.github.io/fasthtml/api/components.html#fill_form)
+class:
+
+``` python
+fill_form(profile_form, profile)
+```
+
+``` html
+
+```
+
+### Forms with views
+
+The usefulness of FastHTML forms becomes more apparent when they are
+combined with FastHTML views. We’ll show how this works by using the
+test client from above. First, let’s create a SQlite database:
+
+``` python
+db = Database("profiles.db")
+profiles = db.create(Profile, pk="email")
+```
+
+Now we insert a record into the database:
+
+``` python
+profiles.insert(profile)
+```
+
+ Profile(email='john@example.com', phone='123456789', age=5)
+
+And we can then demonstrate in the code that form is filled and
+displayed to the user.
+
+``` python
+@rt("/profile/{email}")
+def profile(email:str):
+ profile = profiles[email]
+ filled_profile_form = fill_form(profile_form, profile)
+ return Titled(f'Profile for {profile.email}', filled_profile_form)
+
+print(client.get(f"/profile/john@example.com").text)
+```
+
+Line 3
+Fetch the profile using the profile table’s `email` primary key
+
+Line 4
+Fill the form for display.
+
+
+
+
+
+
+ Profile for john@example.com
+
+
+
+
Profile for john@example.com
+
+
+
+
+
+And now let’s demonstrate making a change to the data.
+
+``` python
+@rt("/profile")
+def post(profile: Profile):
+ profiles.update(profile)
+ return RedirectResponse(url=f"/profile/{profile.email}")
+
+new_data = dict(email='john@example.com', phone='7654321', age=25)
+print(client.post("/profile", data=new_data).text)
+```
+
+Line 2
+We use the `Profile` dataclass definition to set the type for the
+incoming `profile` content. This validates the field types for the
+incoming data
+
+Line 3
+Taking our validated data, we updated the profiles table
+
+Line 4
+We redirect the user back to their profile view
+
+Line 7
+The display is of the profile form view showing the changes in data.
+
+
+
+
+
+
+ Profile for john@example.com
+
+
+
+
Profile for john@example.com
+
+
+
+
+
+## Strings and conversion order
+
+The general rules for rendering are: - `__ft__` method will be called
+(for default components like `P`, `H2`, etc. or if you define your own
+components) - If you pass a string, it will be escaped - On other python
+objects, `str()` will be called
+
+As a consequence, if you want to include plain HTML tags directly into
+e.g. a `Div()` they will get escaped by default (as a security measure
+to avoid code injections). This can be avoided by using `NotStr()`, a
+convenient way to reuse python code that returns already HTML. If you
+use pandas, you can use `pandas.DataFrame.to_html()` to get a nice
+table. To include the output a FastHTML, wrap it in `NotStr()`, like
+`Div(NotStr(df.to_html()))`.
+
+Above we saw how a dataclass behaves with the `__ft__` method defined.
+On a plain dataclass, `str()` will be called (but not escaped).
+
+``` python
+from dataclasses import dataclass
+
+@dataclass
+class Hero:
+ title: str
+ statement: str
+
+# rendering the dataclass with the default method
+Main(
+ Hero("
Hello World
", "This is a hero statement")
+)
+```
+
+``` html
+Hero(title='
Hello World
', statement='This is a hero statement')
+```
+
+``` python
+# This will display the HTML as text on your page
+Div("Let's include some HTML here:
Some HTML
")
+```
+
+``` html
+
Let's include some HTML here: <div>Some HTML</div>
+```
+
+``` python
+# Keep the string untouched, will be rendered on the page
+Div(NotStr("
Some HTML
"))
+```
+
+``` html
+
Some HTML
+```
+
+## Custom exception handlers
+
+FastHTML allows customization of exception handlers, but does so
+gracefully. What this means is by default it includes all the ``
+tags needed to display attractive content. Try it out!
+
+``` python
+from fasthtml.common import *
+
+def not_found(req, exc): return Titled("404: I don't exist!")
+
+exception_handlers = {404: not_found}
+
+app, rt = fast_app(exception_handlers=exception_handlers)
+
+@rt('/')
+def get():
+ return (Titled("Home page", P(A(href="/oops")("Click to generate 404 error"))))
+
+serve()
+```
+
+We can also use lambda to make things more terse:
+
+``` python
+from fasthtml.common import *
+
+exception_handlers={
+ 404: lambda req, exc: Titled("404: I don't exist!"),
+ 418: lambda req, exc: Titled("418: I'm a teapot!")
+}
+
+app, rt = fast_app(exception_handlers=exception_handlers)
+
+@rt('/')
+def get():
+ return (Titled("Home page", P(A(href="/oops")("Click to generate 404 error"))))
+
+serve()
+```
+
+## Cookies
+
+We can set cookies using the `cookie()` function. In our example, we’ll
+create a `timestamp` cookie.
+
+``` python
+from datetime import datetime
+from IPython.display import HTML
+```
+
+``` python
+@rt("/settimestamp")
+def get(req):
+ now = datetime.now()
+ return P(f'Set to {now}'), cookie('now', datetime.now())
+
+HTML(client.get('/settimestamp').text)
+```
+
+
+
+
+ FastHTML page
+
+
+
Set to 2024-09-04 18:30:34.896373
+
+
+
+Now let’s get it back using the same name for our parameter as the
+cookie name.
+
+``` python
+@rt('/gettimestamp')
+def get(now:date): return f'Cookie was set at time {now.time()}'
+
+client.get('/gettimestamp').text
+```
+
+ 'Cookie was set at time 18:30:34.896405'
+
+## Sessions
+
+For convenience and security, FastHTML has a mechanism for storing small
+amounts of data in the user’s browser. We can do this by adding a
+`session` argument to routes. FastHTML sessions are Python dictionaries,
+and we can leverage to our benefit. The example below shows how to
+concisely set and get sessions.
+
+``` python
+@rt('/adder/{num}')
+def get(session, num: int):
+ session.setdefault('sum', 0)
+ session['sum'] = session.get('sum') + num
+ return Response(f'The sum is {session["sum"]}.')
+```
+
+## Toasts (also known as Messages)
+
+Toasts, sometimes called “Messages” are small notifications usually in
+colored boxes used to notify users that something has happened. Toasts
+can be of four types:
+
+- info
+- success
+- warning
+- error
+
+Examples toasts might include:
+
+- “Payment accepted”
+- “Data submitted”
+- “Request approved”
+
+Toasts require the use of the `setup_toasts()` function plus every view
+needs these two features:
+
+- The session argument
+- Must return FT components
+
+``` python
+setup_toasts(app)
+
+@rt('/toasting')
+def get(session):
+ # Normally one toast is enough, this allows us to see
+ # different toast types in action.
+ add_toast(session, f"Toast is being cooked", "info")
+ add_toast(session, f"Toast is ready", "success")
+ add_toast(session, f"Toast is getting a bit crispy", "warning")
+ add_toast(session, f"Toast is burning!", "error")
+ return Titled("I like toast")
+```
+
+Line 1
+`setup_toasts` is a helper function that adds toast dependencies.
+Usually this would be declared right after `fast_app()`
+
+Line 4
+Toasts require sessions
+
+Line 11
+Views with Toasts must return FT components.
+
+## Authentication and authorization
+
+In FastHTML the tasks of authentication and authorization are handled
+with Beforeware. Beforeware are functions that run before the route
+handler is called. They are useful for global tasks like ensuring users
+are authenticated or have permissions to access a view.
+
+First, we write a function that accepts a request and session arguments:
+
+``` python
+# Status code 303 is a redirect that can change POST to GET,
+# so it's appropriate for a login page.
+login_redir = RedirectResponse('/login', status_code=303)
+
+def user_auth_before(req, sess):
+ # The `auth` key in the request scope is automatically provided
+ # to any handler which requests it, and can not be injected
+ # by the user using query params, cookies, etc, so it should
+ # be secure to use.
+ auth = req.scope['auth'] = sess.get('auth', None)
+ # If the session key is not there, it redirects to the login page.
+ if not auth: return login_redir
+```
+
+Now we pass our `user_auth_before` function as the first argument into a
+[`Beforeware`](https://AnswerDotAI.github.io/fasthtml/api/core.html#beforeware)
+class. We also pass a list of regular expressions to the `skip`
+argument, designed to allow users to still get to the home and login
+pages.
+
+``` python
+beforeware = Beforeware(
+ user_auth_before,
+ skip=[r'/favicon\.ico', r'/static/.*', r'.*\.css', r'.*\.js', '/login', '/']
+)
+
+app, rt = fast_app(before=beforeware)
+```
+
+## Server-sent events (SSE)
+
+With [server-sent
+events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events),
+it’s possible for a server to send new data to a web page at any time,
+by pushing messages to the web page. Unlike WebSockets, SSE can only go
+in one direction: server to client. SSE is also part of the HTTP
+specification unlike WebSockets which uses its own specification.
+
+FastHTML introduces several tools for working with SSE which are covered
+in the example below. While concise, there’s a lot going on in this
+function so we’ve annotated it quite a bit.
+
+``` python
+import random
+from asyncio import sleep
+from fasthtml.common import *
+
+hdrs=(Script(src="https://unpkg.com/htmx-ext-sse@2.2.1/sse.js"),)
+app,rt = fast_app(hdrs=hdrs)
+
+@rt
+def index():
+ return Titled("SSE Random Number Generator",
+ P("Generate pairs of random numbers, as the list grows scroll downwards."),
+ Div(hx_ext="sse",
+ sse_connect="/number-stream",
+ hx_swap="beforeend show:bottom",
+ sse_swap="message"))
+
+shutdown_event = signal_shutdown()
+
+async def number_generator():
+ while not shutdown_event.is_set():
+ data = Article(random.randint(1, 100))
+ yield sse_message(data)
+ await sleep(1)
+
+@rt("/number-stream")
+async def get(): return EventStream(number_generator())
+```
+
+Line 5
+Import the HTMX SSE extension
+
+Line 12
+Tell HTMX to load the SSE extension
+
+Line 13
+Look at the `/number-stream` endpoint for SSE content
+
+Line 14
+When new items come in from the SSE endpoint, add them at the end of the
+current content within the div. If they go beyond the screen, scroll
+downwards
+
+Line 15
+Specify the name of the event. FastHTML’s default event name is
+“message”. Only change if you have more than one call to SSE endpoints
+within a view
+
+Line 17
+Set up the asyncio event loop
+
+Line 19
+Don’t forget to make this an `async` function!
+
+Line 20
+Iterate through the asyncio event loop
+
+Line 22
+We yield the data. Data ideally should be comprised of FT components as
+that plugs nicely into HTMX in the browser
+
+Line 26
+The endpoint view needs to be an async function that returns a
+[`EventStream`](https://AnswerDotAI.github.io/fasthtml/api/core.html#eventstream)
+
+
+
+> **New content as of September 1, 2024**
+>
+> - [Forms](../tutorials/quickstart_for_web_devs.html#forms)
+> - [Server-side Events
+> (SSE)](../tutorials/quickstart_for_web_devs.html#server-sent-events-sse)
+>
+> We’re going to be adding more to this document, so check back
+> frequently for updates.
+
+
+
+| Attribute | Description |
+|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
+| [`hx-get`](@/attributes/hx-get.md) | issues a `GET` to the specified URL |
+| [`hx-post`](@/attributes/hx-post.md) | issues a `POST` to the specified URL |
+| [`hx-on*`](@/attributes/hx-on.md) | handle events with inline scripts on elements |
+| [`hx-push-url`](@/attributes/hx-push-url.md) | push a URL into the browser location bar to create history |
+| [`hx-select`](@/attributes/hx-select.md) | select content to swap in from a response |
+| [`hx-select-oob`](@/attributes/hx-select-oob.md) | select content to swap in from a response, somewhere other than the target (out of band) |
+| [`hx-swap`](@/attributes/hx-swap.md) | controls how content will swap in (`outerHTML`, `beforeend`, `afterend`, ...) |
+| [`hx-swap-oob`](@/attributes/hx-swap-oob.md) | mark element to swap in from a response (out of band) |
+| [`hx-target`](@/attributes/hx-target.md) | specifies the target element to be swapped |
+| [`hx-trigger`](@/attributes/hx-trigger.md) | specifies the event that triggers the request |
+| [`hx-vals`](@/attributes/hx-vals.md) | add values to submit with the request (JSON format) |
+
+
+
+## Additional Attribute Reference {#attributes-additional}
+
+All other attributes available in htmx.
+
+
+
+| Attribute | Description |
+|------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|
+| [`hx-boost`](@/attributes/hx-boost.md) | add [progressive enhancement](https://en.wikipedia.org/wiki/Progressive_enhancement) for links and forms |
+| [`hx-confirm`](@/attributes/hx-confirm.md) | shows a `confirm()` dialog before issuing a request |
+| [`hx-delete`](@/attributes/hx-delete.md) | issues a `DELETE` to the specified URL |
+| [`hx-disable`](@/attributes/hx-disable.md) | disables htmx processing for the given node and any children nodes |
+| [`hx-disabled-elt`](@/attributes/hx-disabled-elt.md) | adds the `disabled` attribute to the specified elements while a request is in flight |
+| [`hx-disinherit`](@/attributes/hx-disinherit.md) | control and disable automatic attribute inheritance for child nodes |
+| [`hx-encoding`](@/attributes/hx-encoding.md) | changes the request encoding type |
+| [`hx-ext`](@/attributes/hx-ext.md) | extensions to use for this element |
+| [`hx-headers`](@/attributes/hx-headers.md) | adds to the headers that will be submitted with the request |
+| [`hx-history`](@/attributes/hx-history.md) | prevent sensitive data being saved to the history cache |
+| [`hx-history-elt`](@/attributes/hx-history-elt.md) | the element to snapshot and restore during history navigation |
+| [`hx-include`](@/attributes/hx-include.md) | include additional data in requests |
+| [`hx-indicator`](@/attributes/hx-indicator.md) | the element to put the `htmx-request` class on during the request |
+| [`hx-inherit`](@/attributes/hx-inherit.md) | control and enable automatic attribute inheritance for child nodes if it has been disabled by default |
+| [`hx-params`](@/attributes/hx-params.md) | filters the parameters that will be submitted with a request |
+| [`hx-patch`](@/attributes/hx-patch.md) | issues a `PATCH` to the specified URL |
+| [`hx-preserve`](@/attributes/hx-preserve.md) | specifies elements to keep unchanged between requests |
+| [`hx-prompt`](@/attributes/hx-prompt.md) | shows a `prompt()` before submitting a request |
+| [`hx-put`](@/attributes/hx-put.md) | issues a `PUT` to the specified URL |
+| [`hx-replace-url`](@/attributes/hx-replace-url.md) | replace the URL in the browser location bar |
+| [`hx-request`](@/attributes/hx-request.md) | configures various aspects of the request |
+| [`hx-sync`](@/attributes/hx-sync.md) | control how requests made by different elements are synchronized |
+| [`hx-validate`](@/attributes/hx-validate.md) | force elements to validate themselves before a request |
+| [`hx-vars`](@/attributes/hx-vars.md) | adds values dynamically to the parameters to submit with the request (deprecated, please use [`hx-vals`](@/attributes/hx-vals.md)) |
+
+
+
+## CSS Class Reference {#classes}
+
+
+
+| Class | Description |
+|-----------|-------------|
+| `htmx-added` | Applied to a new piece of content before it is swapped, removed after it is settled.
+| `htmx-indicator` | A dynamically generated class that will toggle visible (opacity:1) when a `htmx-request` class is present
+| `htmx-request` | Applied to either the element or the element specified with [`hx-indicator`](@/attributes/hx-indicator.md) while a request is ongoing
+| `htmx-settling` | Applied to a target after content is swapped, removed after it is settled. The duration can be modified via [`hx-swap`](@/attributes/hx-swap.md).
+| `htmx-swapping` | Applied to a target before any content is swapped, removed after it is swapped. The duration can be modified via [`hx-swap`](@/attributes/hx-swap.md).
+
+
+
+| Header | Description |
+|--------|-------------|
+| `HX-Boosted` | indicates that the request is via an element using [hx-boost](@/attributes/hx-boost.md)
+| `HX-Current-URL` | the current URL of the browser
+| `HX-History-Restore-Request` | "true" if the request is for history restoration after a miss in the local history cache
+| `HX-Prompt` | the user response to an [hx-prompt](@/attributes/hx-prompt.md)
+| `HX-Request` | always "true"
+| `HX-Target` | the `id` of the target element if it exists
+| `HX-Trigger-Name` | the `name` of the triggered element if it exists
+| `HX-Trigger` | the `id` of the triggered element if it exists
+
+
+
+| Header | Description |
+|------------------------------------------------------|-------------|
+| [`HX-Location`](@/headers/hx-location.md) | allows you to do a client-side redirect that does not do a full page reload
+| [`HX-Push-Url`](@/headers/hx-push-url.md) | pushes a new url into the history stack
+| `HX-Redirect` | can be used to do a client-side redirect to a new location
+| `HX-Refresh` | if set to "true" the client-side will do a full refresh of the page
+| [`HX-Replace-Url`](@/headers/hx-replace-url.md) | replaces the current URL in the location bar
+| `HX-Reswap` | allows you to specify how the response will be swapped. See [hx-swap](@/attributes/hx-swap.md) for possible values
+| `HX-Retarget` | a CSS selector that updates the target of the content update to a different element on the page
+| `HX-Reselect` | a CSS selector that allows you to choose which part of the response is used to be swapped in. Overrides an existing [`hx-select`](@/attributes/hx-select.md) on the triggering element
+| [`HX-Trigger`](@/headers/hx-trigger.md) | allows you to trigger client-side events
+| [`HX-Trigger-After-Settle`](@/headers/hx-trigger.md) | allows you to trigger client-side events after the settle step
+| [`HX-Trigger-After-Swap`](@/headers/hx-trigger.md) | allows you to trigger client-side events after the swap step
+
+
+
+## Event Reference {#events}
+
+
+
+| Event | Description |
+|-------|-------------|
+| [`htmx:abort`](@/events.md#htmx:abort) | send this event to an element to abort a request
+| [`htmx:afterOnLoad`](@/events.md#htmx:afterOnLoad) | triggered after an AJAX request has completed processing a successful response
+| [`htmx:afterProcessNode`](@/events.md#htmx:afterProcessNode) | triggered after htmx has initialized a node
+| [`htmx:afterRequest`](@/events.md#htmx:afterRequest) | triggered after an AJAX request has completed
+| [`htmx:afterSettle`](@/events.md#htmx:afterSettle) | triggered after the DOM has settled
+| [`htmx:afterSwap`](@/events.md#htmx:afterSwap) | triggered after new content has been swapped in
+| [`htmx:beforeCleanupElement`](@/events.md#htmx:beforeCleanupElement) | triggered before htmx [disables](@/attributes/hx-disable.md) an element or removes it from the DOM
+| [`htmx:beforeOnLoad`](@/events.md#htmx:beforeOnLoad) | triggered before any response processing occurs
+| [`htmx:beforeProcessNode`](@/events.md#htmx:beforeProcessNode) | triggered before htmx initializes a node
+| [`htmx:beforeRequest`](@/events.md#htmx:beforeRequest) | triggered before an AJAX request is made
+| [`htmx:beforeSwap`](@/events.md#htmx:beforeSwap) | triggered before a swap is done, allows you to configure the swap
+| [`htmx:beforeSend`](@/events.md#htmx:beforeSend) | triggered just before an ajax request is sent
+| [`htmx:configRequest`](@/events.md#htmx:configRequest) | triggered before the request, allows you to customize parameters, headers
+| [`htmx:confirm`](@/events.md#htmx:confirm) | triggered after a trigger occurs on an element, allows you to cancel (or delay) issuing the AJAX request
+| [`htmx:historyCacheError`](@/events.md#htmx:historyCacheError) | triggered on an error during cache writing
+| [`htmx:historyCacheMiss`](@/events.md#htmx:historyCacheMiss) | triggered on a cache miss in the history subsystem
+| [`htmx:historyCacheMissError`](@/events.md#htmx:historyCacheMissError) | triggered on a unsuccessful remote retrieval
+| [`htmx:historyCacheMissLoad`](@/events.md#htmx:historyCacheMissLoad) | triggered on a successful remote retrieval
+| [`htmx:historyRestore`](@/events.md#htmx:historyRestore) | triggered when htmx handles a history restoration action
+| [`htmx:beforeHistorySave`](@/events.md#htmx:beforeHistorySave) | triggered before content is saved to the history cache
+| [`htmx:load`](@/events.md#htmx:load) | triggered when new content is added to the DOM
+| [`htmx:noSSESourceError`](@/events.md#htmx:noSSESourceError) | triggered when an element refers to a SSE event in its trigger, but no parent SSE source has been defined
+| [`htmx:onLoadError`](@/events.md#htmx:onLoadError) | triggered when an exception occurs during the onLoad handling in htmx
+| [`htmx:oobAfterSwap`](@/events.md#htmx:oobAfterSwap) | triggered after an out of band element as been swapped in
+| [`htmx:oobBeforeSwap`](@/events.md#htmx:oobBeforeSwap) | triggered before an out of band element swap is done, allows you to configure the swap
+| [`htmx:oobErrorNoTarget`](@/events.md#htmx:oobErrorNoTarget) | triggered when an out of band element does not have a matching ID in the current DOM
+| [`htmx:prompt`](@/events.md#htmx:prompt) | triggered after a prompt is shown
+| [`htmx:pushedIntoHistory`](@/events.md#htmx:pushedIntoHistory) | triggered after an url is pushed into history
+| [`htmx:responseError`](@/events.md#htmx:responseError) | triggered when an HTTP response error (non-`200` or `300` response code) occurs
+| [`htmx:sendError`](@/events.md#htmx:sendError) | triggered when a network error prevents an HTTP request from happening
+| [`htmx:sseError`](@/events.md#htmx:sseError) | triggered when an error occurs with a SSE source
+| [`htmx:sseOpen`](/events#htmx:sseOpen) | triggered when a SSE source is opened
+| [`htmx:swapError`](@/events.md#htmx:swapError) | triggered when an error occurs during the swap phase
+| [`htmx:targetError`](@/events.md#htmx:targetError) | triggered when an invalid target is specified
+| [`htmx:timeout`](@/events.md#htmx:timeout) | triggered when a request timeout occurs
+| [`htmx:validation:validate`](@/events.md#htmx:validation:validate) | triggered before an element is validated
+| [`htmx:validation:failed`](@/events.md#htmx:validation:failed) | triggered when an element fails validation
+| [`htmx:validation:halted`](@/events.md#htmx:validation:halted) | triggered when a request is halted due to validation errors
+| [`htmx:xhr:abort`](@/events.md#htmx:xhr:abort) | triggered when an ajax request aborts
+| [`htmx:xhr:loadend`](@/events.md#htmx:xhr:loadend) | triggered when an ajax request ends
+| [`htmx:xhr:loadstart`](@/events.md#htmx:xhr:loadstart) | triggered when an ajax request starts
+| [`htmx:xhr:progress`](@/events.md#htmx:xhr:progress) | triggered periodically during an ajax request that supports progress events
+
+
+
+## JavaScript API Reference {#api}
+
+
+
+| Method | Description |
+|-------|-------------|
+| [`htmx.addClass()`](@/api.md#addClass) | Adds a class to the given element
+| [`htmx.ajax()`](@/api.md#ajax) | Issues an htmx-style ajax request
+| [`htmx.closest()`](@/api.md#closest) | Finds the closest parent to the given element matching the selector
+| [`htmx.config`](@/api.md#config) | A property that holds the current htmx config object
+| [`htmx.createEventSource`](@/api.md#createEventSource) | A property holding the function to create SSE EventSource objects for htmx
+| [`htmx.createWebSocket`](@/api.md#createWebSocket) | A property holding the function to create WebSocket objects for htmx
+| [`htmx.defineExtension()`](@/api.md#defineExtension) | Defines an htmx [extension](https://extensions.htmx.org)
+| [`htmx.find()`](@/api.md#find) | Finds a single element matching the selector
+| [`htmx.findAll()` `htmx.findAll(elt, selector)`](@/api.md#find) | Finds all elements matching a given selector
+| [`htmx.logAll()`](@/api.md#logAll) | Installs a logger that will log all htmx events
+| [`htmx.logger`](@/api.md#logger) | A property set to the current logger (default is `null`)
+| [`htmx.off()`](@/api.md#off) | Removes an event listener from the given element
+| [`htmx.on()`](@/api.md#on) | Creates an event listener on the given element, returning it
+| [`htmx.onLoad()`](@/api.md#onLoad) | Adds a callback handler for the `htmx:load` event
+| [`htmx.parseInterval()`](@/api.md#parseInterval) | Parses an interval declaration into a millisecond value
+| [`htmx.process()`](@/api.md#process) | Processes the given element and its children, hooking up any htmx behavior
+| [`htmx.remove()`](@/api.md#remove) | Removes the given element
+| [`htmx.removeClass()`](@/api.md#removeClass) | Removes a class from the given element
+| [`htmx.removeExtension()`](@/api.md#removeExtension) | Removes an htmx [extension](https://extensions.htmx.org)
+| [`htmx.swap()`](@/api.md#swap) | Performs swapping (and settling) of HTML content
+| [`htmx.takeClass()`](@/api.md#takeClass) | Takes a class from other elements for the given element
+| [`htmx.toggleClass()`](@/api.md#toggleClass) | Toggles a class from the given element
+| [`htmx.trigger()`](@/api.md#trigger) | Triggers an event on an element
+| [`htmx.values()`](@/api.md#values) | Returns the input values associated with the given element
+
+
+
+
+## Configuration Reference {#config}
+
+Htmx has some configuration options that can be accessed either programmatically or declaratively. They are
+listed below:
+
+
+
+| Config Variable | Info |
+|---------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `htmx.config.historyEnabled` | defaults to `true`, really only useful for testing |
+| `htmx.config.historyCacheSize` | defaults to 10 |
+| `htmx.config.refreshOnHistoryMiss` | defaults to `false`, if set to `true` htmx will issue a full page refresh on history misses rather than use an AJAX request |
+| `htmx.config.defaultSwapStyle` | defaults to `innerHTML` |
+| `htmx.config.defaultSwapDelay` | defaults to 0 |
+| `htmx.config.defaultSettleDelay` | defaults to 20 |
+| `htmx.config.includeIndicatorStyles` | defaults to `true` (determines if the indicator styles are loaded) |
+| `htmx.config.indicatorClass` | defaults to `htmx-indicator` |
+| `htmx.config.requestClass` | defaults to `htmx-request` |
+| `htmx.config.addedClass` | defaults to `htmx-added` |
+| `htmx.config.settlingClass` | defaults to `htmx-settling` |
+| `htmx.config.swappingClass` | defaults to `htmx-swapping` |
+| `htmx.config.allowEval` | defaults to `true`, can be used to disable htmx's use of eval for certain features (e.g. trigger filters) |
+| `htmx.config.allowScriptTags` | defaults to `true`, determines if htmx will process script tags found in new content |
+| `htmx.config.inlineScriptNonce` | defaults to `''`, meaning that no nonce will be added to inline scripts |
+| `htmx.config.inlineStyleNonce` | defaults to `''`, meaning that no nonce will be added to inline styles |
+| `htmx.config.attributesToSettle` | defaults to `["class", "style", "width", "height"]`, the attributes to settle during the settling phase |
+| `htmx.config.wsReconnectDelay` | defaults to `full-jitter` |
+| `htmx.config.wsBinaryType` | defaults to `blob`, the [the type of binary data](https://developer.mozilla.org/docs/Web/API/WebSocket/binaryType) being received over the WebSocket connection |
+| `htmx.config.disableSelector` | defaults to `[hx-disable], [data-hx-disable]`, htmx will not process elements with this attribute on it or a parent |
+| `htmx.config.withCredentials` | defaults to `false`, allow cross-site Access-Control requests using credentials such as cookies, authorization headers or TLS client certificates |
+| `htmx.config.timeout` | defaults to 0, the number of milliseconds a request can take before automatically being terminated |
+| `htmx.config.scrollBehavior` | defaults to 'instant', the behavior for a boosted link on page transitions. The allowed values are `auto`, `instant` and `smooth`. Instant will scroll instantly in a single jump, smooth will scroll smoothly, while auto will behave like a vanilla link. |
+| `htmx.config.defaultFocusScroll` | if the focused element should be scrolled into view, defaults to false and can be overridden using the [focus-scroll](@/attributes/hx-swap.md#focus-scroll) swap modifier. |
+| `htmx.config.getCacheBusterParam` | defaults to false, if set to true htmx will append the target element to the `GET` request in the format `org.htmx.cache-buster=targetElementId` |
+| `htmx.config.globalViewTransitions` | if set to `true`, htmx will use the [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) API when swapping in new content. |
+| `htmx.config.methodsThatUseUrlParams` | defaults to `["get"]`, htmx will format requests with these methods by encoding their parameters in the URL, not the request body |
+| `htmx.config.selfRequestsOnly` | defaults to `true`, whether to only allow AJAX requests to the same domain as the current document |
+| `htmx.config.ignoreTitle` | defaults to `false`, if set to `true` htmx will not update the title of the document when a `title` tag is found in new content |
+| `htmx.config.scrollIntoViewOnBoost` | defaults to `true`, whether or not the target of a boosted element is scrolled into the viewport. If `hx-target` is omitted on a boosted element, the target defaults to `body`, causing the page to scroll to the top. |
+| `htmx.config.triggerSpecsCache` | defaults to `null`, the cache to store evaluated trigger specifications into, improving parsing performance at the cost of more memory usage. You may define a simple object to use a never-clearing cache, or implement your own system using a [proxy object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) |
+| `htmx.config.allowNestedOobSwaps` | defaults to `true`, whether to process OOB swaps on elements that are nested within the main response element. See [Nested OOB Swaps](@/attributes/hx-swap-oob.md#nested-oob-swaps). |
+
+
+
+You can set them directly in javascript, or you can use a `meta` tag:
+
+```html
+
+```
+ # 🗿 Surreal
+### Tiny jQuery alternative for plain Javascript with inline [Locality of Behavior](https://htmx.org/essays/locality-of-behaviour/)!
+
+![cover](https://user-images.githubusercontent.com/24665/171092805-b41286b2-be4a-4aab-9ee6-d604699cc507.png)
+(Art by [shahabalizadeh](https://www.deviantart.com/shahabalizadeh))
+
+
+## Why does this exist?
+
+For devs who love ergonomics! You may appreciate Surreal if:
+
+* You want to stay as close as possible to Vanilla JS.
+* Hate typing `document.querySelector` over.. and over..
+* Hate typing `addEventListener` over.. and over..
+* Really wish `document.querySelectorAll` had Array functions..
+* Really wish `this` would work in any inline `
+
+```
+
+See the [Live Example](https://gnat.github.io/surreal/example.html)! Then [view source](https://github.com/gnat/surreal/blob/main/example.html).
+
+## 🎁 Install
+
+Surreal is only 320 lines. No build step. No dependencies.
+
+[📥 Download](https://raw.githubusercontent.com/gnat/surreal/main/surreal.js) into your project, and add `` in your ``
+
+Or, 🌐 via CDN: ``
+
+## ⚡ Usage
+
+### 🔍️ DOM Selection
+
+* Select **one** element: `me(...)`
+ * Can be any of:
+ * CSS selector: `".button"`, `"#header"`, `"h1"`, `"body > .block"`
+ * Variables: `body`, `e`, `some_element`
+ * Events: `event.currentTarget` will be used.
+ * Surreal selectors: `me()`,`any()`
+ * Choose the start location in the DOM with the 2nd arg. (Default: `document`)
+ * 🔥 `any('button', me('#header')).classAdd('red')`
+ * Add `.red` to any `
+ # 🌘 CSS Scope Inline
+
+![cover](https://github.com/gnat/css-scope-inline/assets/24665/c4935c1b-34e3-4220-9d42-11f064999a57)
+(Art by [shahabalizadeh](https://www.artstation.com/artwork/zDgdd))
+
+## Why does this exist?
+
+* You want an easy inline vanilla CSS experience without Tailwind CSS.
+* Hate creating unique class names over.. and over.. to use once.
+* You want to co-locate your styles for ⚡️ [Locality of Behavior (LoB)](https://htmx.org/essays/locality-of-behaviour/)
+* You wish `this` would work in `
+
+
+```
+See the [Live Example](https://gnat.github.io/css-scope-inline/example.html)! Then [view source](https://github.com/gnat/css-scope-inline/blob/main/example.html).
+
+## 🌘 How does it work?
+
+This uses `MutationObserver` to monitor the DOM, and the moment a `
+ red
+
green
+
green
+
green
+
yellow
+
blue
+
green
+
green
+
+
+
+ red
+
green
+
green
+
green
+
yellow
+
blue
+
green
+
green
+
+```
+
+### CSS variables and child elements
+At first glance, **Tailwind Example 2** looks very promising! Exciting ...but:
+* 🔴 **Every child style requires an explicit selector.**
+ * Tailwinds' shorthand advantages sadly disappear.
+ * Any more child styles added in Tailwind will become longer than vanilla CSS.
+ * This limited example is the best case scenario for Tailwind.
+* 🔴 Not visible on github: **no highlighting for properties and units** begins to be painful.
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+```
+## 🔎 Technical FAQ
+* Why do you use `querySelectorAll()` and not just process the `MutationObserver` results directly?
+ * This was indeed the original design; it will work well up until you begin recieving subtrees (ex: DOM swaps with [htmx](https://htmx.org), ajax, jquery, etc.) which requires walking all subtree elements to ensure we do not miss a `