Overview
Clace supports deploying any type of app, in any language/framework, using containerized apps. Apps can also be built where the backend API is in the container but the UI is built using Clace. Clace UI applications implement a Hypermedia driven approach for developing web applications. Applications return HTML fragments as API response using Go html templates. The UI uses HTML enhanced with hypermedia controls using the HTMX library to implement user interactions.
The backend API routes and dependencies like CSS library, JavaScript modules etc are configured using Starlark configuration. Any custom API handling required is implemented in handler functions also written in Starlark. Starlark is a subset of python, optimized for application configuration use-cases.
App Types
Clace apps can be of few different types:
- Action apps: Actions allow apps to expose an autogenerated UI for simple backend actions.
- Containerized apps: The whole app is implemented in a container, Clace proxies the container results. This uses the container and proxy plugins. No Starlark code is required for this.
- Starlark apps: These use the Clace plugins to implement the whole app. No containers are required for such apps.
- Hybrid apps: The backend APIs are implemented in a container. Clace is used to implement the Hypermedia based UI using Starlark handlers. This uses the http plugin to talk to the backend API and the container plugin to configure the backend.
This section of the docs covers Starlark and Hybrid apps. For a containerized app, the --spec
definition includes all the app definition. There is no need to do any custom Starlark config for a regular containerized app.
Sample Starlark App
To create an app with a custom HTML page which shows a listing of files in your root directory, create an ~/myapp4/app.star
file with
load("exec.in", "exec")
def handler(req):
ret = exec.run("ls", ["-l", "/"])
if ret.error:
return {"Error": ret.error, "Lines": []}
return {"Error": "", "Lines": ret.value}
app = ace.app("hello4",
custom_layout=True,
routes = [ace.html("/")],
permissions = [ace.permission("exec.in", "run", ["ls"])]
)
and an ~/myapp4/index.go.html
file with
<!doctype html>
<html>
<head>
<title>File List</title>
{{ template "clace_gen_import" . }}
</head>
<body>
{{ .Data.Error }}
{{ range .Data.Lines }}
{{.}}
<br/>
{{end}}
</body>
</html>
Run clace app create --auth=none --dev --approve ~/myapp4 /hello4
. After that, the app is available at /hello4
. Note that the --dev
option is required for the clace_gen_import
file to be generated which is required for live reload.
This app uses the exec
plugin to run the ls command. The output of the command is shown when the app is accessed. To allow the app to run the plugin command, use the clace app approve
command.
ls
to dir
. Else, use the fs
plugin to make this platform independent. See https://github.com/claceio/apps/blob/main/system/disk_usage/app.star.Custom Layout HTML App
To return HTML response, a HTML template file named *.go.html
is required. Create an ~/myapp2/app.star
file containing
app = ace.app("hello2",
custom_layout=True,
routes = [ace.html("/")]
)
and an ~/myapp2/index.go.html
file containing
hello world2
Run clace app create --auth=none ~/myapp2 /hello2
. After that, the app is available at /hello2
$ curl localhost:25222/hello2
hello world2
The ~/myapp2/index.go.html
can be updated to have a complete HTML page. Use the command clace app reload --promote /hello2
to pick up changes. This app is using custom_layout=True
which means the app developer has to provide the complete HTML.
Default Layout HTML App
The default is custom_layout=False
meaning app developer has to provide only the HTML body, Clace will automatically generate the rest of the HTML. For using the auto generated HTML templates, the app has to be created in dev mode using the --dev
option.
Create an ~/myapp3/app.star
file containing
app = ace.app("hello3",
routes = [ace.html("/")]
)
and an ~/myapp3/app.go.html
file containing
{{block "clace_body" .}}
hello world3
{{end}}
Run clace app create --auth=none --dev ~/myapp3 /hello3
. After that, the app is available at /hello3
. Note that the --dev
option is required for the index_gen.go.html
file to be generated.
There is only one route defined, for page /, which shows a HTML page with the name of the app. The body is generated from the contents of the app.go.html file. A more verbose way to write the same app config would be
app = ace.app(name="hello3",
custom_layout=False,
routes = [ace.html(path="/", full="index_gen.go.html")]
)
Automatic Error Handling
To enable automatic error handling (recommended), add an error_handler
function like:
def error_handler(req, ret):
if req.IsPartial:
return ace.response(ret, "error", retarget="#error_div", reswap="innerHTML")
else:
return ace.response(ret, "error.go.html")