# KBVE — full doc corpus
> Concatenated body text of every long-form doc on kbve.com. Page metadata + index live at /llms.txt.
Generated at build time from the Astro `docs` content collection. 534 entries included; itemdb / npcdb / mapdb / questdb data tables are excluded (see /api/itemdb.json etc. for those).
---
# Android
> Android is an open source operating system based off of Linux that runs within the ARM architecture;
the primary use case is within the mobile/tablet eco-system but it has been expanding into server, desktop and embedables.
Android utilizes a modified Linux kernel optimized for low power devices and real time performance.
Furthermore, the system provides a robust framework for application development through the Android SDK and Java/Kotlin APIs.
Android's modular architecture allows hardware vendors to customize drivers, UI layers, and services for specific devices.
With the introduction of Project Treble and mainline updates, the OS now supports more consistent long-term maintenance and faster security patches.
Beyond consumer devices, Android has also evolved into specialized distributions such as Android TV, Android Auto, and Wear OS, extending its ecosystem across multiple platforms.
Source: https://kbve.com/application/android/
import {
Aside,
Steps,
Card,
CardGrid,
Code,
FileTree,
} from '@astrojs/starlight/components';
import { Giscus, Adsense } from '@/components/astropad';
## Information
Are you ready to step into the heart of a global Android revolution, where millions of users and developers collaborate to improve the open source mobile operating system, giving you endless possibilities to customize your device and operating system.
Unleash your creativity and make your smartphone, tablet, or smartwatch truly your own with the endless array of apps and features available on Android, tailored to fit your unique needs and preferences.
Our job at KBVE will be to provide you with everything you need to deploy your own Android application on almost any device!
This one page guide is meant to serve as your resource manual moving forward, we will start with the cheat sheet below, that makes it easy to reference back in the future.
Jump to the [ADB cheatsheet](#cheatsheet), [data storage](#android-data-storage), or [React Native](#react-native) notes.
## Cheatsheet
The ADB cheat sheet is an essential resource for navigating and managing Android operating systems and applications via the Android Debug Bridge (ADB).
It offers a comprehensive list of basic commands that facilitate various tasks such as installing apps, debugging issues, and accessing device logs.
While the cheat sheet covers a wide range of functionalities, it's important to note that some commands require root access, and certain Android versions may necessitate specific tweaks to the standard commands.
This makes the cheat sheet a versatile and indispensable tool for both novice users and experienced developers working with Android devices.
### Device Commands
Android ADB Device commands are commands that you can use to control the Android device over USB from a computer.
You can use them to list all devices, restart the ADB server, and reboot connected devices.
| Command | Description | Notes / Variants |
| :----------------- | :------------------------------------------------------------------------- | :----------------------------------------------------------------------------- |
| `adb devices` | List all connected devices. | |
| `adb devices -l` | Query additional information (model, product, transport ID). | Useful for identifying multiple devices. |
| `adb get-state` | Display the current device state (`device`, `offline`, or `unauthorized`). | |
| `adb get-serialno` | Query the device’s serial number. | |
| `adb root` | Launch the ADB daemon (`adbd`) with root permissions. | May fail on production builds: `adbd cannot run as root in production builds`. |
| `adb start-server` | Start the ADB server daemon. | Runs automatically if missing when using other ADB commands. |
| `adb kill-server` | Terminate the ADB server process. | Use to restart ADB cleanly if it becomes unresponsive. |
| `adb reboot` | Reboot the currently connected device. | Accepts optional args like `bootloader` or `recovery`. |
| `adb help` | Display general help and usage information. | Lists all supported subcommands. |
### Shell
ADB shell is a command-line interface that you can use to access the shell and run various commands on your Android device.
You can use ADB shell commands to perform actions such as changing the resolution of your device display, uninstalling bloatware or system apps, enabling and disabling features, modifying the system files, ect..
| Command | Description | Notes / Variants |
| :--------------------------------------- | :------------------------------------------------------------------------------------ | :--------------------------------------------------------- |
| `adb shell` | Launch the interactive shell terminal on the connected device. | Equivalent to opening a remote terminal session. |
| `adb -s $deviceString $deviceCommand` | Send a command (`$deviceCommand`) to a specific device identified by `$deviceString`. | Useful when multiple devices are connected. |
| `adb shell pwd` | Print the current working directory on the device. | |
| `adb shell ls` | List the contents of the current directory. | |
| `adb shell ls -s` | List directory contents with file size information. | |
| `adb shell ls -R` | Recursively list contents of all subdirectories. | |
| `adb shell netstat` | Display current TCP/IP network connections. | Useful for debugging sockets and ports. |
| `adb shell dumpsys` | Dump system service information and status reports. | A powerful diagnostic tool for system introspection. |
| `adb shell dumpsys iphonesybinfo` | Retrieve IMEI and related telephony information. | Typo in some Android versions — should be `iphonesubinfo`. |
| `adb shell dumpsys battery` | Display current battery status and related data. | |
| `adb shell dumpsys battery set level $v` | Manually set battery level from `0` to `100`. | Useful for testing low-power states. |
| `adb shell dumpsys battery reset` | Reset battery state to default (real readings). | |
| `adb shell dumpsys activity $package` | Dump activity information for a specific package. | |
| `adb shell pm list features` | List available hardware and software features. | |
| `adb shell service list` | List all registered Android system services. | Often used before running targeted `dumpsys` queries. |
| `adb shell wm` | Base command for WindowManager operations. | Placeholder — requires subcommands. |
| `adb shell wm size` | Show the current screen resolution. | |
| `adb shell wm size $WxH` | Set custom screen resolution (e.g., `1080x1920`). | |
| `adb shell wm size reset` | Reset screen resolution to default. | |
| `adb shell wm density` | Show the current display density (DPI). | |
| `adb shell wm density reset` | Reset display density to system default. | |
| `adb shell ps` | List all running processes on the device. | Similar to Linux `ps` command. |
| `exit` | Exit the current ADB shell session. | Returns to the host terminal. |
### Key Events
Android Key Events - A quick breakdown for each event and how the operating system handles them.
Generic Android Keyevents:
```bash
adb shell input keyevent
```
| Keycode | Command Example | Description |
| :-----: | :---------------------------- | :---------------------- |
| 0 | `adb shell input keyevent 0` | Keycode 0 |
| 1 | `adb shell input keyevent 1` | Soft Left |
| 2 | `adb shell input keyevent 2` | Soft Right |
| 3 | `adb shell input keyevent 3` | Home Button Event |
| 4 | `adb shell input keyevent 4` | Back Button Event |
| 5 | `adb shell input keyevent 5` | Call Event |
| 6 | `adb shell input keyevent 6` | End Call / Hangup Event |
| 7 | `adb shell input keyevent 7` | Keycode 0 |
| 8 | `adb shell input keyevent 8` | Keycode 1 — Number 1 |
| 9 | `adb shell input keyevent 9` | Keycode 2 — Number 2 |
| 10 | `adb shell input keyevent 10` | Keycode 3 — Number 3 |
| 11 | `adb shell input keyevent 11` | Keycode 4 — Number 4 |
| 12 | `adb shell input keyevent 12` | Keycode 5 — Number 5 |
| 13 | `adb shell input keyevent 13` | Keycode 6 — Number 6 |
| 14 | `adb shell input keyevent 14` | Keycode 7 — Number 7 |
| 15 | `adb shell input keyevent 15` | Keycode 8 — Number 8 |
| 16 | `adb shell input keyevent 16` | Keycode 9 — Number 9 |
| 17 | `adb shell input keyevent 17` | STAR (\*) Key |
| 18 | `adb shell input keyevent 18` | Pound (#) Key |
- Koltin: `open class KeyEvent: InputEvent, Parcelable`
- Java: `public class KeyEvent extends InputEvent implements Parcelable`
---
## Android Data Storage
In Android, there are several ways to store data persistently.
The choice of storage mechanism depends on the nature of the data and the requirements of the app.
Below are the primary methods for data storage in Android:
**Comparison of Storage Options**
| Storage Method | Visibility | Persistence | Complexity | Best For |
| ----------------- | ---------- | ---------------------- | ----------- | ---------------------------------------- |
| SharedPreferences | Private | Until app uninstall | Low | Small key-value pairs |
| Internal Storage | Private | Until app uninstall | Low | Private files |
| External Storage | Public | Until manually deleted | Medium | Large/shared files |
| SQLite Database | Private | Until app uninstall | High | Structured data |
| Room | Private | Until app uninstall | Medium-High | Structured data with compile-time safety |
When choosing a storage method, consider the type of data you're storing, how much data you need to store, the required level of security, and the complexity you're willing to manage in your app.
1. SharedPreferences
SharedPreferences is a framework that allows you to save and retrieve key-value pairs of primitive data types.
**Use Cases**
- Storing user preferences.
- Saving settings or configuration data.
**Advantages:**
- Simple to use for small amounts of data
- Data persists across app restarts
**Disadvantages:**
- Not suitable for large or complex data structures
- Not encrypted by default
**Java Code Example**
```java
// Saving data to SharedPreferences
SharedPreferences sharedPref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("key_name", "value");
editor.apply();
// Retrieving data from SharedPreferences
SharedPreferences sharedPref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
String value = sharedPref.getString("key_name", "default_value");
```
2. Internal Storage
Internal Storage is used to store private data within the device's internal memory.
**Use Cases**
- Storing sensitive data.
- Files that should not be accessible to other apps.
**Advantages:**
- Data is private to the app.
- Files are removed when the app is uninstalled.
**Disadvantages:**
- Limited by device storage.
- Not easily accessible for backup.
**Java Code Example**
```java
// Writing to internal storage
String filename = "myfile";
String fileContents = "Hello, World!";
FileOutputStream fos = openFileOutput(filename, Context.MODE_PRIVATE);
fos.write(fileContents.getBytes());
fos.close();
// Reading from internal storage
FileInputStream fis = openFileInput(filename);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
String fileContents = sb.toString();
fis.close();
```
3. External Storage
External Storage is used to store public data on the shared external storage.
It's typically used for storing larger files.
**Use Cases**
- Storing media files (images, videos, audio)
- Documents that need to be shared with other apps.
**Advantages:**
- Larger storage capacity
- Files can be shared with other apps
**Disadvantages:**
- Not secure, as other apps can access the files
- Files may remain after app uninstallation
**Permissions**
```xml
```
**Java Code Example**
```java
// Writing to external storage
String filename = "myfile";
String fileContents = "Hello, World!";
File file = new File(getExternalFilesDir(null), filename);
FileOutputStream fos = new FileOutputStream(file);
fos.write(fileContents.getBytes());
fos.close();
// Reading from external storage
File file = new File(getExternalFilesDir(null), filename);
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
String fileContents = sb.toString();
fis.close();
```
4. SQLite Database
SQLite is a lightweight relational database embedded within Android.
**Use Cases**
- Structured data storage.
- Complex querying requirements.
- Managing complex data relationships
**Advantages:**
- Efficient for complex queries and large datasets
- Supports transactions and data integrity
**Disadvantages:**
- More complex to set up and use compared to other options
- Overkill for simple data storage needs
**Java Code Example**
```java
// Creating a database helper
public class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "mydatabase.db";
private static final int DATABASE_VERSION = 1;
public MyDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE mytable (id INTEGER PRIMARY KEY, name TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS mytable");
onCreate(db);
}
}
// Using the database helper
MyDatabaseHelper dbHelper = new MyDatabaseHelper(context);
SQLiteDatabase db = dbHelper.getWritableDatabase();
// Inserting data
ContentValues values = new ContentValues();
values.put("name", "John Doe");
long newRowId = db.insert("mytable", null, values);
// Querying data
Cursor cursor = db.query("mytable", new String[]{"id", "name"}, null, null, null, null, null);
while (cursor.moveToNext()) {
long itemId = cursor.getLong(cursor.getColumnIndexOrThrow("id"));
String itemName = cursor.getString(cursor.getColumnIndexOrThrow("name"));
}
cursor.close();
db.close();
```
5. Room Database
Room is an abstraction layer over SQLite that provides a more robust database access while harnessing the full power of SQLite.
**Use Cases:**
- When you need a robust database solution but want to avoid the complexity of raw SQLite
**Advantages:**
- Compile-time verification of SQL queries
- Convenient annotations to define database structure
- Easy integration with other Architecture components
**Disadvantages:**
- Adds additional dependencies to your project
- May be overkill for very simple data storage needs
**Java Code Example**
```java
// Define Entity
@Entity(tableName = "user")
public class User {
@PrimaryKey
public int id;
public String name;
}
// Define DAO
@Dao
public interface UserDao {
@Insert
void insert(User user);
@Query("SELECT * FROM user WHERE id = :id")
User getUserById(int id);
}
// Define Database
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
// Using Room
AppDatabase db = Room.databaseBuilder(getApplicationContext(),
AppDatabase.class, "mydatabase").build();
UserDao userDao = db.userDao();
// Inserting data
User user = new User();
user.id = 1;
user.name = "John Doe";
userDao.insert(user);
// Querying data
User user = userDao.getUserById(1);
```
6. Content Providers
Content Providers manage access to a structured set of data. They encapsulate the data and provide mechanisms for defining data security.
**Use Cases**
- Sharing data between different applications.
- Accessing data from other applications.
**Java Code Example**
```java
// Querying a content provider
Cursor cursor = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI,
null,
null,
null,
null);
while (cursor.moveToNext()) {
String id = cursor.getString(
cursor.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(
cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
cursor.close();
```
---
## React Native
This part of the guide goes into the specific parts of React Native and Android, we do try to keep all our react native notes into one area.
We recommend going to the React Native section as well, but there might be double notes in this section.
## FAQ
**What is ADB (Android Debug Bridge)?**
ADB is a command-line tool that lets a computer control an Android device over USB or Wi-Fi. It is used to install and uninstall apps, push and pull files, read device logs with `logcat`, open a device shell, and debug applications during development.
**How do I connect a device with ADB?**
Enable Developer Options and USB debugging on the device, connect it over USB, and run `adb devices` to confirm it is listed. Some commands need root access, and certain Android versions may require slightly different command syntax.
**What languages are used for Android development?**
Native Android apps are written in Kotlin (now preferred) or Java against the Android SDK. Cross-platform options include React Native and [Flutter](/application/flutter/). KBVE's Android apps use React Native with Expo, with native modules added when a feature needs platform-specific code.
**Is Android open source?**
Yes. Android is built on the open-source Android Open Source Project (AOSP) on top of a modified Linux kernel. Vendors customize drivers and UI layers on top, while Project Treble and mainline modules allow more consistent updates and faster security patches.
**What is Android used for beyond phones?**
Android extends well past phones and tablets into specialized distributions — Android TV for televisions, Android Auto for vehicles, and Wear OS for smartwatches — plus growing use in embedded, desktop, and server-adjacent devices thanks to its modular architecture.
---
# Ansible
> DevOps software that handles the infrastructure of the backend through automation.
Ansible's main function(s) operate through a "playbook" system that exectues a collection of commands for the system admin, which becomes a pillar within the IaaC environment.
Source: https://kbve.com/application/ansible/
import {
Aside,
Steps,
Card,
CardGrid,
Code,
FileTree,
Tabs,
TabItem,
} from '@astrojs/starlight/components';
import { Giscus, Adsense } from '@/components/astropad';
## Information
With **Ansible**, you can automate complex IT operations with clarity and control.
It simplifies system management, application deployment, and workflow orchestration through powerful, modular building blocks.
Powered by open source, Python, and SSH, Ansible connects seamlessly to your devices—no agents required.
It sends lightweight programs called **modules** to perform tasks precisely where they are needed, then removes them once finished.
From provisioning servers to configuring networks and deploying applications, Ansible turns manual, error-prone processes into consistent, repeatable automation.
Jump to [install](#install), [playbooks](#playbook), [modules](#modules), [AWX](#awx), or the [cheatsheet](#cheatsheet).
### Ansible for a Newbie!
Ansible is a tool that helps people do things with computers.
Sometimes people have many computers and they want to do the same thing on all of them.
For example, they might want to make them play a game, or show a picture, or talk to each other.
Doing the same thing on many computers can be hard and boring.
Ansible makes it easy and fun and has a list of things that people want to do with computers.
It can read the list and do the things one by one and then also check if the things are done correctly.
Ansible can talk to different kinds of computers and tell them what to do.
Think of Ansible like a friend that helps people with computers.
## Install
To install **Ansible**, you will need two types of machines:
a **control node** (where Ansible runs) and one or more **managed nodes** (where Ansible performs tasks).
1. **Set up your Control and Managed Nodes**
The **control node** is where you run Ansible commands and playbooks.
It can be any UNIX-like system with **Python 3.9+** installed.
The **managed node** is any system that supports **Python 2.7+** and communicates via **SSH** (or PowerShell on Windows).
2. **Install Ansible**
Depending on your operating system, there are multiple installation paths:
- **Ubuntu / Debian:** Use `apt install ansible` from the official repositories.
- **Windows:** Enable **Windows Subsystem for Linux (WSL)** and install Ansible using `pip install ansible` or `pip3 install ansible`.
- **Source:** Clone the [Ansible GitHub repository](https://github.com/ansible/ansible) and build from source to get the latest development version.
3. **Configure Ansible**
Set up your **inventory file** to list managed nodes and their connection details.
You can further customize settings in the `ansible.cfg` file or override them using environment variables or command-line options.
4. **Verify the Installation**
Run a quick test to ensure Ansible is configured properly:
```bash
ansible all -m ping
```
If everything is set up correctly, you will receive a pong response from your managed nodes.
---
## Playbook
An Ansible playbook is your automation blueprint written in YAML/JSON.
The purpose of the playbook is to tell Ansible what to do, where to do it, and how to do it.
With a playbook, you can transform your IT tasks into simple and repeatable steps that run on any number of hosts.
Whether you need to install software, configure settings, run commands, or anything else, an Ansible playbook will make it happen in a snap.
### Playbook Examples
Let me dazzle you with an example of a playbook that I borrowed from the Ansible documentation.
```yaml
- name: Update web servers
hosts: webservers
remote_user: root
tasks:
- name: Ensure apache is at the latest version
ansible.builtin.yum:
name: httpd
state: latest
- name: Write the apache config file
ansible.builtin.template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
- name: Update db servers
hosts: databases
remote_user: root
tasks:
- name: Ensure postgresql is at the latest version
ansible.builtin.yum:
name: postgresql
state: latest
- name: Ensure that postgresql is started
ansible.builtin.service:
name: postgresql
state: started
```
This playbook has two plays.
The first one updates the web servers by installing the latest version of apache and writing a config file.
The second one updates the database servers by installing the latest version of postgresql and starting the service.
Each play has a name, a list of hosts to target, a remote user to execute the tasks, and a list of tasks to perform.
Each task has a name and a module to call with some parameters.
#### Minecraft Server Update Playbook Example
```yaml
- name: Update Minecraft server
hosts: minecraft
vars:
minecraft_version: latest
minecraft_url: https://s3.amazonaws.com/Minecraft.Download/versions
minecraft_home: /srv/minecraft
tasks:
- name: Get latest Minecraft version
uri:
url: '{{ minecraft_url }}/latest.json'
return_content: yes
register: latest_version
when: minecraft_version == "latest"
- name: Set Minecraft version
set_fact:
minecraft_version: '{{ latest_version.json.id }}'
when: minecraft_version == "latest"
- name: Check if Minecraft server jar exists
stat:
path: '{{ minecraft_home }}/minecraft_server.{{ minecraft_version }}.jar'
register: jar_file
- name: Download Minecraft server jar
get_url:
url: '{{ minecraft_url }}/{{ minecraft_version }}/minecraft_server.{{ minecraft_version }}.jar'
dest: '{{ minecraft_home }}'
when: not jar_file.stat.exists
- name: Restart Minecraft service
systemd:
name: minecraft
state: restarted
when: not jar_file.stat.exists
```
This playbook is composed of four parts:
- The name of the playbook, which is `Update Minecraft server`.
- The hosts that the playbook will run on, which are the ones in the `minecraft` group in the inventory file.
- The variables that the playbook will use, such as `minecraft_version`, `minecraft_url`, and `minecraft_home`.
- The tasks that the playbook will execute, such as getting the latest Minecraft version, downloading the server jar file, and restarting the Minecraft service.
Each task has a name, a module to use, and some parameters for the module.
Some tasks also have a condition (`when`) that determines when they will run.
For example, the task `Download Minecraft server jar` will only run if the jar file does not exist in the `minecraft_home` directory.
The playbook uses the `register` keyword to store the output of some tasks in variables, such as `latest_version` and `jar_file`.
These variables can be used in later tasks or conditions and this playbook could be expanded to include file checks with hashing.
---
## Modules
Cloud modules can be used to interact with different cloud providers, such as AWS, Azure, Google Cloud, etc.
The cloud modules within Ansible are a set of modules that can be used to interact with different cloud providers and services.
They allow you to provision, configure and manage cloud resources, such as virtual machines, networks, storage, databases, etc.
---
### CI/CD Modules
The CI/CD modules enable you to run Ansible playbooks directly within automated pipelines.
They are useful for testing, provisioning, or deploying infrastructure and applications as part of your workflow.
| Module / Action | Description |
| :-------------------------------- | :---------------------------------------------------------------- |
| `ansible/ansible-lint-action` | Runs `ansible-lint` to validate playbooks and roles. |
| `ansible/ansible-playbook-action` | Executes an Ansible playbook inside your GitHub Actions workflow. |
| `ansible/galaxy-action` | Manages Ansible Galaxy roles and collections in your pipeline. |
#### FileTree
Here is a full featured layout with Talos OS, core addons, git ops, data plane.
- .github/
- actions/
- setup-ansible/ # optional composite action (cache, galaxy install)
- workflows/
- check.yml # lint (ansible-lint), yamllint, jsonschema, markdown
- test.yml # molecule with k3d/kind; idempotence checks
- deploy.yml # on tag or manual dispatch → staged rollout
- .env.example # sample env for CI (secrets injected via repo/env)
- .gitignore
- ansible.cfg
- requirements.yml # collections: kubernetes.core, community.general, community.kubernetes
- requirements-roles.yml
- inventories/
- production/
- hosts.yml
- group_vars/
- all.yml
- gitops.yml # argo root app repo/branch/path
- storage.yml # default sc, longhorn, nfs, cnpg
- observability.yml # loki, prom, grafana toggles
- networking.yml # cni options, lb, svc CIDRs (reference-only if Talos-managed)
- staging/
- hosts.yml
- group_vars/
- all.yml
- group_vars/
- all.yml # cluster_name, domain, issuer, registry creds (non-secret)
- host_vars/
- cp-01.yml
- worker-01.yml
- collections/ # (optional, if vendored)
- roles/
- talos_bootstrap/
- tasks/
- main.yml # talosctl gen secrets/apply, kubeconfig export
- kubernetes_cluster/
- tasks/
- main.yml # kube-api reachability, ns, rbac, psp replacement, quotas
- helm_release/
- tasks/
- main.yml
- cert_manager/
- tasks/
- main.yml # ClusterIssuer (LE DNS/HTTP), CRDs, health checks
- ingress_nginx/
- tasks/
- main.yml # controller, TCP services, proxy settings
- argocd/
- tasks/
- main.yml # install, admin secret mgmt (sealed-secrets optional)
- sealed_secrets/
- tasks/
- main.yml
- longhorn/
- tasks/
- main.yml
- cnpg/
- tasks/
- main.yml # CloudNativePG operator
- clickhouse_operator/
- tasks/
- main.yml
- apps_catalog/
- tasks/
- main.yml # app-of-apps: ergo-irc, restreamer, etc.
- playbooks/
- 00-bootstrap.yml # includes: talos_bootstrap (optional if you do Talos externally)
- 10-cluster.yml # includes: kubernetes_cluster
- 20-core.yml # includes: cert_manager, ingress_nginx, sealed_secrets
- 30-gitops.yml # includes: argocd (+ root apps)
- 40-storage.yml # includes: longhorn, cnpg, clickhouse_operator
- 99-apps.yml # includes: apps_catalog (ergo, restreamer, etc.)
- vars/
- issuers.yml
- registries.yml
- domains.yml
- storage.yml
- files/
- kubeconfig.sample # for local dev (never commit real kubeconfigs)
- manifests/
- argocd/
- root-app.yaml # optional if you don't bootstrap via Helm
- templates/
- argocd-values.yaml.j2
- cert-manager-values.yaml.j2
- ingress-nginx-values.yaml.j2
- molecule/
- k3d-default/
- converge.yml
- verify.yml
- molecule.yml
- docs/
- ADR-0001-ci-approach.md
- ADR-0002-gitops-structure.md
- README.md
- Talos handles OS + kubelet; Ansible focuses on cluster add-ons (Helm + Kubernetes modules) and GitOps bootstrap.
- CI stages are there for a quick check, test and deploy.
---
### AWS Modules
Ansible provides a wide range of **AWS modules** that let you automate tasks across Amazon Web Services, from launching EC2 instances to managing S3 buckets, security groups, and CloudFormation stacks.
These modules use the AWS SDK for Python (boto3) under the hood, allowing secure, API-based interaction with your cloud resources.
You can use them to playbooks to **create, configure, and delete** infrastructure components, making it easy to manage everything as code aka `IaaC`.
| Module | Description |
| :------------------------------ | :----------------------------------------------------- |
| `amazon.aws.ec2_instance` | Create and manage EC2 instances. |
| `amazon.aws.s3_bucket` | Create, delete, and configure S3 buckets. |
| `amazon.aws.cloudformation` | Deploy infrastructure stacks using AWS CloudFormation. |
| `amazon.aws.iam_user` | Manage IAM users and access permissions. |
| `amazon.aws.ec2_security_group` | Define and modify EC2 security groups. |
---
### Azure Modules
With these modules, you have full control over your Microsoft Azure resources, whether they are VMs, Storage, Network or anything else.
For example, you can use the `azure_rm_virtualmachine` module to create and manage Azure virtual machines.
---
### GCP Modules
You can work with any Google Cloud Platform service with these modules, such as Compute Engine, Storage, Network and more.
The `gcp_compute_instance` module is an example of how you can achieve your goals with GCP servers using Ansible.
> [Official Documentation on GCP Compute Instance module](https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_compute_instance_module.html)
#### Create GCP Instance
Creating a compute instance with a specific name, zone, machine type, image and network:
```yaml
- name: create gcp instance
google.cloud.gcp_compute_instance:
name: test_object
zone: us-central1-a
machine_type: n1-standard-1
disks:
- auto_delete: true
boot: true
source: '{{ disk }}'
network_interfaces:
- network: '{{ network }}'
access_configs:
- name: External NAT
nat_ip: '{{ address }}'
type: ONE_TO_ONE_NAT
state: present
```
This example creates a compute instance with a specific name, zone, machine type, image and network.
It uses the `state: present` parameter to indicate that the instance should exist.
It also specifies the `disks` and `network_interfaces` parameters to configure the disk and network settings of the instance.
The `disk` and `network` variables are assumed to be defined elsewhere in the playbook or inventory.
#### Delete GCP Instance
Deleting a compute instance with a specific name and zone:
```yaml
- name: dlete gcp instance
google.cloud.gcp_compute_instance:
name: test_object
zone: us-central1-a
state: absent
```
For this task, it deletes a compute instance with a specific `name` and `zone`.
It uses the `state: absent` parameter to indicate that the instance should not exist.
It does not need to specify any other parameters, as the `name` and `zone` are enough to identify the instance to delete.
#### Update GCP Instance
Updating a compute instance with a new machine type and labels
```yaml
- name: update gcp instance
google.cloud.gcp_compute_instance:
name: test_object
zone: us-central1-a
machine_type: n1-standard-2
labels:
env: prod
webserver: nginx
state: present
```
The update example performs the task of updating a compute instance with a new machine type and labels.
It uses the `state: present` parameter to indicate that the instance should exist.
It also specifies the `machine_type` and `labels` parameters to change the machine type and labels of the instance.
The machine type determines the CPU and memory resources of the instance, and the labels are key-value pairs that can be used to organize and filter instances.
Any other parameters that are not specified will remain unchanged.
---
### OpenStack Modules
OpenStack modules can be used to work with OpenStack, an open source cloud platform that provides infrastructure as a service (IaaS).
The `os_server` module is an example of how you can have full control over your OpenStack servers.
---
### Network Modules
You can configure and manage any network device with these modules, such as routers, switches, firewalls and beyond.
---
### System Modules
With these modules, you have full control over your system resources, whether they are users, groups, files, directories, services, packages or anything else.
---
### Database Modules
Employing these modules, you have full control over your database servers and objects, from MySQL and PostgreSQL to MongoDB and more.
---
### Windows Modules
Windows modules can be used to manage Windows systems and applications, such as Active Directory, IIS, PowerShell, etc.
For example, you can use the `win_service` module to manage Windows service
---
## AWX
> tldr; AWX is a web-base RESTFul API and task engine that operates on top of Ansible, thus enabling you to automate certain aspects of the IT/DevOps.
AWX is an open source project that gives you a sleek and modern web-based user interface, a powerful and flexible REST API, and a robust and scalable task engine to work with Ansible.
It is the upstream project of Red Hat Ansible Automation Platform, which is a premium solution that offers additional features and support for enterprise customers.
With AWX, you can easily manage your Ansible playbooks, inventories, credentials, and vaults in a collaborative and secure way among your team members.
Moreover, AWX empowers you to plan and run your Ansible playbooks on your managed nodes with speed, efficiency and dependability; you can set up custom schedules, workflows, notifications, and callbacks to automate your Ansible operations and monitor their outcomes.
In conclusion, AWX gives you full control and visibility over your Ansible playbooks and their execution.
### AWX Repo
> The official [Repository](https://github.com/ansible/awx) for AWX - Ansible.
The AWX repository is a GitHub repository that contains a treasure trove of source code and other resources.
### AWX Terraform
> More information on [Terraform](/application/terraform/)
Terraform AWX Provider from Denouche.
By using AWX and Terraform together, you can leverage the power and flexibility of Ansible to manage your AWS resources with ease and efficiency.
The Two tools that can be used together to automate IT infrastructure.
- Official [Registry](https://registry.terraform.io/providers/denouche/awx/latest/docs) Link:
Example Usage - With Username/Password:
```ini
provider "awx" {
hostname = "http://localhost:8078"
username = "kbvetest"
password = "changemepassword"
}
```
Example Usage - With Token:
```ini
provider "awx" {
hostname = "http://localhost:8078"
token = "awxtoken"
}
```
> Remember that if you set both (username/password) and (token), then the (token) will have precedence.
## Cheatsheet
> tldr; Commands that will make it easier operate ansible scripts / playbooks. This cheatsheet is still a work-in-progress.
An Ansible cheatsheet is a quick and handy reference guide that provides examples and tips on how to use Ansible command line tools and playbooks, thus enabling you to unleash the power of Ansible!
With an Ansible cheatsheet at your fingertips, you can breeze through a variety of tasks that would otherwise be tedious and time-consuming.
Whether you need to test the connectivity to your nodes, switch to a different user, use a custom SSH key, use password-based authentication, run ad-hoc commands, create and run playbooks, use modules and roles, or anything else, an Ansible cheatsheet will make your life easier and more fun.
## Videos
Video -> https://www.youtube.com/watch?v=EcnqJbxBcM0
## Notes
Notes for Ansible
## FAQ
**What is Ansible?**
Ansible is an open-source IT automation tool for configuration management, application deployment, and orchestration. It is agentless — it connects to hosts over SSH and pushes small programs called modules to do work, then removes them — so managed machines need no special software beyond Python and SSH.
**What is an Ansible playbook?**
A playbook is a YAML file that describes a set of plays, each mapping a group of hosts to an ordered list of tasks. Playbooks are declarative and idempotent — running one repeatedly converges hosts to the same desired state without repeating changes that are already applied.
**Why is Ansible agentless?**
Ansible does not install a daemon on managed nodes. It uses existing SSH access and Python to run modules on demand, which lowers setup overhead, reduces attack surface, and means any reachable host can be managed without provisioning an agent first.
**What is an Ansible module?**
A module is a self-contained unit of work — like `apt`, `copy`, `service`, or `template` — that Ansible ships to a host to perform one task idempotently. Tasks in a playbook call modules with parameters, and Ansible reports whether each run changed the system.
**What is AWX?**
AWX is the open-source upstream of Ansible Tower (Red Hat Ansible Automation Platform). It adds a web UI, REST API, role-based access control, job scheduling, and centralized credential management on top of core Ansible for team-scale automation.
---
# Appwrite
> Appwrite is an open-source backend server that provides developers with core APIs to build applications. It is self-hosted and can run on any operating system. Appwrite aims to simplify backend development for developers.
Source: https://kbve.com/application/appwrite/
import {
Aside,
Steps,
Card,
CardGrid,
Code,
FileTree,
} from '@astrojs/starlight/components';
import { Giscus, Adsense } from '@/components/astropad';
## Overview
**Appwrite** is an open-source, self-hosted **backend server** (Backend-as-a-Service) that hands developers a ready-made set of core APIs — **auth, databases, storage, messaging, and serverless functions** — behind a clean management console. It runs on any OS via Docker, so you skip building common backend plumbing yourself.
This guide covers [Cloud Functions](#javascript) (Init/Core/Extra) and the [Python SDK](#python).
## Information
Appwrite is a cutting-edge backend server that streamlines the development of modern apps.
With its powerful APIs, intuitive tools, and sleek management console UI, Appwrite empowers developers to build their apps with speed and security.
Say goodbye to the headaches of common, complex, and repetitive tasks - Appwrite has got you covered.
Get ready to revolutionize your app development process with Appwrite!
## Javascript
More information for [javascript](/application/javascript)
This part of the documentation is no longer valid for Appwrite 1.4+, as they have changed their functions.
We split the functions into three different areas:
1. `Init` - Which initializes the serverless function, handling the installs if using different libaries, ect...
2. `Core` - These are the notes for the core serverless function.
3. `Extra` - Additional notes and information regarding the expansion of a serverless function.
### Init
Hello there, fellow developers! 🚀
Today, we're diving deep into the world of cloud functions with a special focus on Appwrite - a wonderful platform that allows you to build secure web and mobile applications faster.
### What is a Cloud Function?
At its core, a cloud function is a piece of code that runs in response to an event.
You don’t need to manage the infrastructure; the cloud provider does that for you.
Think of it as "Function as a Service" (FaaS).
Cloud functions are a key part of the serverless architecture, allowing developers to focus on writing code without worrying about the underlying infrastructure.
### Initializing Your Appwrite Cloud Function
1. `Function Creation` :
- Head over to your Appwrite Console, navigate to the Functions section, and click on `Add Function`.
- Give your function a name and choose a runtime (e.g., Node.js, Python, Deno, etc.).
2. `Code Your Function` :
- Reference Core for the basics.
- Here is a basic / starter.
```javascript
module.exports = async (req, res) => {
const payload =
req.payload ||
'No payload provided. Add custom data when executing function.';
const secretKey =
req.variables.SECRET_KEY ||
'SECRET_KEY variable not found. You can set it in Function settings.';
const randomNumber = Math.random();
const trigger = req.variables.APPWRITE_FUNCTION_TRIGGER;
res.json({
message: 'Hello from Appwrite!',
payload,
secretKey,
randomNumber,
trigger,
});
};
```
3. `Packaging` :
- Cloud functions in Appwrite run inside Docker containers, so your function and any dependencies need to be packed into a tarball. For Node.js:
`tar -czf code.tar.gz --exclude code.tar.gz .`
4. `Deployment` :
- Upload Your Code: Back in the Appwrite Console, under your function, click on the Deploy Tag button.
- Upload the code.tar.gz file.
- Set Your Triggers! Functions can respond to various events, like user registration or document creation. Select the triggers relevant to your use case.
- Execute! With everything set, hit the Execute button. Your function will run, and you can see the logs in real-time.
Yay! Congratulations, you’ve just deployed your first Appwrite Cloud Function! 🎉
The power of serverless lies in its simplicity and scalability.
As your application grows, you can continue adding more functions without the hassle of managing servers or infrastructure.
I hope this introduction helps kickstart your journey with Appwrite Cloud Functions.
Stay tuned for more in-depth tutorials, and happy coding! 🚀
### Core
General documentation and information in reference to the cloud functions / open runtime for Appwrite.
Remember to import the SDK outside of the module function.
The main `module.exports` is usually written like this
```javascript
module.exports = async function (req, res) {}; // Passing req and res
```
The `req` contains these three main objects:
`req.headers` - An object with the request headers for the function.
`req.payload` - An object with the payload, which is the main body data.
`req.env` - An object with the environment data.
The `res` can return two main objects:
`res.send` - returns a `text` and `statusCode`.
`res.json` - returns an `object` and `statusCode`.
Example of parsing the `req.payload` check and `res.json` return.
```javascript
if (req.payload) {
try {
payload = JSON.parse(req.payload);
} catch (error) {
errorHandler('Corrupt payload for the function.');
}
} else {
errorHandler('Missing payload for the function.');
}
```
In this case our `errorHandler` function would be:
```javascript
const errorHandler = (__errorMessage, statusCode = 418) => {
res.json({ data: 'error', message: __errorMessage }, statusCode);
};
```
### Extra
In the context of Appwrite Cloud Functions, "extra libraries" refer to external dependencies or packages that your function might need to execute correctly.
Due to the isolated nature of cloud functions, they don't inherently have access to all the libraries or tools available in a full-fledged server environment.
To overcome this, Appwrite allows you to bundle these additional libraries with your function code.
When you're developing your function, you specify and package these libraries—be it npm packages for a Node.js function, pip packages for a Python function, or any other dependencies for other runtimes.
Once bundled, Appwrite ensures that these libraries are available to your function at runtime, providing a seamless execution environment tailored to your specific needs.
- For data fetching, we recommend that you add an external module known as `axios`.
- `const axios = require("axios").default;`
---
## Python
The Appwrite Python SDK allows Python developers to interact with Appwrite's API, facilitating tasks like user authentication, database operations, storage, and more.
By using this SDK, Python developers can seamlessly integrate and manage Appwrite services in their applications, without delving into the complexities of direct API calls.
Step aside traditional backends, the Appwrite Python SDK is in town, rolling out the red carpet for Pythonistas eager to elevate their web and mobile projects!
This snazzy toolkit doesn't just connect Python applications to the Appwrite server; it's a golden ticket to a carnival of backend delights.
From the tantalizing whirlwind of user authentication to the magic show of database operations and the high-flying trapeze of storage management, the SDK transforms mundane backend tasks into a spectacle.
No more wrestling with manual API requests – just harness the SDK's sleek methods and watch as Appwrite's vast services dance harmoniously with your Python code.
Whether you're orchestrating user data or wiring up notifications, the Appwrite Python SDK keeps backend integration clean and readable.
### Appwrite Python SDK Install
Python wizards, gather 'round! Elevate your coding cauldron with a sprinkle of Appwrite magic by simply chanting `pip install appwrite`.
And just like that, your Python broomstick is turbocharged and ready to soar through the backend skies!
Calling the `appwrite` in python is really easy! Just add this below:
```python
from appwrite.client import Client
client = Client()
client = (client
.set_endpoint('https://ap.kbve.com/v1') # Your API Endpoint
.set_project('[PROJECT_ID]') # Your project ID
.set_key('919c2db5d4...a2a3346ad2') # Your secret API key
)
```
And you will be good to go!
### Appwrite Python SDK Demo
Here is a quick and easy demo for Appwrite python below!
```python
from appwrite.client import Client
from appwrite.id import ID
from appwrite.services.users import Users
client = Client()
client = (client
.set_endpoint('https://cloud.appwrite.io/v1') # Your API Endpoint
.set_project('[PROJECT_ID]') # Your project ID
.set_key('919c2db5d4...a2a3346ad2') # Your secret API key
)
users = Users(client)
user = users.create(
user_id=ID.unique(),
email='email@example.com',
phone=None,
password='password'
)
```
## FAQ
**What is Appwrite?**
Appwrite is an open-source, self-hosted backend server (a Backend-as-a-Service) that gives developers core APIs — authentication, databases, storage, messaging, and serverless functions — plus a management console. It runs on any OS via Docker and removes the need to build common backend plumbing from scratch.
**What is an Appwrite Cloud Function?**
A Cloud Function is a piece of code that runs in response to an event (Function-as-a-Service). In Appwrite, functions run inside Docker containers, support runtimes like Node.js, Python, and Deno, and can be triggered by events such as user registration or document creation, or executed manually.
**Which SDKs does Appwrite provide?**
Appwrite ships official SDKs for many platforms including JavaScript/TypeScript, Python, [Flutter](/application/flutter/)/Dart, Android, Apple, and more. Each SDK wraps the REST API so you configure a `Client` with an endpoint, project ID, and key, then call typed service methods instead of raw HTTP.
**Is Appwrite self-hosted or cloud?**
Both. Appwrite is open source and can be self-hosted on your own infrastructure with Docker, and there is also Appwrite Cloud, a managed offering. Self-hosting gives you full data control; the cloud removes operational overhead.
**How do I connect the Appwrite Python SDK?**
Install it with `pip install appwrite`, then create a `Client` and chain `set_endpoint`, `set_project`, and `set_key`. From there you instantiate services like `Users` or `Databases` with that client and call their methods.
---
# ArgoCD
> ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes that syncs the desired state in Git
with the live cluster. This guide covers the architecture, CLI, sync policies, the KBVE annotation standard,
and troubleshooting.
Source: https://kbve.com/application/argocd/
import {
Aside,
Steps,
Card,
CardGrid,
Code,
FileTree,
Tabs,
TabItem,
} from '@astrojs/starlight/components';
import { Giscus, Adsense } from '@/components/astropad';
## Information
ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes. It automates the deployment of applications by synchronizing the desired state defined in Git repositories with the actual state in Kubernetes clusters.
Jump to the [architecture](#architecture), [CLI commands](#cli-commands), [sync policies](#application-management), or [troubleshooting](#troubleshooting).
## Architecture
ArgoCD follows the GitOps pattern where Git repositories are the source of truth for defining the desired application state. Key components include:
Continuously monitors running applications and compares the current live state against the desired target state specified in Git.
Internal service that maintains a local cache of Git repositories holding application manifests.
gRPC/REST server that exposes the API consumed by the Web UI, CLI, and CI/CD systems.
Kubernetes custom resources (CRDs) that define applications, projects, and repositories.
---
## KBVE Cluster Integration
The KBVE production cluster runs ArgoCD to manage 68+ applications across multiple namespaces. All application manifests are stored in the [`apps/kube/`](https://github.com/kbve/kbve/tree/main/apps/kube) directory.
### Dashboard Access
View live deployment status: [ArgoCD Dashboard](/dashboard/argo/)
---
## Application Annotation Standard
### Overview
KBVE uses a standardized annotation schema on ArgoCD Application resources to link them back to their source directories in `apps/kube`. These annotations provide zero-risk metadata that enables traceability, automation, and better observability.
### Schema Version: v1
#### Core Annotations (Required)
These annotations MUST be present on every ArgoCD Application resource:
| Annotation | Description | Example |
|------------|-------------|---------|
| `kbve.com/source-path` | Relative path from repo root to the application directory | `apps/kube/agones/arpg` |
| `kbve.com/manifest-path` | Relative path to the actual Kubernetes manifest directory | `apps/kube/agones/arpg/manifests` |
| `kbve.com/application-file` | Relative path to this ArgoCD Application resource file | `apps/kube/agones/arpg/application.yaml` |
| `kbve.com/managed-by` | Management tool (always `argocd` for these resources) | `argocd` |
| `kbve.com/schema-version` | Version of this annotation schema | `v1` |
#### Classification Annotations (Recommended)
These annotations SHOULD be present to enable categorization and filtering:
| Annotation | Description | Example Values |
|------------|-------------|----------------|
| `kbve.com/category` | Application category | `game-server`, `application`, `infrastructure`, `database`, `observability`, `ci-cd`, `networking` |
| `kbve.com/stack` | Technology stack or framework | `agones`, `rows`, `supabase`, `clickhouse`, `cilium`, `core` |
#### Optional Annotations
Additional context-specific annotations:
| Annotation | Description | When to Use | Example |
|------------|-------------|-------------|---------|
| `kbve.com/tenant` | Tenant identifier | Multi-tenant deployments | `chuckrpg-beta`, `rentearth-release` |
| `kbve.com/deployment-model` | Deployment architecture pattern | Complex deployments | `multi-tenant-overlay`, `singleton`, `replicated` |
| `kbve.com/environment` | Environment stage | When explicit environment tracking needed | `dev`, `staging`, `prod` |
| `kbve.com/owner` | Team or individual responsible | Large teams with ownership boundaries | `platform-team`, `game-dev` |
### Examples
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kbve
namespace: argocd
annotations:
kbve.com/source-path: "apps/kube/kbve"
kbve.com/manifest-path: "apps/kube/kbve/manifest"
kbve.com/application-file: "apps/kube/kbve/application.yaml"
kbve.com/managed-by: "argocd"
kbve.com/schema-version: "v1"
kbve.com/category: "application"
kbve.com/stack: "core"
spec:
project: default
source:
repoURL: https://github.com/KBVE/kbve
targetRevision: HEAD
path: apps/kube/kbve/manifest
destination:
server: https://kubernetes.default.svc
namespace: kbve
```
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: agones-arpg
namespace: argocd
labels:
app.kubernetes.io/part-of: arpg
annotations:
kbve.com/source-path: "apps/kube/agones/arpg"
kbve.com/manifest-path: "apps/kube/agones/arpg/manifests"
kbve.com/application-file: "apps/kube/agones/arpg/application.yaml"
kbve.com/managed-by: "argocd"
kbve.com/schema-version: "v1"
kbve.com/category: "game-server"
kbve.com/stack: "agones"
spec:
project: default
source:
repoURL: https://github.com/kbve/kbve
targetRevision: main
path: apps/kube/agones/arpg/manifests
destination:
server: https://kubernetes.default.svc
namespace: arpg
```
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: rows-chuckrpg-beta
namespace: argocd
annotations:
kbve.com/source-path: "apps/kube/rows/tenants/overlays/chuckrpg-beta"
kbve.com/manifest-path: "apps/kube/rows/tenants/overlays/chuckrpg-beta"
kbve.com/application-file: "apps/kube/rows/tenants/overlays/chuckrpg-beta/application.yaml"
kbve.com/managed-by: "argocd"
kbve.com/schema-version: "v1"
kbve.com/category: "game-server"
kbve.com/stack: "rows"
kbve.com/tenant: "chuckrpg-beta"
kbve.com/deployment-model: "multi-tenant-overlay"
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/KBVE/kbve
targetRevision: main
path: apps/kube/rows/tenants/overlays/chuckrpg-beta
destination:
server: https://kubernetes.default.svc
namespace: rows-chuckrpg-beta
```
### Category Reference
| Category | Description | Example Apps |
|----------|-------------|--------------|
| `game-server` | Game server deployments | arpg, cryptothrone, factorio, mc |
| `application` | Core business applications | kbve, herbmail, n8n, jobboard |
| `infrastructure` | Infrastructure components | argocd, cert-manager, reloader, gateway-api |
| `database` | Database systems | cnpg, clickhouse, valkey, rabbitmq |
| `observability` | Monitoring and logging | monitoring, metrics, vector, analytics |
| `ci-cd` | CI/CD tools and runners | github/runners, github/controller, forgejo |
| `networking` | Network infrastructure | cilium, kong, multus |
| `virtualization` | Virtualization platforms | kubevirt, kasm, firecracker |
| `operator` | Kubernetes operators | agones, clickhouse-operator, kyverno, keda |
| `security` | Security tooling | sealed-secrets, external-secrets, security-profiles-operator |
### Querying Applications
These annotations enable powerful kubectl queries:
```bash
# List all game servers
kubectl get applications -n argocd -o json | \
jq '.items[] | select(.metadata.annotations."kbve.com/category" == "game-server") | .metadata.name'
# Find all ROWS tenants
kubectl get applications -n argocd -o json | \
jq '.items[] | select(.metadata.annotations."kbve.com/stack" == "rows") |
{name: .metadata.name, tenant: .metadata.annotations."kbve.com/tenant"}'
# Get source paths for all applications
kubectl get applications -n argocd -o json | \
jq '.items[] | {name: .metadata.name, path: .metadata.annotations."kbve.com/source-path"}'
```
---
## Talos Integration
### Pause ArgoCD During Upgrades
When performing Talos node upgrades, pause ArgoCD reconciliation to prevent it from fighting manual scale-down operations:
```shell
# Pause ArgoCD application controller
kubectl -n argocd scale sts argocd-application-controller --replicas=0
# After upgrade completes, restore
kubectl -n argocd scale sts argocd-application-controller --replicas=1
```
This prevents the application-controller from interfering with:
- Pre-upgrade workload scale-down
- Longhorn maintenance mode preparation
- Manual pod eviction for graceful drain
See the full Talos upgrade procedure in [Kubernetes - Talos](/application/kubernetes/#talos).
---
## CLI Commands
### Installation
```shell
brew install argocd
```
```shell
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64
```
### Login
```shell
# Port-forward ArgoCD server
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Login via CLI
argocd login localhost:8080
```
### Common Commands
```shell
# List all applications
argocd app list
# Get application details
argocd app get
# Sync an application
argocd app sync
# Get sync status
argocd app sync-status
# View application logs
argocd app logs
# Delete an application
argocd app delete
# Create an application from YAML
argocd app create -f application.yaml
```
---
## Application Management
### Sync Policies
KBVE applications use automated sync with self-healing:
```yaml
syncPolicy:
automated:
prune: true # Delete resources removed from Git
selfHeal: true # Revert manual kubectl changes
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- RespectIgnoreDifferences=true
```
### Ignore Differences
Some resources have fields that ArgoCD should not sync (e.g., Agones Fleet replicas managed by autoscalers):
```yaml
ignoreDifferences:
- group: agones.dev
kind: Fleet
jsonPointers:
- /spec/replicas
```
### Finalizers
Multi-tenant applications use finalizers to ensure cascading deletion:
```yaml
metadata:
finalizers:
- resources-finalizer.argocd.argoproj.io
```
This ensures when an ArgoCD Application is deleted, all deployed resources are cleaned up.
---
## Troubleshooting
### Application Stuck in Progressing
```shell
# Check sync operation status
argocd app get
# Terminate stuck operation
argocd app terminate-op
# Force sync
argocd app sync --force
```
### Out of Sync Despite Matching Git
```shell
# Hard refresh (bypass cache)
argocd app get --hard-refresh
# Check diff
argocd app diff
```
### Health Check Failing
Some resources need custom health checks. ArgoCD has built-in checks for common resources, but custom CRDs may require configuration:
```yaml
# ConfigMap in argocd namespace
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
resource.customizations: |
agones.dev/Fleet:
health.lua: |
hs = {}
if obj.status ~= nil then
if obj.status.readyReplicas ~= nil and obj.status.readyReplicas > 0 then
hs.status = "Healthy"
return hs
end
end
hs.status = "Progressing"
return hs
```
### Controller Logs
```shell
# View application controller logs
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-application-controller -f
# View repo server logs
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-repo-server -f
```
---
## Best Practices
1. **Use Git as Source of Truth**
- Never manually apply manifests that are managed by ArgoCD
- All changes should go through Git commits
2. **Enable Auto-Sync with Self-Heal**
- Automatically corrects drift from manual changes
- Ensures cluster state matches Git
3. **Use Annotations for Metadata**
- Link applications back to source code
- Enable programmatic discovery and automation
4. **Implement Proper RBAC**
- Limit who can sync/delete applications in production
- Use ArgoCD Projects for multi-tenant isolation
5. **Monitor Sync Status**
- Set up alerts for applications stuck in Progressing
- Track sync failures in observability stack
6. **Use Resource Hooks**
- `PreSync`, `Sync`, `PostSync` hooks for migrations
- `SyncFail` hooks for rollback logic
---
## Related Documentation
- [Kubernetes](/application/kubernetes/) - General Kubernetes operations
- [ArgoCD Dashboard](/dashboard/argo/) - Live cluster deployment status
- [GitHub Actions](/application/git/) - CI/CD integration with ArgoCD
---
## FAQ
**What is ArgoCD?**
ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes. It treats a Git repository as the source of truth for the desired application state and continuously syncs the live cluster to match, automating deployments and detecting drift.
**What is GitOps?**
GitOps is an operational model where the desired state of infrastructure and applications is declared in Git, and an automated agent reconciles the running system to match. Git becomes the single source of truth, so every change is version-controlled, reviewable, and auditable.
**What is the difference between prune and self-heal in ArgoCD?**
`prune` deletes cluster resources that were removed from Git, keeping the cluster from accumulating orphans. `selfHeal` reverts manual `kubectl` changes back to the Git-defined state. Together they enforce that the live cluster always matches the repository.
**How do I fix an ArgoCD application stuck in Progressing?**
Check the operation with `argocd app get`, terminate a stuck sync using `argocd app terminate-op`, then force a fresh sync with `argocd app sync --force`. A hard refresh (`--hard-refresh`) bypasses the cache when an app shows out of sync despite matching Git.
**What are `ignoreDifferences` used for in ArgoCD?**
`ignoreDifferences` tells ArgoCD to skip specific resource fields when comparing live and desired state, so it does not fight controllers that own those fields — for example an autoscaler managing an Agones Fleet's `spec.replicas` would otherwise be reverted on every sync.
---
# Authelia
> Authelia is an open-source authentication and authorization server that adds two-factor authentication (2FA) and single sign-on (SSO) to your applications through a reverse proxy. It acts as a firewall-like access portal, securing services outside the scope of the application itself.
Source: https://kbve.com/application/authelia/
import {
Aside,
Steps,
Card,
CardGrid,
Code,
FileTree,
} from '@astrojs/starlight/components';
import { Giscus, Adsense } from '@/components/astropad';
## Information
Have you ever wondered how to secure your web applications with a simple, secure, and elegant solution?
Do you want to offer your users a seamless login experience across multiple domains and services?
If so, you might be interested in **Authelia**, an open-source authentication and authorization server that provides two-factor authentication (2FA) and single sign-on (SSO) for your applications via a web portal.
In this document, KBVE introduces you and your dev team to the features and benefits of Authelia, and shows you how to set it up with common reverse proxies like [Nginx](/application/nginx/), [Traefik](/application/traefik/), or HAProxy.
By the end of this reference, you will be able to protect your web applications with Authelia and enjoy a secure, hassle-free authentication process.
---
## How It Works
Authelia does not modify your applications. Instead, it plugs into your **reverse proxy** using a pattern called **forward auth** (also called external auth or `auth_request`):
1. A user requests a protected service, e.g. `https://app.kbve.com`.
2. The reverse proxy pauses and asks Authelia: *is this session authenticated and authorized?*
3. If **yes**, the proxy forwards the request to the backend as normal.
4. If **no**, the user is redirected to Authelia's login portal, completes 2FA, and is sent back — now with a valid session cookie.
Because the session cookie is scoped to your **root domain**, one login unlocks every protected subdomain — that is the single sign-on (SSO) experience.
| Concept | Meaning |
| ------- | ------- |
| **Authentication** | Proving *who* the user is (password + 2FA) |
| **Authorization** | Deciding *what* the user may access (access control rules) |
| **Forward auth** | Reverse proxy delegates the auth decision to Authelia |
| **SSO** | One authenticated session grants access across services |
## Install
There are a couple of ways to install Authelia. Here are the official deployment notes for each:
- [Docker](https://www.authelia.com/integration/deployment/docker/)
- [Kubernetes](https://www.authelia.com/integration/kubernetes/introduction/)
- [Bare Metal](https://www.authelia.com/integration/deployment/bare-metal/)
---
### Prerequisites
A decent understanding of your operating system, networking, and containerization will be extremely helpful.
One fundamental requirement: **Authelia has to operate under SSL/TLS**.
The default port that Authelia runs on is `9091`, but this can be changed.
Finally, if you have Cloudflare sitting in front of your domain, double-check your forwarded headers — Authelia provides a guide on that [here](https://www.authelia.com/integration/proxies/fowarded-headers/).
---
### Docker
This section covers deploying Authelia via Docker.
We use the DockerHub image `authelia/authelia`, but you can opt for their GitHub image as well.
Since our ecosystem uses **Traefik**, we recommend following the documentation for its [integration](https://www.authelia.com/integration/proxies/traefik/).
A minimal `docker-compose.yml` service:
```yaml
services:
authelia:
image: authelia/authelia
container_name: authelia
volumes:
- ./authelia:/config
ports:
- "9091:9091"
environment:
- TZ=America/New_York
restart: unless-stopped
```
### Traefik forwardAuth
Wire Authelia into Traefik with a `forwardAuth` middleware, then attach it to any protected router:
```yaml
labels:
- "traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.kbve.com"
- "traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email"
```
## FAQ
**What is Authelia?**
Authelia is an open-source authentication and authorization server that provides 2FA and SSO for your web applications. It sits behind a reverse proxy like Nginx or Traefik and validates every request before it reaches the protected service — like an application-layer firewall.
**How does Authelia integrate with a reverse proxy?**
It uses forward auth. The reverse proxy intercepts each request and asks Authelia whether the user is authenticated and authorized. If yes, the request passes through; if not, the user is redirected to the login portal. Nginx uses `auth_request`; Traefik uses a `forwardAuth` middleware.
**What port does Authelia run on?**
Authelia listens on port `9091` by default, but it is configurable. It must operate under SSL/TLS, so you terminate HTTPS at your reverse proxy and forward authenticated traffic to Authelia and your backend services.
**Does Authelia support single sign-on across multiple domains?**
Yes. Once a user authenticates, a session cookie scoped to your root domain grants access to every protected subdomain and service without logging in again.
**What do I need before deploying Authelia?**
A working reverse proxy (Nginx, Traefik, or HAProxy), a domain with valid SSL certificates, and a session/storage backend. If Cloudflare sits in front of your domain, verify your forwarded headers configuration.
## Videos
---
# Blender
> Blender is a powerful open-source 3D creation suite supporting the entire 3D pipeline—modeling, rigging, animation, simulation, rendering, compositing, motion tracking, and video editing.
The software provides professional-grade tools for artists, studios, and hobbyists across industries including game development, film production, architecture, and product visualization.
With Python scripting, extensive addon support, and active community development, Blender has become an industry-standard tool for 3D content creation.
Source: https://kbve.com/application/blender/
import {
Aside,
Steps,
Card,
CardGrid,
Code,
FileTree,
} from '@astrojs/starlight/components';
import { Giscus, Adsense } from '@/components/astropad';
import SpriteSheetBaker from '@/components/blender/SpriteSheetBaker.tsx';
## Information
Blender is a free and open-source 3D creation suite developed by the Blender Foundation and maintained by a global community of contributors.
First released in 1995 and open-sourced in 2002, Blender has evolved into a comprehensive platform capable of handling every stage of the 3D production pipeline.
The software runs on Windows, macOS, and Linux, supporting GPU rendering via CUDA, OptiX, HIP, Metal, and oneAPI.
Blender's architecture is built around a unified interface with multiple workspaces optimized for different tasks: modeling, sculpting, shading, animation, rendering, compositing, and video editing.
The Python API provides deep access to Blender's internals, enabling automation, custom tools, and pipeline integration.
The addon ecosystem extends Blender's capabilities with community and commercial tools for specialized workflows.
---
## Getting Started
Download Blender from [blender.org](https://www.blender.org/download/) or install via package managers:
```bash
# macOS (Homebrew)
brew install --cask blender
# Linux (Snap)
snap install blender --classic
# Linux (Flatpak)
flatpak install flathub org.blender.Blender
# Windows (winget)
winget install -e --id BlenderFoundation.Blender
```
On first launch, Blender presents the Quick Setup dialog for configuring keyboard shortcuts (Blender or Industry Compatible), theme, and interface language.
The default startup file opens with a cube, camera, and light in the 3D viewport.
---
## Isometric Sprite Sheet Baker (ARPG)
The ARPG iso renderer draws environment props and vehicles as upright screen
billboards. To turn a 3D model into a prop, we bake a 360° spin into a sprite
sheet whose frame index maps directly to a facing. The toolchain lives in the
**kbve python package** (`kbve.sprite`) and runs via `uv` console entrypoints, so it
can be invoked from anywhere in the repo; the interactive angle finder stays beside
the arpg assets.
- packages/python/kbve/kbve/sprite/
- model_sprites.py `uv run kbve-model-sprites` — Blender baker (OBJ/FBX → sheet)
- sprite_postprocess.py `uv run kbve-sprite-postprocess` — ground shadow + stitch
- skin_variant.py `uv run kbve-skin-variant` — kill a glow color → "off" skin
- ship_footprint.py `uv run kbve-ship-footprint` — bake ship collision (.ts + .rs)
- apps/agones/arpg/web/scripts/
- preview-model-sprites.html Three.js angle finder (mirrors the baker's math)
- gen-bush-sheet.py Proc bush baker (shelved — bush env parked)
Enable the toolchain (pulls Pillow + numpy, kept off the core install):
```bash
uv sync --project packages/python/kbve --extra sprite
```
**What it does** — loads a model + skin texture, lays the hull flat on the ground
plane (`--pitch`, baked into the mesh), spins it through N yaw facings under an
orthographic isometric camera, and writes one transparent PNG per facing plus a
square row-major `sheet.png` and a `strip.png`.
### Try it in the browser
The island below is the baker's zero-install twin — same yaw / elevation / lay-flat
math, rasterized straight from WebGL. Pick a model (`.obj`, `.glb`, or `.fbx`) and a
skin, dial the angle, then **Bake** to download the sheet. It also prints the matching
Blender command (for a higher-fidelity offline bake) and a ready `EnvDef` snippet.
1. **Find the angle** — serve the previewer (file URLs block local model/texture
loads) and dial yaw / camera elevation / lay-flat pitch. It prints the exact
baker command for the heading you pick.
```bash
cd apps/agones/arpg/web/scripts
python3 -m http.server 8765
# open: http://localhost:8765/preview-model-sprites.html?model=PATH.obj&skin=PATH.jpg
```
2. **Bake the sheet** — paste the copied flags. The entrypoint finds Blender and
runs it headless (set `BLENDER_BIN` to override discovery):
```bash
uv run --project packages/python/kbve kbve-model-sprites -- \
--model fighter1.obj --skin idolknight.jpg --out render_flat \
--frames 16 --res 256 --elev 35 --pitch 90 --yaw-offset 0
```
Equivalent direct form: `blender -b -P packages/python/kbve/kbve/sprite/model_sprites.py -- `.
For a single static "parked" frame: `--frames 1 --yaw-offset `.
For a **lift / spool-up animation** (engines rising off the ground), add
`--anim-frames 8 --lift 0.6`. The hull rises over the frames while a Cycles
shadow-catcher keeps the shadow on the floor, so the gap grows = a real hover.
The sheet lays out one row per facing × one column per anim frame (row-major
`dir * frames + f`), so the `EnvDef` reads it as `frames: 8, directions: 16`:
```bash
uv run --project packages/python/kbve kbve-model-sprites -- \
--model fighter1.obj --skin idolknight.jpg \
--out ship_lift --frames 16 --anim-frames 8 --lift 0.6 --res 256 \
--elev 30 --pitch 90 --yaw-offset 45 --real-shadow
```
3. **Wire the prop** — drop `sheet.png` (or a chosen `frame_NN.png`) under
`web/public/assets/...` and register an `EnvDef` in
`web/src/game/entities/env.ts`. A static prop uses `frames: 1`; a rotatable
one uses `directions: 16` and the full sheet (row-major: row = facing).
| Flag | Meaning | Default |
| --- | --- | --- |
| `--model` | source `.obj` / `.fbx` | required |
| `--skin` | texture applied to all meshes | required |
| `--out` | output dir (frames + `sheet.png` + `strip.png`) | required |
| `--frames` | yaw facings (`1` = static) | `16` |
| `--anim-frames` | animation frames PER facing (`>1` bakes an animation) | `1` |
| `--anim-mode` | `lift` (rise, once), `idle` (bob loop), `move` (fly bob+sway loop), `bank` (monotonic roll L→R for turn lean), `launch` (ascent to space, once) | `lift` |
| `--lift` | hover height as a fraction of model size (lift / idle / move / bank base) | `0.6` |
| `--bob` | vertical bob amplitude as a fraction of model size (idle/move) | `0.06` |
| `--sway` | roll amplitude in degrees (move sway / bank extent) | `8` |
| `--launch-height` | launch ascent height × model size | `5` |
| `--launch-pitch` | launch nose-up pitch deg at apex | `70` |
| `--launch-shrink` | launch final scale (fakes distance) | `0.12` |
| `--res` | px per frame (square) | `256` |
| `--elev` | camera elevation deg (`35` = 2:1 iso) | `35` |
| `--pitch` | lay-flat hull pitch, baked before spin | `90` |
| `--yaw-offset` | heading added to every frame; sets `frame_00` | `0` |
| `--real-shadow` | render a TRUE cast shadow (Cycles + ground catcher) instead of the fake 2D one | off |
| `--sun-elev` / `--sun-az` | sun elevation / azimuth deg (real-shadow; shadow falls opposite) | `55` / `135` |
| `--sun-soft` | sun angular size deg = penumbra softness | `4` |
| `--samples` | Cycles samples (real-shadow) | `64` |
| `--no-shadow` | skip the baked ground shadow | off |
| `--shadow-alpha` | shadow darkness `0..1` | `0.45` |
| `--shadow-squash` | vertical flatten of the silhouette `0..1` | `0.7` |
| `--shadow-shear` | iso ground skew (x per y about the contact line) | `0.15` |
| `--shadow-grow` | dilate the pool past the hull (rim halo, fraction of frame) | `0.05` |
| `--shadow-dx` / `--shadow-dy` | shadow offset along the light (fraction of frame) | `0.0` / `0.045` |
Two shadow modes:
- **Real (`--real-shadow`)** — the proper one. A ground plane under the hull is flagged
as a Cycles shadow catcher; with the transparent film it contributes only the cast
shadow's alpha, so each frame carries the **true** shadow for that facing under the
sun (`--sun-elev`/`--sun-az`/`--sun-soft`). Shape follows the real 3D form and the
light, per facing — no guessing. Costs a Cycles pass (slower than EEVEE, but 16
frames is seconds).
- **Fake (default)** — `kbve-sprite-postprocess` derives a shadow from each frame's own
alpha silhouette and projects it onto the iso floor: squashed toward the contact
line, **sheared** along the iso axis, **dilated** so a soft rim haloes past the hull,
then offset/blurred/darkened. The grow + near-zero offset read as a grounded *contact
pool* (parked); raise `--shadow-dx/dy` for a hovering cast look. No 3D pass, engine-
agnostic, fully tunable. Drop either with `--no-shadow`.
### State variants (engines off / on)
A prop can ship multiple skins for different states. `kbve-skin-variant` masks a
glow color in the skin and desaturates + darkens it, so e.g. the parked ship's green
engines read as **off**:
```bash
uv run --project packages/python/kbve kbve-skin-variant \
--in idolknight.jpg --out idolknight_off.jpg --hue green
```
Bake one sheet per skin (`ship.png` from the off skin, `ship_on.png` from the
original glowing one). They share frame layout, so the game swaps the `EnvDef.sheet`
to switch state — powered-down while parked, glowing when engines are on.
---
## Interface
Blender's interface consists of workspaces, each containing a custom arrangement of editors (viewports, timelines, node editors, etc.).
The top header provides workspace tabs, while each editor has its own header with type selector and context-specific menus.
### Core Editors
- **3D Viewport** - Main scene editor for viewing and manipulating objects in 3D space. Supports multiple shading modes (solid, material preview, rendered).
- **Shader Editor** - Node-based material and shader creation using Cycles and Eevee material systems.
- **UV Editor** - Unwrap and edit UV texture coordinates for meshes.
- **Compositor** - Node-based post-processing and compositing for renders.
- **Geometry Nodes** - Procedural modeling and effects using node graphs.
- **Video Sequencer** - Timeline-based video editing with strips, effects, and audio.
- **Dope Sheet** - Keyframe animation management across multiple objects and properties.
- **Graph Editor** - Bezier curve editing for animation F-curves and driver functions.
- **NLA Editor** - Non-linear animation mixing and blending with action strips.
- **Text Editor** - Built-in Python script editor with syntax highlighting and execution.
- **Outliner** - Hierarchical tree view of scene collections, objects, and data blocks.
- **Properties Panel** - Context-sensitive properties for active object, material, modifier, etc.
### Workspaces
Default workspaces provide task-specific layouts:
- **Layout** - General-purpose workspace with viewport, outliner, and properties.
- **Modeling** - Optimized for polygon modeling with edit mode tools and modifier panel.
- **Sculpting** - High-resolution organic modeling with sculpt mode brushes and dyntopo.
- **UV Editing** - Simultaneous UV and 3D view for texture coordinate unwrapping.
- **Shading** - Shader Editor and viewport in material preview mode for material creation.
- **Animation** - Timeline, dope sheet, and graph editor for keyframe animation.
- **Rendering** - Viewport and render settings for final image production.
- **Compositing** - Compositor and viewer for post-processing render passes.
- **Geometry Nodes** - Geometry Nodes editor with spreadsheet for procedural workflows.
- **Scripting** - Python console, text editor, and info log for development.
---
## Modeling
Blender supports multiple modeling paradigms: polygon modeling, sculpting, procedural modeling, and curve-based modeling.
### Polygon Modeling
Traditional box-modeling workflow using vertices, edges, and faces.
Edit mode provides selection tools, extrude, loop cuts, bevel, inset, and subdivision operations.
Proportional editing allows smooth falloff transformations for organic shapes.
1. **Enter Edit Mode** - Tab key toggles between Object and Edit mode
2. **Select components** - Vertex (1), Edge (2), Face (3) selection modes
3. **Transform** - Move (G), Rotate (R), Scale (S) with axis constraints (X/Y/Z)
4. **Add geometry** - Extrude (E), Inset (I), Loop Cut (Ctrl+R)
5. **Refine** - Bevel (Ctrl+B), Subdivide, Merge, Knife tool (K)
### Modifiers
Non-destructive modifier stack for procedural operations:
- **Generate** - Array, Bevel, Boolean, Build, Decimate, Geometry Nodes, Mirror, Multiresolution, Remesh, Screw, Skin, Solidify, Subdivision Surface, Triangulate, Volume to Mesh, Weld, Wireframe
- **Deform** - Armature, Cast, Curve, Displace, Hook, Laplacian Deform, Lattice, Mesh Deform, Shrinkwrap, Simple Deform, Smooth, Smooth Corrective, Smooth Laplacian, Surface Deform, Warp, Wave
- **Physics** - Cloth, Collision, Dynamic Paint, Explode, Fluid, Ocean, Particle Instance, Particle System, Soft Body
- **Color** - UV Project, Vertex Weight Edit, Vertex Weight Mix, Vertex Weight Proximity
Modifiers are applied in stack order. The Subdivision Surface modifier is commonly used for smooth subdivision modeling.
### Sculpting
High-resolution organic modeling using dynamic topology or multiresolution modifiers.
Sculpt mode provides brushes for draw, grab, pinch, smooth, inflate, and crease operations.
**Dyntopo** (Dynamic Topology) - Automatically subdivides geometry under the brush stroke, enabling infinite detail without pre-subdivision.
**Multiresolution** - Non-destructive subdivision modifier preserving base mesh topology, allowing detail sculpting at higher levels while maintaining the ability to edit the base form.
### Geometry Nodes
Procedural modeling system using node graphs to generate or modify geometry.
Geometry Nodes can create instances, scatter points, generate meshes from curves, apply fields, and build complex procedural systems.
Common nodes:
- **Mesh Primitives** - Cube, UV Sphere, Ico Sphere, Cylinder, Cone, Grid
- **Curve Primitives** - Bezier Segment, Curve Circle, Curve Line, Curve Spiral
- **Instances** - Instance on Points, Realize Instances, Instances to Points
- **Geometry** - Join Geometry, Merge by Distance, Transform, Set Position
- **Mesh Operations** - Subdivide Mesh, Extrude Mesh, Dual Mesh, Triangulate
- **Utilities** - Math, Vector Math, Random Value, Map Range, Switch
---
## Materials and Shading
Blender uses node-based materials compatible with both rendering engines.
### Shader Nodes
The Shader Editor constructs materials using nodes connected by sockets:
- **Shader** - Principled BSDF (physically-based), Diffuse, Glossy, Glass, Emission, Mix Shader, Add Shader
- **Texture** - Image Texture, Procedural (Noise, Voronoi, Wave, Magic, Gradient, Musgrave), Brick, Checker, Environment
- **Color** - Mix, RGB Curves, Hue/Saturation, Bright/Contrast, Invert, Gamma
- **Vector** - Mapping, Normal Map, Bump, Vector Transform, Displacement
- **Input** - UV Map, Texture Coordinate, Geometry, Object Info, Vertex Color, Fresnel
- **Converter** - Math, Vector Math, Color Ramp, Separate/Combine RGB/XYZ, Map Range
### Principled BSDF
The Principled BSDF is a physically-based shader combining multiple layers into a single node.
It uses Disney's principled shading model with inputs for base color, metallic, roughness, IOR, transmission, emission, and normal maps.
Common PBR workflow:
1. **Base Color** - Albedo/diffuse texture (sRGB color space)
2. **Metallic** - Black for dielectric, white for metal (linear/non-color)
3. **Roughness** - Surface microsurface detail (linear/non-color)
4. **Normal** - Normal map connected via Normal Map node
5. **Emission** - Self-illumination (color + strength)
### UV Unwrapping
UV unwrapping projects 3D mesh surfaces onto 2D texture space.
1. **Mark Seams** - In Edit Mode, select edges and Mark Seam (Ctrl+E)
2. **Unwrap** - UV > Unwrap (U) - projects faces based on seams
3. **Layout UVs** - Scale, rotate, and pack islands in UV Editor
4. **Test with Texture** - Apply checker texture to verify distortion
Common unwrap methods:
- **Unwrap** - Angle-based unwrapping using marked seams
- **Smart UV Project** - Automatic island creation by angle threshold
- **Cube Projection** - Projects from six orthogonal directions
- **Sphere/Cylinder Projection** - Wraps around primitive shapes
- **Lightmap Pack** - Optimizes UVs for baked lighting with minimal overlap
---
## Animation
Blender provides keyframe animation, rigging, constraints, and non-linear animation systems.
### Keyframes
Keyframes define property values at specific frames. Blender interpolates between keyframes to create motion.
1. **Set initial pose** - Move object to starting position/rotation
2. **Insert keyframe** - Press I (or right-click property > Insert Keyframe)
3. **Advance timeline** - Scrub to new frame
4. **Change property** - Transform, rotate, or modify value
5. **Insert second keyframe** - Press I again
6. **Play animation** - Spacebar to preview
The Graph Editor displays F-curves (animation curves) as Bezier splines, allowing precise timing control through handle manipulation.
### Rigging
Rigging creates a skeleton (armature) of bones that deform a mesh via weight painting.
**Armature** - A collection of bones, each with head, tail, and roll defining local space.
**Bone Constraints** - Limit rotation, track targets, inverse kinematics (IK), copy transforms, damped track, stretch to.
**Weight Painting** - Defines bone influence per vertex. Accessed via Weight Paint mode with brush tools for painting influence values (0.0 to 1.0).
**Inverse Kinematics (IK)** - Automatically calculates joint rotations to reach a target position, useful for limbs and procedural animation.
### Actions and NLA
**Action** - A reusable animation clip containing F-curves for keyframed properties.
**NLA (Non-Linear Animation)** - Layers and blends actions on a track-based timeline, enabling animation mixing, looping, and transitions without destroying original keyframes.
### Drivers
Drivers create property relationships using expressions or variables.
Example: Drive a wheel's rotation based on a vehicle's forward movement, or link facial expression sliders to bone rotations.
---
## Rendering
Blender includes three render engines with different performance and quality tradeoffs.
### Eevee
Real-time physically-based renderer using rasterization.
Provides fast interactive feedback with screen-space reflections, volumetrics, subsurface scattering, and bloom.
Ideal for real-time previews, stylized rendering, and game engine-compatible material authoring.
**Key features:**
- Screen-space reflections and refractions
- Irradiance volumes and reflection probes for baked indirect lighting
- Volumetric lighting and fog with light scattering
- Subsurface scattering with screen-space approximation
- Shadows: VSM (Variance Shadow Maps) or ESM (Exponential Shadow Maps)
- Bloom, motion blur, depth of field, ambient occlusion
**Limitations:**
- No true path-traced global illumination (relies on probes)
- Screen-space effects limited to visible screen pixels
- Transparency rendering order dependent
### Cycles
Physically-based path tracer for photorealistic rendering.
Supports CPU and GPU rendering (CUDA, OptiX, HIP, Metal, oneAPI) with unbiased light transport.
**Render modes:**
- **Path Tracing** - Unbiased physically accurate light simulation
- **Branched Path Tracing** (deprecated) - Legacy mode with controllable sample distribution
- **Adaptive Sampling** - Stops sampling pixels when noise threshold reached, reducing render time
**Denoising:**
- **OptiX Denoiser** - NVIDIA GPU accelerated, highest quality
- **OpenImageDenoise** - Intel CPU/GPU denoiser, cross-platform
- **NLM (Non-Local Means)** - Legacy CPU denoiser
**Performance optimizations:**
- Tile rendering with configurable tile size
- BVH acceleration structure (static/dynamic)
- Light tree sampling for many-light scenes
- Caustics and motion blur control
### Workbench
Fast preview renderer for viewport shading during modeling and animation.
Not intended for final output, but useful for quick material and lighting previews.
### Render Settings
Common render settings (Cycles):
- **Sampling** - Max Samples (higher = less noise), Time Limit, Adaptive Threshold
- **Light Paths** - Max Bounces (Total, Diffuse, Glossy, Transmission, Volume, Transparency)
- **Film** - Transparent Background, Exposure, Pixel Filter
- **Performance** - Tile Size, Acceleration Structure, Use GPU
### Render Passes
Render passes output individual components (diffuse, specular, normal, AO, etc.) for compositing.
Configure in View Layer properties under Passes.
Common passes:
- **Combined** - Final composited image
- **Diffuse** - Direct and indirect diffuse lighting
- **Glossy** - Specular reflections
- **Transmission** - Refraction through transparent surfaces
- **Emission** - Self-illuminating materials
- **Environment** - Background/sky contribution
- **AO (Ambient Occlusion)** - Cavity shading
- **Shadow** - Shadow mask
- **Normal** - Surface normal vectors
- **UV** - UV coordinate map
- **Object/Material Index** - Masking IDs for compositing
- **Mist** - Depth-based fog pass
- **Cryptomatte** - Automatic per-object/material masks
---
## Compositing
The Compositor combines render passes, applies effects, and performs color grading using a node-based workflow.
### Compositor Nodes
- **Input** - Render Layers, Image, Movie Clip, Mask, RGB, Value
- **Output** - Composite, Viewer, File Output, Split Viewer
- **Color** - Mix, Color Balance, Hue/Saturation, Bright/Contrast, Gamma, Curves, Alpha Over
- **Filter** - Blur, Bilateral Blur, Bokeh Blur, Vector Blur, Dilate/Erode, Denoise, Despeckle, Filter, Glare, Inpaint, Pixelate, Sun Beams
- **Converter** - ID Mask, Math, Separate/Combine (RGBA, HSVA, YCbCrA), Set Alpha, RGB to BW
- **Matte** - Keying, Channel Key, Chroma Key, Color Key, Difference Key, Distance Key, Luminance Key, Double Edge Mask, Cryptomatte
- **Distort** - Transform, Scale, Rotate, Translate, Flip, Crop, Displace, Map UV, Lens Distortion, Movie Distortion, Corner Pin, Plane Track Deform
- **Vector** - Normal, Map Value, Map Range, Normalize
- **Layout** - Frame, Reroute, Switch
### Common Compositing Workflows
**Color Grading:**
1. Render Layers input → RGB Curves → Hue/Saturation → Composite
**Depth of Field:**
1. Render Layers (Image + Depth) → Defocus/Bokeh Blur (using depth as factor) → Composite
**Glow/Bloom:**
1. Render Layers → Glare (Fog Glow or Ghosts) → Mix with original → Composite
**Sky Replacement:**
1. Render Layers → ID Mask (Background) → Mix (Image + New Sky) → Composite
---
## Simulation
Blender includes physics simulation systems for cloth, fluid, soft body, rigid body, and particle dynamics.
### Rigid Body
Simulates solid objects with collision and stacking.
Objects are either Active (dynamic) or Passive (static collision).
Managed via Rigid Body World settings with gravity, solver iterations, and substeps.
**Collision Shapes:** Box, Sphere, Capsule, Cylinder, Cone, Convex Hull, Mesh (slowest, most accurate)
### Cloth
Simulates fabric using spring-based physics.
Requires vertex groups for pinning static areas and controlling stiffness.
**Settings:**
- **Quality Steps** - Simulation accuracy (higher = slower but more stable)
- **Stiffness** - Tension, Compression, Shear, Bending
- **Damping** - Energy loss per frame
- **Collisions** - Distance, Self-collisions, friction
### Fluid
Mantaflow-based fluid solver supporting liquid and gas (smoke) simulations.
**Liquid:**
- Domain defines simulation bounds and resolution
- Flow objects emit or absorb liquid
- Effector objects deflect or control flow
- Mesh generated from particle system
**Smoke/Fire:**
- Domain contains smoke with voxel resolution
- Flow emits smoke or fire with velocity, density, heat
- Volumetric shader renders density field
### Soft Body
Deformable mesh simulation with springs, goal weights, and collision.
Useful for jiggling objects, cushions, or soft organic motion.
### Particle Systems
Point-based particles for hair, fur, grass, crowds, and effects.
**Emitter:**
- Emits particles from mesh faces or vertices
- Controls lifetime, velocity, rotation, size
- Supports force fields (wind, turbulence, gravity)
**Hair:**
- Generates strand-based hair from surface
- Combing, cutting, growing in particle edit mode
- Strand rendering or child particle interpolation
**Keyed:**
- Particles follow target positions for controlled motion
**Boids:**
- Flocking simulation with rules for separation, alignment, cohesion, goal seeking
---
## Scripting and Automation
Blender's Python API (`bpy`) provides programmatic access to all editor functions, data structures, and operators.
### Python Console
The Scripting workspace includes a Python console with autocomplete for quick API testing:
```python
import bpy
# Create a UV sphere
bpy.ops.mesh.primitive_uv_sphere_add(location=(0, 0, 0), radius=2)
# Access active object
obj = bpy.context.active_object
# Rename object
obj.name = "MySphere"
# Apply material
mat = bpy.data.materials.new(name="Red Material")
mat.diffuse_color = (1, 0, 0, 1) # RGBA
obj.data.materials.append(mat)
# Keyframe animation
obj.location.z = 0
obj.keyframe_insert(data_path="location", frame=1)
obj.location.z = 5
obj.keyframe_insert(data_path="location", frame=50)
```
### Addon Development
Addons extend Blender with custom operators, panels, menus, and importers/exporters.
**Addon structure:**
```python
bl_info = {
"name": "My Addon",
"author": "Your Name",
"version": (1, 0),
"blender": (4, 0, 0),
"category": "Object",
}
import bpy
class OBJECT_OT_my_operator(bpy.types.Operator):
bl_idname = "object.my_operator"
bl_label = "My Operator"
def execute(self, context):
# Operator logic
return {'FINISHED'}
def register():
bpy.utils.register_class(OBJECT_OT_my_operator)
def unregister():
bpy.utils.unregister_class(OBJECT_OT_my_operator)
if __name__ == "__main__":
register()
```
**Installation:**
1. Save script as `.py` file
2. Edit > Preferences > Add-ons > Install
3. Enable checkbox to activate
### Batch Rendering
Automate rendering via command line:
```bash
# Render single frame
blender -b scene.blend -f 1
# Render animation range
blender -b scene.blend -s 1 -e 250 -a
# Render with Python script
blender -b scene.blend -P render_script.py
# Set output path
blender -b scene.blend -o /tmp/render_####.png -f 1
# Use specific engine
blender -b scene.blend -E CYCLES -f 1
```
### Common API Patterns
**Iterate over selected objects:**
```python
for obj in bpy.context.selected_objects:
print(obj.name)
```
**Create mesh from Python:**
```python
import bpy
import bmesh
mesh = bpy.data.meshes.new("MyMesh")
obj = bpy.data.objects.new("MyObject", mesh)
bpy.context.collection.objects.link(obj)
bm = bmesh.new()
bm.from_mesh(mesh)
# Add vertices, edges, faces via bmesh API
bm.to_mesh(mesh)
bm.free()
```
**Access node trees:**
```python
mat = bpy.data.materials.new("NodeMaterial")
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
# Clear default nodes
nodes.clear()
# Add nodes
output = nodes.new('ShaderNodeOutputMaterial')
bsdf = nodes.new('ShaderNodeBsdfPrincipled')
links.new(bsdf.outputs['BSDF'], output.inputs['Surface'])
```
---
## Addons
Blender ships with official addons and supports third-party extensions.
### Official Addons (included)
Enable via Edit > Preferences > Add-ons:
- **Import-Export** - FBX, OBJ, Alembic, USD, glTF 2.0, STL, PLY, X3D, SVG
- **Rigging** - Rigify (advanced auto-rigging), Bone Selection Sets
- **Mesh** - Bool Tool, LoopTools, Auto Mirror, Extra Objects
- **Animation** - AnimAll (animate mesh data), Copy Global Transform
- **Render** - Freestyle SVG Exporter
- **Node** - Node Wrangler (shader shortcuts)
- **3D View** - Measureit (dimension annotation), 3D Navigation
### Popular Third-Party Addons
- **Hard Ops / Boxcutter** - Hard-surface modeling tools
- **Machine Tools** - CAD-style precision modeling
- **FLIP Fluids** - High-performance liquid simulation
- **Animation Nodes** - Procedural animation via node graphs (free)
- **Retopoflow** - Retopology suite with advanced brush tools
- **UVPackmaster** - AI-powered UV packing optimization
- **X-Muscle System** - Muscle and skin deformation rig
- **Dendrite** - Terrain generation
- **Scatter** - Advanced scattering and ecosystem tools
- **Real Camera** - Photographer-friendly camera controls
---
## Pipeline Integration
### Game Engine Export
**Unreal Engine:**
- Use FBX exporter with "Apply Modifiers" and "Bake Animation"
- Enable "Selected Objects" for specific exports
- Collision primitives named `UCX_[MeshName]_##`
**Unity:**
- Export as FBX with "Apply Transform" disabled (Unity handles scale)
- Use "Triangulate Faces" for predictable geometry
- Separate materials and embed textures or use external references
**Godot:**
- glTF 2.0 export for best compatibility (embedded or separate)
- Support for animations, materials, cameras, lights
- Use Godot-Blender Exporter addon for direct integration
### CICD and Automation
Blender supports headless operation for render farms, asset baking, and CI pipelines.
**Headless rendering:**
```bash
# Render without GUI
blender -b scene.blend -o /output/frame_#### -F PNG -s 1 -e 100 -a
# Enable GPU rendering via script
blender -b scene.blend -P enable_gpu.py -- -f 1
```
**enable_gpu.py:**
```python
import bpy
# Enable CUDA or OptiX
prefs = bpy.context.preferences.addons['cycles'].preferences
prefs.compute_device_type = 'CUDA' # or 'OPTIX', 'HIP', 'METAL'
prefs.get_devices()
# Enable all GPUs
for device in prefs.devices:
device.use = True
# Set render engine
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.cycles.device = 'GPU'
# Save preferences
bpy.ops.wm.save_userpref()
```
### Docker Rendering
Run Blender in a container for isolated render jobs:
```dockerfile
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
blender \
xvfb \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /blender
CMD ["blender", "-b", "scene.blend", "-a"]
```
**Run container:**
```bash
docker run -v $(pwd):/blender blender-render
```
---
## Asset Libraries
Blender 3.0+ introduced Asset Browser for managing reusable materials, objects, node groups, and poses.
### Creating Assets
1. Select object, material, or node group
2. Right-click > Mark as Asset
3. Configure metadata (tags, description, preview)
4. Save to asset library path
### Asset Libraries
Configure libraries in Preferences > File Paths > Asset Libraries:
- **Current File** - Assets in active .blend file
- **User Library** - Personal asset collection
- **Custom Libraries** - Studio or project-specific paths
### Asset Packs
Community and commercial asset libraries:
- **Blender Cloud** - Official textures, HDRIs, and models (subscription)
- **Poly Haven** - Free CC0 HDRIs, textures, models
- **Quixel Megascans** - Photogrammetry assets (free with Epic account)
- **BlenderKit** - Free and paid addon with integrated asset browser
---
## KBVE Integration
Blender can be integrated into KBVE workflows for procedural asset generation, batch rendering, and pipeline automation.
### CI/CD Workflow
The KBVE monorepo runs headless Blender through a **router → flow** pair on the self-hosted `mac-blender` runner:
- [`.github/workflows/ci-blender-router.yml`](.github/workflows/ci-blender-router.yml) — `workflow_dispatch` entry point. Validates inputs, picks the LFS backend (`forgejo` or `azure`), then hands off to the flow.
- [`.github/workflows/ci-blender-flow.yml`](.github/workflows/ci-blender-flow.yml) — reusable `workflow_call` builder. Pulls the target object from LFS, runs the task on `[self-hosted, macOS, ARM64, mac-blender]`, and uploads artifacts.
The object lives in external LFS — Forgejo (`git.kbve.com`, via `FORGEJO_USER`/`FORGEJO_TOKEN`) or Azure DevOps (via `AZURE_PAT`). Tag your runner with the `mac-blender` label so only Blender jobs land on it.
**Available tasks:**
- **`validate`** - Check blend file integrity and test headless launch
- **`render`** - Render single frames or animation ranges with configurable engine/device
- **`export`** - Export scene or selected objects to FBX, glTF, OBJ, USD, Alembic, STL
- **`batch-export`** - Export each mesh object as a separate file
- **`script`** - Run custom Python scripts in headless mode
**Example workflow dispatch:**
```bash
# Render with Cycles GPU — object pulled from Forgejo LFS
gh workflow run ci-blender-router.yml \
-f task=render \
-f app_name=my-project \
-f lfs_backend=forgejo \
-f object_glob=assets/blender \
-f blend_file=assets/blender/scene.blend \
-f render_engine=CYCLES \
-f render_device=GPU \
-f frame_range=1-100 \
-f samples=128
# Export all objects as FBX for Unreal — object pulled from Azure DevOps
gh workflow run ci-blender-router.yml \
-f task=batch-export \
-f app_name=game-assets \
-f lfs_backend=azure \
-f external_repo_url=dev.azure.com/kbve/art/_git/props \
-f blend_file=external-blender/props.blend \
-f export_format=FBX \
-f output_path=/tmp/exports
```
**Automatic Blender installation:**
The workflow automatically installs Blender via Homebrew if not found:
```bash
brew install --cask blender
```
**Supported render engines:**
| Engine | GPU Support | Best For |
|--------|-------------|----------|
| `CYCLES` | CUDA, OptiX, HIP, Metal | Photorealistic path tracing |
| `BLENDER_EEVEE` | Yes (rasterization) | Real-time previews, stylized |
| `BLENDER_WORKBENCH` | Yes (OpenGL) | Viewport solid shading |
**Export formats:**
| Format | Extension | Use Case |
|--------|-----------|----------|
| `FBX` | `.fbx` | Unreal Engine, Unity, Maya |
| `GLTF` | `.gltf` / `.glb` | Web, Godot, Three.js |
| `OBJ` | `.obj` | Universal interchange |
| `USD` | `.usd` | Pixar USD pipeline |
| `ALEMBIC` | `.abc` | VFX, baked animation |
| `STL` | `.stl` | 3D printing |
**Pipeline integration:**
The workflow outputs artifacts via `actions/upload-artifact@v7`, which can be consumed by downstream jobs or downloaded manually.
```yaml
# Example: Render in Blender, then deploy to Unreal
jobs:
render:
uses: KBVE/kbve/.github/workflows/ci-blender-flow.yml@dev
with:
task: render
lfs_backend: forgejo
object_glob: assets/blender
blend_file: assets/blender/environment.blend
output_path: /tmp/renders
secrets: inherit
unreal_import:
needs: [render]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v8
with:
name: blender-project-render
path: ./renders
# ... import into Unreal via Python/C++ automation
```
### Batch Export Script
Automate FBX export for all selected objects:
```python
import bpy
import os
output_dir = "/tmp/blender_export"
os.makedirs(output_dir, exist_ok=True)
for obj in bpy.context.selected_objects:
# Select only this object
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
# Export as FBX
filepath = os.path.join(output_dir, f"{obj.name}.fbx")
bpy.ops.export_scene.fbx(
filepath=filepath,
use_selection=True,
apply_scale_options='FBX_SCALE_ALL',
bake_anim=True
)
print(f"Exported: {filepath}")
```
Run via:
```bash
blender -b scene.blend -P batch_export.py
```
### Legacy CI Pipeline Example
```yaml
# .github/workflows/blender-render.yml
name: Blender Render
on:
push:
paths:
- '**.blend'
jobs:
render:
runs-on: ubuntu-latest
container:
image: nytimes/blender:4.0-gpu-ubuntu22.04
steps:
- uses: actions/checkout@v4
- name: Render Scene
run: |
blender -b scene.blend \
-o /tmp/render_#### \
-F PNG \
-s 1 -e 100 -a
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: renders
path: /tmp/render_*.png
```
### Geometry Node Export for Unreal
Use Geometry Nodes to procedurally generate assets, then export to Unreal:
1. Create Geometry Node graph in Blender
2. Use Python script to realize instances and export
3. Import FBX into Unreal as static mesh or skeletal mesh
4. Optionally: Export vertex animation as Alembic cache
---
## Performance Tips
### Viewport Optimization
- **Simplify Overlays** - Disable overlays (Alt+Shift+Z) for large scenes
- **Reduce Draw Distance** - Limit clip end in viewport shading settings
- **Use Collections** - Organize scene into collections, hide unused
- **Limit Subdivision** - Keep viewport subdivision level lower than render
- **Disable Eevee Effects** - Turn off bloom, volumetrics, SSR for faster preview
### Render Optimization
- **Adaptive Sampling** - Stop rendering clean pixels early (Cycles)
- **Denoising** - Use OptiX denoiser on NVIDIA GPUs for lower sample counts
- **Light Path Settings** - Reduce max bounces (4-8 total is often sufficient)
- **Tile Size** - GPU: larger tiles (256-512), CPU: smaller tiles (32-64)
- **Resolution** - Render at 50% resolution for preview, 100% for final
- **Bake Indirect Lighting** - Use Eevee irradiance volumes for real-time GI approximation
### Large Scene Management
- **Instancing** - Use collection instances for repeated geometry (trees, buildings)
- **Geometry Nodes** - Procedural generation avoids storing duplicate data
- **Level of Detail (LOD)** - Decimate modifier or simplified versions for distant objects
- **Library Linking** - Link assets from external .blend files to reduce file size
- **Purge Orphan Data** - File > Clean Up > Purge Orphan Data removes unused data blocks
---
## Troubleshooting
### Common Issues
**Slow Viewport Performance:**
- Disable overlays, reduce subdivision levels, hide unused collections
- Check GPU is selected in Preferences > System > Cycles Render Devices
**Render Crashes:**
- Reduce tile size, lower max samples, disable adaptive sampling
- Update GPU drivers, check VRAM usage (render smaller regions)
- For CPU renders, reduce thread count in render settings
**Materials Not Showing:**
- Ensure viewport shading is set to Material Preview or Rendered
- Check material has Use Nodes enabled
- Verify Shader Editor has Principled BSDF connected to Material Output
**Animation Not Playing:**
- Check playback range (start/end frames in timeline)
- Verify keyframes exist in Dope Sheet or Graph Editor
- Disable simulation caching if physics is causing lag
**Export Issues:**
- Apply modifiers before export (or enable "Apply Modifiers" in exporter)
- Triangulate faces for game engines (or enable in FBX export)
- Check scale settings (FBX scale, Apply Transform)
---
# CSS
> CSS styles the web. From modern CSS features to TailwindCSS utilities and ready-to-use custom components.
Source: https://kbve.com/application/css/
import {
Aside,
Steps,
Card,
CardGrid,
Code,
FileTree,
} from '@astrojs/starlight/components';
import { Giscus, Adsense, DevCode } from '@/components/astropad';
## Information
CSS (Cascading Style Sheets) is the styling layer of the web.
It controls layout, color, typography, motion and responsiveness.
Where HTML gives a page structure and JavaScript gives it behavior, CSS gives it form.
This document is an all-in-one reference: modern CSS features that ship in evergreen browsers today, the TailwindCSS utility framework, and a library of copy-paste custom components (buttons, forms, text effects, glassmorphism and more).
---
## Modern CSS
Modern CSS removed the need for many preprocessor tricks and JavaScript hacks.
The features below are baseline across current Chrome, Firefox, Safari and Edge.
### Nesting
Native CSS nesting works without Sass. Selectors nest with `&` for the parent reference.
```css
.card {
padding: 1rem;
border-radius: 0.5rem;
& h2 {
margin: 0;
}
&:hover {
box-shadow: 0 4px 12px rgb(0 0 0 / 0.15);
}
}
```
### :has() — the parent selector
`:has()` selects an element based on its descendants. It enables parent and previous-sibling styling that once required JavaScript.
```css
/* Style a card that contains an image */
.card:has(img) {
grid-template-rows: auto 1fr;
}
/* Style a label whose input is checked */
label:has(input:checked) {
font-weight: 700;
}
/* Form with an invalid field */
form:has(:invalid) button[type="submit"] {
opacity: 0.5;
pointer-events: none;
}
```
### Container queries
Container queries style an element based on the size of its container, not the viewport. This makes components truly reusable across layouts.
```css
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
@container sidebar (min-width: 400px) {
.widget {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
```
### Fluid type with clamp()
`clamp(MIN, PREFERRED, MAX)` builds responsive typography and spacing without breakpoints.
```css
h1 {
/* Never smaller than 1.5rem, never larger than 3rem, scales with viewport */
font-size: clamp(1.5rem, 1rem + 3vw, 3rem);
}
```
### Modern color: oklch() and color-mix()
`oklch()` is a perceptually uniform color space — lightness stays consistent across hues. `color-mix()` blends two colors in any space.
```css
:root {
--brand: oklch(0.7 0.15 200);
/* 80% brand, 20% white — a tint without a second variable */
--brand-tint: color-mix(in oklch, var(--brand) 80%, white);
--brand-shade: color-mix(in oklch, var(--brand) 80%, black);
}
```
### @property — typed custom properties
`@property` registers a custom property with a type, enabling animation of values CSS could not previously interpolate (like gradient stops or angles).
```css
@property --angle {
syntax: "";
initial-value: 0deg;
inherits: false;
}
.spinner {
background: conic-gradient(from var(--angle), cyan, magenta, cyan);
animation: rotate 2s linear infinite;
}
@keyframes rotate {
to { --angle: 360deg; }
}
```
### Subgrid
`subgrid` lets a nested grid inherit the track sizing of its parent, aligning content across cards.
```css
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid; /* header / body / footer line up across all cards */
}
```
### Scroll-driven animations
Animate elements as the user scrolls — no scroll-event JavaScript, runs on the compositor.
```css
@keyframes reveal {
from { opacity: 0; transform: translateY(2rem); }
to { opacity: 1; transform: translateY(0); }
}
.section {
animation: reveal linear both;
animation-timeline: view();
animation-range: entry 0% cover 40%;
}
```
### View transitions
The View Transitions API animates between two DOM states — the browser snapshots before and after, then cross-fades or morphs between them. It works for in-page state changes (same-document) and across page navigations (cross-document / MPA).
**Same-document.** Wrap the DOM mutation in `startViewTransition`. The browser captures, applies your callback, then animates old → new. A default cross-fade comes free.
```js
function toggle() {
if (!document.startViewTransition) return update(); // graceful fallback
document.startViewTransition(() => update()); // animated path
}
```
**Shared-element morph.** Give the same `view-transition-name` to an element in both states and the browser tweens it between positions — a thumbnail growing into a hero, a card expanding into a detail page.
```css
.thumbnail { view-transition-name: hero; }
/* On the next view, the large image carries the SAME name → it morphs */
.detail-image { view-transition-name: hero; }
```
**Customizing.** The transition exposes pseudo-elements you can target with normal `@keyframes` — `::view-transition-old(name)` (outgoing) and `::view-transition-new(name)` (incoming).
```css
@keyframes slide-from-right { from { transform: translateX(40px); opacity: 0; } }
@keyframes fade-out { to { opacity: 0; } }
::view-transition-old(root) { animation: fade-out 0.2s both; }
::view-transition-new(root) { animation: slide-from-right 0.3s both; }
```
**Cross-document (MPA).** One CSS rule opts an entire multi-page site into transitions — no JavaScript, no SPA router.
```css
@view-transition { navigation: auto; }
```
### Respecting motion preferences
Always gate non-essential motion behind `prefers-reduced-motion`. Users who set the OS "reduce motion" flag get a static experience; everyone else gets the animation.
```css
@media (prefers-reduced-motion: no-preference) {
.card {
animation: reveal linear both;
animation-timeline: view();
}
}
/* Or kill all motion as a blanket safety net */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
```
### Text wrapping
```css
h1, h2, h3 {
text-wrap: balance; /* even line lengths for headings */
}
p {
text-wrap: pretty; /* avoids orphans / single-word last lines */
}
```
### Logical properties
Logical properties adapt to writing direction (LTR / RTL) automatically.
```css
.box {
margin-inline: auto; /* left+right in LTR, swaps in RTL */
padding-block: 1rem; /* top+bottom */
border-inline-start: 2px solid; /* "left" border that flips for RTL */
}
```
---
## Layout Patterns
The two layout engines — Flexbox (one dimension) and Grid (two dimensions) — cover almost every layout. A handful of patterns recur constantly.
### Responsive grid without media queries
`auto-fit` + `minmax()` reflows columns to fit the container. Cards wrap on their own as space shrinks.
```css
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
gap: 1rem;
}
```
### Dead-center anything
```css
.center {
display: grid;
place-items: center;
}
```
### Sticky footer
Footer sits at the bottom on short pages, pushed down on tall ones — no fixed heights.
```css
body {
min-height: 100dvh; /* dvh = dynamic viewport, accounts for mobile URL bars */
display: flex;
flex-direction: column;
}
main {
flex: 1; /* grows to fill, footer follows */
}
```
### The stack and the sidebar
```css
/* Even vertical rhythm between children */
.stack > * + * {
margin-block-start: 1.5rem;
}
/* Sidebar that collapses below content when space runs out */
.with-sidebar {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.with-sidebar > .sidebar { flex: 1 1 15rem; }
.with-sidebar > .content { flex: 999 1 60%; }
```
### Cascade layers
`@layer` gives you explicit control over specificity ordering — later layers always win over earlier ones, regardless of selector strength. This tames override wars and is how Tailwind v4 organizes its own output (`theme`, `base`, `components`, `utilities`).
```css
@layer reset, base, components, utilities;
@layer base {
a { color: blue; }
}
@layer components {
/* Wins over base even though the selector is identical specificity */
.link { color: rebeccapurple; }
}
```
---
## Typography
Readable type is mostly a few well-chosen defaults: a sensible measure, comfortable line height, and a scale that adapts to the viewport.
### Fluid type scale
Combine `clamp()` with custom properties for a scale that breathes between phone and desktop without breakpoints.
```css
:root {
--step--1: clamp(0.83rem, 0.78rem + 0.24vw, 0.96rem);
--step-0: clamp(1rem, 0.91rem + 0.43vw, 1.25rem);
--step-1: clamp(1.2rem, 1.07rem + 0.65vw, 1.56rem);
--step-2: clamp(1.44rem, 1.26rem + 0.93vw, 1.95rem);
--step-3: clamp(1.73rem, 1.47rem + 1.29vw, 2.44rem);
}
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
p { font-size: var(--step-0); }
```
### Measure and rhythm
```css
.prose {
max-width: 65ch; /* ~65 characters is the readable sweet spot */
line-height: 1.6; /* unitless — scales with font-size */
text-wrap: pretty; /* avoids orphaned last words */
}
```
### Variable fonts
One file, every weight and width. Animate the axes live with `font-variation-settings`.
```css
@font-face {
font-family: "Inter var";
src: url("/fonts/inter.woff2") format("woff2");
font-weight: 100 900; /* the full axis range */
font-display: swap; /* show fallback text immediately, swap when loaded */
}
.heading {
font-family: "Inter var", sans-serif;
font-weight: 720; /* any value in range, not just 700 */
}
```
### Truncation & clamping
export const truncateCode = `
Single line that gets cut with an ellipsis when it overflows its container
Multi-line clamp limits a block to a fixed number of lines and adds an ellipsis. Useful for card descriptions and previews where you want a uniform height regardless of how much copy each item carries. Anything past the third line is hidden.
`;
---
## Transitions & Animation
Two mechanisms: `transition` interpolates between two states (a hover, a class toggle), while `@keyframes` + `animation` runs a defined timeline that can loop and have many steps.
### Transitions
```css
.button {
background: var(--brand);
/* property | duration | easing | delay */
transition: background 200ms ease-out, transform 200ms ease-out;
}
.button:hover {
transform: translateY(-2px);
}
```
### Easing
`ease-out` for things entering, `ease-in` for things leaving, custom `cubic-bezier()` for character. Modern browsers also support `linear()` for spring and bounce curves without JavaScript.
```css
:root {
--ease-snappy: cubic-bezier(0.2, 0, 0, 1);
/* A spring-like bounce, approximated with a linear() stop list */
--ease-spring: linear(0, 0.4 12%, 1.1 28%, 0.95 42%, 1.02 60%, 1);
}
```
### Keyframes
A full timeline. This is the `shimmer` keyframe the gradient-text example earlier relies on — define it once globally (in your stylesheet or Tailwind `@theme`).
```css
@keyframes shimmer {
to { background-position: 200% center; }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-0.5rem); }
}
.badge {
animation: float 3s ease-in-out infinite;
}
```
### Animation Gallery
Live, self-contained keyframe demos. Each snippet carries its own `
`;
#### Pulse Ring
A notification dot with an expanding, fading ring — the classic "live" indicator.
export const fxPulseCode = `
`;
#### Shimmer Text
The gradient shimmer referenced earlier — now running live via an embedded keyframe.
export const fxShimmerCode = `
Shimmer
`;
#### Typewriter
`steps()` makes the reveal tick character-by-character; a second keyframe blinks the caret.
export const fxTypeCode = `
console.log(42)
`;
#### Marquee
Seamless infinite scroll — duplicate the content and translate by -50%.
export const fxMarqueeCode = `
`;
#### Flip Card
A 3D flip on hover with `transform-style: preserve-3d` and `backface-visibility`.
export const fxFlipCode = `
Hover me
Flipped!
`;
---
## Effects & Filters
CSS can do a lot of what once needed image editors — blur, recolor, clip and blend — all GPU-accelerated and animatable.
### filter
`filter` chains image-style operations: `blur`, `brightness`, `contrast`, `grayscale`, `saturate`, `hue-rotate`, `drop-shadow`. They compose left to right.
export const fxFilterCode = `
nonegrayscale(1)hue-rotateblur(4px)drop-shadow
`;
### backdrop-filter
`backdrop-filter` filters whatever sits **behind** an element — the basis of frosted glass.
export const fxBackdropCode = `
Frosted Glass
backdrop-filter: blur + saturate
`;
### mix-blend-mode
Blend an element with what's underneath — `difference`, `multiply`, `screen`, `overlay`. Great for text that stays legible over any background.
export const fxBlendCode = `
BLEND
`;
### clip-path
`clip-path` crops an element to any shape — polygons, circles, insets. Animatable between equal point counts.
export const fxClipCode = `
pentagoncirclearrow tag
`;
### mask-image
A mask uses a gradient or image alpha to fade or cut out content — softer than the hard edges of `clip-path`.
export const fxMaskCode = `
This paragraph fades out toward the edge using a linear-gradient mask — the classic "read more" teaser without an overlay element.
`;
---
## TailwindCSS
TailwindCSS is a utility-first CSS framework. Instead of writing custom CSS, you compose designs from low-level utility classes directly in your markup.
This promotes consistency, reusability and speed, and the production build strips every class you do not use.
Tailwind v4 is **CSS-first**: configuration lives in your CSS via `@theme` instead of a `tailwind.config.js` file, the engine is faster, and many former plugins (container queries, text-shadow) are now built in.
### TailwindCSS Setup (v4)
0. **Create a project directory**
```shell
mkdir my-tailwind-project
cd my-tailwind-project
pnpm init
```
1. **Install Tailwind v4**
v4 ships a dedicated Vite plugin (or the standalone CLI / PostCSS plugin).
```shell
pnpm add tailwindcss @tailwindcss/vite
```
2. **Wire up the Vite plugin**
```js
// vite.config.js
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [tailwindcss()],
});
```
3. **Import Tailwind in your CSS**
One line replaces the old `@tailwind base/components/utilities` trio.
```css
/* src/styles.css */
@import "tailwindcss";
```
4. **Configure in CSS with @theme**
Design tokens live in CSS now. No `tailwind.config.js` required.
```css
@import "tailwindcss";
@theme {
--color-brand: oklch(0.7 0.15 200);
--font-display: "Satoshi", sans-serif;
--animate-spin-slow: spin 5s linear infinite;
}
```
These tokens auto-generate utilities like `bg-brand`, `font-display` and `animate-spin-slow`.
5. **Use it in markup**
```html
`;
#### Loading
A spinner swaps in while an action is in flight; the button stays disabled.
export const buttonLoadingCode = `
`;
#### 3D Pressable
A hard bottom shadow that collapses on click — the button physically depresses.
export const button3dCode = `
`;
#### Gradient Border
A gradient ring around a solid core — padding-box vs border-box trick, done here with a wrapper.
export const buttonGradBorderCode = `
`;
#### Social Login
export const buttonSocialCode = `