LogoLogo
Go ToJoin the Community
  • Getting Started
    • Introduction
    • How it Works
    • Onboarding
  • Examples
    • Tutorials
      • Hello, World!
      • Image Generation w/ Stable Diffusion
  • CREATE WITH BYTENITE
    • Building Blocks
      • Apps
      • Job Templates
  • SDK
    • ByteNite Dev CLI
  • Launch with ByteNite
    • Data Sources
      • AWS S3
      • Google Cloud Storage
      • Storj
      • HTTP
      • File Upload
      • Temporary Bucket
    • Jobs
  • API Reference
    • Customer API
      • Jobs
        • Create
        • Read
        • Update
        • Manage
        • Other
      • Logs
      • Data Sources
      • Templates
      • Events
    • Authentication API
      • Access Token
      • API Keys
      • Secrets
      • User
    • Developer API
      • Apps
        • Metadata
        • Push
        • Manage
        • Pull
      • Engines
        • Metadata
        • Push
        • Manage
        • Pull
      • Templates
    • Wallet API
      • Balance
      • Transactions
      • Exchange Rate
      • Redeem Coupon
  • GUI
  • Other
    • Glossary
    • Feature Requests
    • Status
Powered by GitBook

© 2025 ByteNite Inc.

On this page
  • 📁 App directory overview
  • 🔧 Configure app settings: manifest.json
  • App versioning
  • Platform & hardware requirements
  • 👨🏽‍💻 Develop the main script
  • Default environment variables
  • Example: Python entry point script
  • ☑️ (Optional) Require Parameter Validation: schema.json
  • 💡 App Development Tips

Was this helpful?

Export as PDF
  1. CREATE WITH BYTENITE
  2. Building Blocks

Apps

An App is a versioned program that lets you run code on ByteNite.

Apps can be simple—just a single function—or complex systems with multiple libraries and functions.

This guide walks through the structure of an app’s directory and explains where (and how) to write your code so it integrates smoothly into a ByteNite app.

📁 App directory overview

To create a new app directory in your local environment, execute the following ByteNite Dev CLI command:

bytenite app new [app_name]

A sample folder with pre-populated files and fields will be generated at your current path:

/[app_name]
├── app
│   ├── main.*
│   └── [scripts/libraries]
├── manifest.json
├── template.json
└── schema.json

Directory Structure:

  • app/ Contains your application’s entry point (main.*), plus any additional scripts or libraries. See: 👨🏽‍💻 Develop the main script.

  • manifest.json Holds configurations, details, and app requirements. See: 🔧 Configure app settings: manifest.json.

  • template.json Defines your job template, which ties together your building blocks into a single configuration. This template can be optionally submitted with your app. Learn more: #Job Templates.

  • schema.json Provides input parameter validation for your app using a JSON schema definition. See:☑️ (Optional) Require Parameter Validation: schema.json.


🔧 Configure app settings: manifest.json

The manifest.json file holds the core details of your app—things like platform configuration, hardware requirements, the app’s name, and version.

Here’s a sample manifest:

manifest.json - full example
{
  "name": "my-first-stable-diffusion-app",
  "version": "0.4",
  "description": "A stable diffusion app using HuggingFace's diffusers",
  "platform": "docker",
  "entrypoint": "main.py",
  "platform_config": {
    "container": "huggingface/diffusers-pytorch-cuda:latest"
  },
  "device_requirements": {
    "min_cpu": 4,
    "min_memory": 8
  }
}

How the manifest works

The manifest defines key settings your app depends on, including:

  • Platform configuration (e.g., Docker container details)

  • Hardware requirements (e.g., minimum CPU and memory)

  • App metadata (name, version, description)

Since many apps rely on specific hardware or container setups, tweaking this file to align with your app’s needs is essential for reliable performance.

The following sections dive deeper into app versioning, platform settings, and hardware requirements—all centered around how to define them in your manifest.json.

App versioning

Each app is identified by a name and a version, following the semantic versioning format: major.minor

Example:

manifest.json - versioning example
{
  ...
  "name": "my-first-stable-diffusion-app",
  "version": "0.4",
  "description": "A stable diffusion app using HuggingFace's diffusers"
  ...
}

Each app is identified by a name and a version, following the semantic versioning format "major.minor".

Version Management

  • Unlimited versions: You can store and activate unlimited versions of your app, provided that each one has a unique (name, version) pair.

  • Uploading a new version: Uploading an app with a new (name, version) combination will create a new, independent record. it creates a fresh, independent record. This is helpful if you need to maintain separate versions for testing, staging, or production.

  • Updating versions: Uploading an app with an existing (name, version) pairwill overwrite the current version with your updated code and configurations.

Use the name and version fields in the manifest to manage app uploads and ensure consistency across your deployments:

name string

Description:

The human-readable name of your app. This acts as the app’s identifier.

Supported Format:

  • Alphanumeric characters, dashes (-), and underscores (_)

  • Max length: 64 characters

Example:

"my-first-stable-diffusion-app"

version string

Description:

A semantic version for managing updates.

Supported Format:

"[major].[minor]"

  • major int

  • minor int

Example:

"0.4"

Platform & hardware requirements

To configure your app’s environment:

  • Define the platform type and the container image using the platform and platformConfig fields in your manifest.

  • Set your app’s minimum hardware requirements (like CPU and memory) using the deviceRequirements field.

These settings ensure your app runs in the right environment with the right resources. Learn more below.

Platform Configs

To run your app on ByteNite, use the platform and platformConfig fields in the manifest to define the Docker container image your app should use.

Example:

manifest.json - platform configs example
{
  ...
  "platform": "docker",
  "entrypoint": "main.py",
  "platform_config": {
    "container": "huggingface/diffusers-pytorch-cuda:latest",
    "private_image": true,
    "username": "alex_rivers6241",
    "token":"dckr_pat_HgNOmERVLDm1YBSvAJELJeGOOAM"
  }
  ...
}

The container image must be either publicly accessible or include the proper credentials if it’s private. It can be hosted on Docker Hub or any compatible container registry.

While there are many ready-to-use images, most apps require custom images tailored to specific dependencies, environment variables, or system configurations. Defining this ensures your app runs exactly how you need it.

platform string

Description:

Specifies the platform your app will run on.

Supported Values:

  • ["docker"]

platformConfig object

Description:

Contains platform-specific configurations.

Supported Properties:

    • "python:3.8-alpine"

    • "tensorflow/tensorflow:latest-gpu"

    • "blender/blender:latest"

  • private_image boolean Set this to true if your image repository is private.

  • username string Your Docker Hub username (only needed if private_image is true).

Example:

{
    "container": "huggingface/transformers-pytorch-cpu:latest",
    "private_image": true,
    "username": "alex_rivers6241",
    "token":"dckr_pat_HgNOmERVLDm1YBSvAJELJeGOOAM"
}

In summary, these are the suggested steps to pair your ByteNite app with a Docker container image:

1. Build or choose a Docker image with all the necessary libraries and dependencies.

2. Develop your app’s logic outside the image—place your code in the app/ directory.

3. Upload your app using the ByteNite CLI, referencing your Docker image in the manifest file.

Hardware Requirements

At ByteNite, we handle the infrastructure so you can focus on building your apps—not worrying about hardware.

To ensure smooth performance, you’ll define your app’s minimum hardware requirements, like the number of CPU cores and memory size. This helps ByteNite allocate machines that meet (or exceed) these requirements, making sure your app runs reliably.

For example, for Stable Diffusion jobs:

  • Recommended minimum: 16 vCPUs and 32 GiB of RAM

  • More demanding pipelines (e.g., high-resolution outputs or larger models) may need 32+ vCPUs and 64 GiB of RAM

You set these requirements in the deviceRequirements field of your manifest.json.

Example:

manifest.json - hardware reqs example
{
  ...
  "device_requirements": {
    "min_cpu": 4,
    "min_memory": 8
  }
  ...
}
deviceRequirements object

Description:

Specifies the minimum hardware resources for the machines running your app..

Supported Properties:

  • min_cpu int Minimum number of vCPUs required.

  • min_memory int Minimum amount of RAM (in GiB) required.

Example:

{"min_cpu": 2, "min_memory": 2}


👨🏽‍💻 Develop the main script

The entry point script powers your app’s core functionality—it reads input chunks, processes data, and returns results.

What your script can do is nearly limitless. You can run model inferences, process large datasets, render video frames, generate PDFs in bulk, scrape the web. If it can run inside a container, it can run on ByteNite.

If needed, extend your entry point script by adding custom scripts or libraries to the app/ folder. These can be imported into your main script to support your logic.

The key requirement is how you handle inputs, parameters, and outputs. These must follow ByteNite’s conventions to ensure your workflow runs smoothly across distributed infrastructure.

How ByteNite Executes Your Script

  • ByteNite pulls the container image specified in your manifest.

  • It overrides the container’s original entry point and runs the ByteNite entry point script instead—your script inside the app/ folder.

This script must align with the programming language and libraries supported by your container image.

Make sure any external dependencies your code needs are installed in the container image. This ensures they’re available at runtime.

Important: Container Entrypoint ≠ ByteNite Entrypoint

When your app runs:

  • ByteNite launches the container based on your specified image.

  • Your container’s original entrypoint is overridden.

  • ByteNite runs its own entrypoint to execute the script inside the app/ folder.

This setup ensures your runtime environment stays flexible and modular—making it easier to iterate on your app’s logic without changing the container itself.

Default environment variables

Alongside your entry point script, ByteNite injects your container with environment variables. These variables provide paths to your app’s input and output folders, plus any job parameters.

Configuring your app’s data flow using these variables ensures your job runs smoothly and interacts properly with ByteNite’s components.

Here are the three preset ByteNite App environment variables:

TASK_DIR environment variable

Description:

Contains the path to the directory holding a single input data chunk. The chunk is stored in a file named data.bin.

  • This file holds the raw binary input data for your task, passed by the Partitioning Engine.

  • If you use a passthrough partitioner, data.bin is the original data source.

The directory is automatically created and contains only this one chunk—you don’t need to manage it manually. Just use this variable to access the input file.

Be sure to load and decode data.bin based on your app’s expected data type.

If your app doesn’t process input files, you can skip this step.

Usage (Python):

task_dir = os.getenv('TASK_DIR')
chunk_path = os.path.join(task_dir, 'data.bin')
TASK_RESULTS_DIR environment variable

Description:

This is the directory where your app should store processed results. Files saved here must be readable by the Assembling Engine.

  • The assembler collects these files across all runs of your app.

  • For passthrough assemblers, any file saved here is directly uploaded to the job’s data destination.

The folder is automatically created inside your app's environment. There’s no required output format—just make sure the assembler can access the files.

Usage (Python):

task_results_dir = os.getenv('TASK_RESULTS_DIR')
APP_PARAMS environment variable

Description:

This variable provides your app with parameters passed through a job. It contains a dictionary based on the data provided in the Create Job request (under params -> app).

These parameters let you adjust your app’s behavior per job.

For example, a parameter like "case" could control output string formatting, or a parameter "prompt" might contain a text prompt for a stable diffusion pipeline.

Usage (Python):

app_params = json.loads(os.getenv('APP_PARAMS'))

Example: Python entry point script

Here’s an example of a Python-based entry point script (main.py) that uses the environment variables we just covered.

# === BYTENITE APP - MAIN SCRIPT ===

# Documentation: https://docs.bytenite.com/create-with-bytenite/building-blocks/apps

# == Imports and Environment Variables ==

try:
    import json
    import os
except ImportError as e:
    raise ImportError(f"Required library is missing: {e}")

# Path to the directory containing a single data chunk, passed by your partitioner.
# Note: This folder is automatically created and contains only one chunk. You don't need to create or manage it.
task_dir = os.getenv('TASK_DIR')
if not task_dir:
    raise ValueError("TASK_DIR environment variable is not set or is invalid.")
chunk_path = os.path.join(task_dir, 'data.bin')

# Path to the folder where your app's task results must be saved. The assembler will access these files across all runs of your app.
# Note: The folder is automatically created and passed to your app. There is no required output format—just ensure your assembler can read the files.
task_results_dir = os.getenv('TASK_RESULTS_DIR')
if not task_results_dir:
    raise ValueError("TASK_RESULTS_DIR environment variable is not set or is invalid.")

# App parameters imported from the job request (located under "params" -> "app").
app_params_raw = os.getenv('APP_PARAMS')
if not app_params_raw:
    raise ValueError("APP_PARAMS environment variable is not set or is empty.")
try:
    app_params = json.loads(app_params_raw)
except json.JSONDecodeError as e:
    raise ValueError(f"APP_PARAMS environment variable contains invalid JSON: {e}")


if __name__ == '__main__':
    print("Python task started")
    result_path = os.path.join(task_results_dir, 'processed_chunk.txt')
    try:
        # --------------
        # 1. Reading Inputs
    
        # Example: Expect a text file to be passed by the partitioner
        with open(chunk_path, 'r', encoding="utf-8") as infile:
            my_string = infile.read()

        # --------------
        # 2. Handling Parameters
        
        # Example: Expect the job parameters to have a key named 'case', and the options to be "upper", "lower", and "title"
        case = app_params['case']

        # --------------
        # 3. Developing the Core Functionality
        
        # Example: Process the string based on the case parameter
        if case == "upper":
            my_string = my_string.upper()
        elif case == "lower":
            my_string = my_string.lower()
        elif case == "title":
            my_string = my_string.title()
        else:
            my_string = my_string
        
        # --------------
        # 4. Saving Outputs

        # Example: Save the string directly into a text file to the default task results directory
        with open(os.path.join(task_results_dir, "hello_world_processed.txt"), 'w', encoding="utf-8") as outfile:
            outfile.write(my_string)

    except Exception as e:
        print("Python exception: ", e)
        raise e


☑️ (Optional) Require Parameter Validation: schema.json

If your app receives parameters, validating them ahead of time ensures they follow a defined structure. This helps prevent issues like missing keys or malformed data.

You can define a JSON Schema in the schema.json file inside your app directory.

Any input parameters submitted to the Jobs API will be checked against this schema before the job starts.

Example Schema

Here’s an example of a schema that requires a single input string (prompt) with a maximum length of 50 characters:

schema.json
{
  "$id": "db://image-generation-simple-inputs",
  "definitions": {
    "input": {
      "type": "string",
      "description": "A prompt for image generation",
      "maxLength": 50
    }
  },
  "properties": {
    "prompt": {
      "$ref": "#/definitions/input"
    }
  },
  "required": ["prompt"],
  "title": "Stable Diffusion App Schema"
}

Why Use a Schema?

  • Prevents errors:

    Ensures parameters meet your expected format before the job runs.

  • Generates UI:

    The schema automatically creates a graphical interface in your Job Launch console, making it easy for you (or your users) to configure and launch jobs from the UI.


💡 App Development Tips

To get the most out of your ByteNite apps, keep the following principles in mind:

  • Your app code is executed by distributed task runners. Each task runs independently on a worker machine, based on how your data is partitioned. → Only include the logic that should run on a single worker—ByteNite handles all task distribution and resource orchestration for you.

  • Within each worker, your app can take advantage of multi-core architectures. You’re free to parallelize work across available CPU cores using threads or multiprocessing.

  • Avoid implementing custom distributed systems logic. ByteNite’s platform is designed to manage scaling, scheduling, and fault tolerance for you.

  • Ensure your data sources are properly configured via the Customer API (see Data Sources). Custom data ingestion or export logic within your app can lead to errors, inefficient performance, or increased container runtime—and ultimately, higher costs.

  • Incorporate robust error handling and logging. This is essential for monitoring, debugging, and improving the reliability of your app in production.

In summary:

✅ Do’s

  • Define the core functionality of your app.

  • Use multiple CPU cores to process subtasks in parallel within a single worker.

❌ Don’ts

  • Distribute tasks to other workers or machines. → Your app already runs within ByteNite’s distributed environment.

  • Read from or write to additional data sources directly. → Input/output is managed by ByteNite’s Partitioning and Assembling Engines.

⚠️ Use with Caution

  • Interact with external services or APIs only when necessary, and only if the required functionality cannot be handled by ByteNite’s Data Engines or built-in integrations.

PreviousBuilding BlocksNextJob Templates

Last updated 11 days ago

Was this helpful?

ByteNite supports containerized workloads by integrating with Docker images from . Docker lets you package your app’s dependencies, libraries, and runtime into a single, portable container—so your app runs consistently across environments.

container string A Docker container image reference. Refer to the official to choose the right base image for your app. Examples:

token string Your for authenticating image pull requests (only required if private_image is true).

See: for common serverless job examples.

Docker Hub
Docker documentation
Docker Hub Personal Access Token (PAT)
Examples of core processing use cases