TrevStack
This is a CRUD app to use as a template for starting projects
Features
- Communicate anywhere. Define a protocol buffer, and Connect generates type-safe code to facilitate communication between the server and any client (web, mobile, embedded, etc). The protocol buffers can contain annotations to validate fields on the client and server. For clients that cannot use Connect, an OpenAPI spec is also generated
- Build anywhere. The dev environment, testing and building is all declared in a single Nix flake. Every developer and server can use the same environment
- Deploy anywhere. CI/CD is already set up using github actions. New versions are automatically released for every major platform, along with a docker image. The binaries created require zero run-time dependencies and are relatively small (this app is 26 MiB)
- Can be entirely self-hosted
- Authentication is rolled in, including API key, fingerprint & passkey
- Automatic database migration on startup
- Light & dark modes with the catppuccin color palette
- Really good at running as a progressive web app
While I personally prefer using a Svelte frontend and Go backend, feel free to swap them out with whatever you like, you'll be surprised how easy it is.
Getting Started
- Install Nix
- Run
nix develop
- Create a
server/.env
file that looks something like
KEY=changeme
PORT=8080
URL=http://localhost:5173
DATABASE_URL=sqlite:/home/trev/.config/trevstack/sqlite.db
- Run
treli
to start the server & client
It's that simple. If you're feeling fancy, install direnv and the dev environment will load automatically.
Useful Commands
-
nix run #update
: updates all of the dependencies -
nix run #bump [major | minor]
: bumps the current version up one. Defaults to "patch" (0.0.1 -> 0.0.2) -
nix build [#trevstack-(GOOS)-(GOARCH)]
: builds the application. Defaults to building for your current platform, but can be built to many by specifying the GOOS and GOARCH values -
nix flake check
: runs all validations -
buf lint proto
&buf generate
: lints and generates code from protocol buffers -
sqlc vet
&sqlc generate
: verifies and generates code from SQL files -
dbmate new
&dbmate up
: creates a new migration file and runs pending migrations
Github Actions
To use github actions for CI/CD, you'll need to create a fine-grained personal access token for the repository with the permissions:
- Contents (read and write)
- Pull requests (read and write)
And change some settings for the repository:
- General -> Allow auto-merge: true
- Rules -> Rulesets -> New ruleset
- Branch targeting criteria: Default
- Branch rules
- Require status checks to pass -> Add checks -> "check"
- Actions -> General -> Workflow permissions
- Read and write permissions: true
- Allow GitHub Actions to create and approve pull requests: true
- Secrets and variables -> Actions -> Repository secrets
- PAT: (personal access token)
Gitea Actions
To use gitea actions for CI/CD, you'll need to create an API token with the scopes:
- write:repository
- write:package
And change some settings for the repository:
- Repository -> Delete pull request branch after merge by default: true
- Branches -> Add New Rule
- Protected Branch Name Pattern: main
- Enable Status Check: true
- Status check patterns: Check / check*
- Actions -> Secrets
- PAT: (API token)
Components
Client
- svelte 5 [docs] UI framework
- tailwind 4 [docs] CSS framework
- bits ui [docs] headless components
- components from shadcn-svelte [docs] altered to work with tailwind 4, fit the catppuccin color palette, and use shallow routing
- connect rpc [docs] to communicating with the server
- protovalidate-es [docs], along with a function coolforms to emulate the library sveltekit-superforms
- simplewebauthn [docs] for passkey authentication
- scalar [docs] for displaying openapi specs
- tw-animate-css [docs] to animate with just tailwind classes
- vite [docs] for dev server and bundling
- eslint [docs] for linting
- prettier [docs] for formatting
Server
- go [docs]
- connect rpc [docs] to serve gRPC & HTTP requests
- protovalidate-go [docs] for validating those requests
- sqlc [docs] because writing the SQL yourself is better than an ORM
- go-webauthn [docs] because webauthn is hard
- dbmate [docs] for database migrations
- revive [docs] for linting