Apply changes proposed by @mdb in #37 and use the opportunity to clear out some obsolete cruft.

This commit is contained in:
Sebastian Jeltsch
2025-03-24 12:25:46 +01:00
parent 9f18a992d0
commit fe591cfdea
6 changed files with 89 additions and 149 deletions

View File

@@ -1,5 +1,3 @@
# example.com
localhost
encode gzip zstd
reverse_proxy blog:4000

View File

@@ -18,27 +18,86 @@
</picture>
</p>
The main goal of this example is to be easily digestible while show-casing many
of TrailBase's capabilities both for web and cross-platform Flutter:
The blog example presents some of TrailBase's capabilities in an easily easily
digestible fashion:
* Bootstrapping the database including schemas and dummy content though migration.
* End-to-end type-safety through code-generated data models for TypeScript,
Dart and many more based on JSON Schema.
* Builtin web authentication flow (including OAuth) on web and Flutter as well
as a custom password-based login in Flutter.
* API authorization: world readable, user editable, and moderator manageable articles.
* Building UI Apps both for web and cross-platform using Flutter.
* End-to-end type-safe APIs based on JSON schemas and code-generation
supporting most popular languages.
* Authentication flows with social OAuth and password sign-in for web and Flutter.
* Authorization: world readable, user editable, and moderator manageable articles.
* Different API types:
* Table and View-based APIs for custom user profiles associating users with a
username and keep their email addresses private as well as associating
articles with usernames.
* Virtual-table-based query API to expose `is_editor` authorization.
* The web client illustrates two different styles: a consumer SPA and an
HTML-only form-based authoring UI.
* Table and View-based APIs for custom user profiles associating users with a
username to keep their email addresses private as well as associating
articles with usernames.
* Virtual-table-based query API to expose `is_editor` authorization.
* Migrations to bootstrap the database with schemas and dummy content.
* The web UI is implemented as a reader-side SPA and static HTML page for blog
authors to demonstrate both styles.
Default users:
## Getting Started
* (email: `admin@localhost`, password: `secret`) - access to admin dash.
* (email: `editor@localhost`, password: `secret`) - permission to write and alter blog posts.
To get the blog up and running with self-signed SSL certificates in under 2
minutes, simply run:
```bash
cd examples/blog
docker compose up --build -d
```
Afterwards check out the blog at [http://localhost](http://localhost). You'll
be automatically forwarded to HTTPS and will need to accept the self-signed
certificate.
You can write new blog posts using the predefined user:
* email: `editor@localhost`
* password: `secret`
You can also check out the admin dashboard at
[http://localhost/_/admin](http://localhost/_/admin) using the predefined
admin:
* email: `admin@localhost`
* password: `secret`
For context, the above `docker compose` invocation started two services:
* TrailBase itself hosting the web UI, and
* a [Caddy](https://github.com/caddyserver/caddy) reverse-proxy to
automatically terminate TLS using self-signed certificates demonstrating a
production-ready setup.
To shut everything back down, simply run:
```bash
docker compose down
```
## Detailed Instructions
If you don't want to use the docker compose setup above, build from scratch, or
run the the Flutter app, only a few simple steps are needed.
If you have `cargo`, `pnpm`, and `flutter` installed, you can simply run:
```bash
# Build the Blog's web UI:
$ pnpm --dir web build
# Build and start TrailBase:
$ cargo run --bin trail -- run --public web/dist
# Build and start the Flutter app:
$ cd flutter
$ flutter run -d <Device, e.g.: Linux, Chrome, Mobile Emulator, ...>
```
In case you'd like to re-generate the language bindings for the type-safe APIs
or generate new bindings for a different language, check out the `Makefile` or
run:
```bash
$ make --always-make types
```
## Directory Structure
@@ -65,39 +124,6 @@ Default users:
└── ...
```
## Instructions
Generally speaking, there are roughly 2.5 moving parts to run the example, i.e:
we have to build the web UI, start the TrailBase server, and optionally start
the Flutter app. Once you have `cargo`, `pnpm`, and `flutter` installed, you
can simply run:
```bash
# From within the blog examples base directory
$ cd $REPO/examples/blog
# build and bundle the web app:
$ pnpm --dir web build
# Start TrailBase:
cargo run --bin trail -- run --public web/dist
# Start Flutter app:
$ cd flutter
$ flutter run -d <Device, e.g.: Linux, Chrome, Mobile Emulator, ...>
```
You can also try the code generation:
```bash
# Optionally delete the checked-in JSON schemas and code first
$ make clean_types
# Genarate JSON Schema and codegen types from DB schema (this requires that
# you start TrailBase first to initialize the DB)
$ make --always-make types
```
## Reference
* The styling is based on: https://github.com/palmiak/pacamara-astro 🙏
* The styling is based on: [palmiak/pacamara-astro](https://github.com/palmiak/pacamara-astro) 🙏

View File

@@ -1,20 +1,8 @@
services:
blog:
# NOTE: We have to build relative to root to have a build context that
# includes both: the trailbase server source and the demo wepapp sources.
# build: ../..
# TODO: Build from "." once the Dockerfile can pull a base image from
# dockerhub. We still need an example Dockerfile to build the UI.
build:
context: ../..
dockerfile: examples/blog/Dockerfile
build: .
restart: unless-stopped
environment:
TRAIL_INITIAL_PASSWORD: secret
ADDRESS: 0.0.0.0:4000
PUBLIC_DIR: ./public
DATA_DIR: ./traildepot
volumes:
- ./traildepot:/app/traildepot

View File

@@ -1,80 +0,0 @@
{
"$defs": {
"image": {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"content_type": {
"description": "The file's user-provided content type.",
"type": [
"string",
"null"
]
},
"filename": {
"description": "The file's original file name.",
"type": [
"string",
"null"
]
},
"id": {
"type": "string"
},
"mime_type": {
"description": "The file's inferred mime type. Not user provided.",
"type": [
"string",
"null"
]
}
},
"required": [
"id"
],
"title": "FileUpload",
"type": "object"
}
},
"properties": {
"author": {
"type": "string"
},
"body": {
"type": "string"
},
"created": {
"type": "integer"
},
"id": {
"type": "string"
},
"image": {
"$ref": "#/$defs/image"
},
"intro": {
"type": "string"
},
"tag": {
"type": "string"
},
"title": {
"type": "string"
},
"username": {
"type": "string"
}
},
"required": [
"id",
"author",
"title",
"intro",
"tag",
"body",
"created",
"username"
],
"title": "articles_view",
"type": "object"
}

View File

@@ -21,7 +21,7 @@
"nanostores": "^0.11.4",
"solid-icons": "^1.1.0",
"solid-js": "^1.9.5",
"trailbase": "workspace:*"
"trailbase": "^0.3.3"
},
"devDependencies": {
"@astrojs/solid-js": "^5.0.5",

12
pnpm-lock.yaml generated
View File

@@ -149,8 +149,8 @@ importers:
specifier: ^1.9.5
version: 1.9.5
trailbase:
specifier: workspace:*
version: link:../../../trailbase-core/js/client
specifier: ^0.3.3
version: 0.3.3
devDependencies:
'@astrojs/solid-js':
specifier: ^5.0.5
@@ -5221,6 +5221,9 @@ packages:
resolution: {integrity: sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==}
engines: {node: '>=18'}
trailbase@0.3.3:
resolution: {integrity: sha512-s0GgYMlMbWJKwg3jcu7d9T5AN3rzBlrIeUpOiQhi8ogNX1BoHzRYb0vq3Yy52nEyybCmY+ExnJQvawzm/Yvc0A==}
trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
@@ -11692,6 +11695,11 @@ snapshots:
dependencies:
punycode: 2.3.1
trailbase@0.3.3:
dependencies:
jwt-decode: 4.0.0
uuid: 11.1.0
trim-lines@3.0.1: {}
trough@2.2.0: {}