Skip to content
/ tea Public template

Axum Template. The base behind every Bytebury application, using our preferred stack: Axum, Askama, HTMX, SQLite, OAuth, and Stripe.

License

Notifications You must be signed in to change notification settings

bytebury/tea

Repository files navigation

tea 🧋

Build like bytebury. The official template that we use for our websites, skip all the bootstrapping. We are not suggesting that this is the right way to create an application, this is just our way and we're sharing with everybody. We favor simplicity in developer experience over processes and tools. Hence, running locally is a single command: ./dev.sh and deploying is done automatically through GHA. By keeping local development simple, as well as our architecture, we can move fast — relying on Rust's speed to match on the server. It's how we built Fun Banking, CTRunner, Oolong and continue to build more.

Some Background

This is the template that we use at bytebury. Our primary stack is Axum, Askama, HTMX, and SQLite through SQLx. We run all of our servers on DigitalOcean on various server sizes, so you'll notice some deployment workflows for DigitalOcean (feel free to change that to your liking). We use Stripe as our payment partner and Google for our OAuth (extensible). You will also need to install TailwindCSS. As, we use TailwindCSS to build out stylesheets.

Getting Started

Note

Running ./dev will run the application in watch mode for you as well as run any pending migrations! It is all you need to get started locally.

  1. Clone the repository git clone git@github.com:bytebury/tea.git
  2. Run the development server cd ./tea && ./dev.sh in your terminal

This will run all of your migrations as well as generate a .env file in your root directory. Open it up and change the environment variables to your liking. After that, you should be ready to start development.

Creating a Migration

Note

You will need sqlx installed locally to create migrations.

sqlx migrate add create_my_table

Listen to Stripe Events

You can use the Stripe CLI to listen to the webhooks locally. To do that, you'll need to download the Stripe CLI and then run the following command in a separate terminal:

stripe listen --forward-to localhost:8080/webhooks/stripe

IP Services

Important

If you wish to use IP2Location LITE, you will need to download one of their databases and put it in "db/ip2location.BIN" location.

We use IP2Location LITE for our IP services. If you plan on following suite, know that they require you to attribute them by adding the following HTML to your website.

<p>
  {{ shared.app_info.name }} uses the IP2Location LITE database for
  <a class="underline" href="https://lite.ip2location.com" target="_blank">IP geolocation</a>.
</p>

How Pagination Works

You'll need to implement the Paginatable trait for your entity.

impl Paginatable for User {
  fn table_name() -> &'static str {
    "users"
  }
}

Once you do that, then you will be able to paginate your data like:

// paginate everything, without any filtering
User::paginate(db, Pagination::default())
// paginate with a filter
User::paginate_filter(db, Pagination::default(), "role = ? ORDER BY created_at DESC", vec!["admin"])

RBAC

At this time, we deal with Role Based Access Control (RBAC) through the Can trait. This trait has a singular function that you can implement like so:

impl Can<Resource> for User {
  fn can(&self, action: Action, resource: &Resource) -> bool {
    match self.role {
      Role::Admin => true, // Admins are super-users.
      Role::User => match action {
        Action::Read | Action::Create => true,
        Action::Update | Action::Delete => resource.user_id == self.id,
      }
    }
  }
}

// Usage:

if user.can(Action::Delete, &article) {
  // success
}

if user.cannot(Action::Delete, &article) {
  // uh-oh you can't do that.
}

We decided to do this due to simplicity in our applications. We almost never need granular access through the database — most of the times, roles suffice for our use-cases.

Creating a Server from Scratch

Important

You will need to create a folder called APP_NAME in the root of your server.

For using SSH as a connection, you will need to provide a working private key.

When you are creating a server from scratch, you'll typically need to configure your Nginx, or at least, we do at bytebury. So, we've included a script that does the set up we use: SSL + HTTP/2 enabled via server-setup.sh. This is a one-time command. Once you have your server already configured, you won't need this again. However, we've included it so it can streamline those who use it.

Our Philosophy

  • Focus on what matters — off-load often
  • Be close with the browser — it probably already does it
  • Simple cloud architecture — your server can handle it
  • Simple dev experience — doesn't mean "cool"
  • If people don't ask for it — they probably don't want it

About

Axum Template. The base behind every Bytebury application, using our preferred stack: Axum, Askama, HTMX, SQLite, OAuth, and Stripe.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published