Skip to content

AlgoKit Templates

Using a Custom AlgoKit Template

To initialize a community AlgoKit template, you can either provide a URL to the community template during the interactive wizard or by passing in --template-url to algokit init. For example:

Terminal window
algokit init --template-url https://github.com/algorandfoundation/algokit-python-template
# This is the url of the official Python template. Replace with the community template URL.
# or
algokit init # and select the Custom Template option

When you select the Custom Template option during the interactive wizard, you will be prompted to provide the URL of the custom template.

Terminal window
Community templates have not been reviewed, and can execute arbitrary code.
Please inspect the template repository, and pay particular attention to the values of _tasks, _migrations and _jinja_extensions in copier.yml
Enter a custom project URL, or leave blank and press enter to go back to official template selection.
Note that you can use gh: as a shorthand for github.com and likewise gl: for gitlab.com
Valid examples:
- gh:copier-org/copier
- gl:copier-org/copier
- [email protected]:copier-org/copier.git
- git+https://mywebsiteisagitrepo.example.com/
- /local/path/to/git/repo
- /local/path/to/git/bundle/file.bundle
- ~/path/to/git/repo
- ~/path/to/git/repo.bundle
? Custom template URL: # Enter the URL of the custom template here

The --template-url option can be combined with --template-url-ref to specify a specific commit, branch or tag. For example:

Terminal window
algokit init --template-url https://github.com/algorandfoundation/algokit-python-templat --template-url-ref 9985005b7389c90c6afed685d75bb8e7608b2a96

If the URL is not an official template there is a potential security risk and so to continue you must either acknowledge this prompt, or if you are in a non-interactive environment you can pass the --UNSAFE-SECURITY-accept-template-url option (but we generally don’t recommend this option so users can review the warning message first) e.g.

Terminal window
Community templates have not been reviewed, and can execute arbitrary code.
Please inspect the template repository, and pay particular attention to the values of \_tasks, \_migrations and \_jinja_extensions in copier.yml
? Continue anyway? Yes

Creating Custom AlgoKit Templates

If the official templates do not serve your needs, you can create custom AlgoKit templates tailored to your project requirements or industry needs. These custom templates can be used for your future projects or contributed to the Algorand developer community, enhancing the ecosystem with specialized solutions.

Creating templates in AlgoKit involves using various configuration files and a templating engine to generate project structures tailored to your needs. This guide will cover the key concepts and best practices for creating templates in AlgoKit. We will also refer to the official algokit-python-template as an example.

Quick Start

For users who are keen on getting started with creating AlgoKit templates, you can follow these quick steps:

  1. Click on Use this template->Create a new repository on algokit-python-template Github page. This will create a new reference repository with clean git history, allowing you to modify and transform the base Python template into your custom template.
  2. Modify the cloned template according to your specific needs. The remainder of this tutorial will help you understand expected behaviors from the AlgoKit side, Copier, the templating framework, and key concepts related to the default files you will encounter in the reference template.

Overview of AlgoKit Templates

AlgoKit templates are project scaffolds that can initialize new smart contract projects. These templates can include code files, configuration files, and scripts. AlgoKit uses Copier and the Jinja templating engine to create new projects based on these templates.

Copier/Jinja

AlgoKit uses Copier templates. Copier is a library that allows you to create project templates that can be easily replicated and customized. It’s often used along with Jinja. Jinja is a modern and designer-friendly templating engine for Python programming language. It’s used in Copier templates to substitute variables in files and file names. You can find more information in the Copier documentation and Jinja documentation.

AlgoKit Functionality with Templates

AlgoKit provides the algokit init command to initialize a new project using a template. You can pass the template name using the -t flag or select a template from a list.

Key Concepts

.algokit.toml

This file is the AlgoKit configuration file for this project, and it can be used to specify the minimum version of the AlgoKit. This is essential to ensure that projects created with your template are always compatible with the version of AlgoKit they are using.

Example from algokit-python-template:

[algokit]
min_version = "v1.1.0-beta.4"

This specifies that the template requires at least version v1.1.0-beta.4 of AlgoKit.

Python Support: pyproject.toml

Python projects in AlgoKit can leverage various tools for dependency management and project configuration. While Poetry and the pyproject.toml file are common choices, they are not the only options. If you opt to use Poetry, you’ll rely on the pyproject.toml file to define the project’s metadata and dependencies. This configuration file can utilize the Jinja templating syntax for customization.

Example snippet from algokit-python-template:

[tool.poetry]
name = "{{ project_name }}"
version = "0.1.0"
description = "Algorand smart contracts"
authors = ["{{ author_name }} <{{ author_email }}>"]
readme = "README.md"
...

This example shows how project metadata and dependencies are defined in pyproject.toml, using Jinja syntax to allow placeholders for project metadata.

TypeScript Support: package.json

For TypeScript projects, the package.json file plays a similar role as pyproject.toml can do for Python projects. It specifies metadata about the project and lists the dependencies required for smart contract development.

Example snippet:

{
"name": "{{ project_name }}",
"version": "1.0.0",
"description": "{{ project_description }}",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"typescript": "^4.2.4",
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0"
}
}

This example shows how Jinja syntax is used within package.json to allow placeholders for project metadata and dependencies.

Bootstrap Option

When instantiating your template via AlgoKit CLI, it will optionally prompt the user to automatically run algokit bootstrap after the project is initialized and can perform various setup tasks like installing dependencies or setting up databases.

  • env: Searches for and copies a .env*.template file to an equivalent .env* file in the current working directory, prompting for any unspecified values. This feature is integral for securely managing environment variables, preventing sensitive data from inadvertently ending up in version control. By default, Algokit will scan for network-prefixed .env variables (e.g., .env.localnet), which can be particularly useful when relying on the Algokit deploy command. If no such prefixed files are located, Algokit will then attempt to load default .env files. This functionality provides greater flexibility for different network configurations.

  • poetry: If your Python project uses Poetry for dependency management, the poetry command installs Poetry (if not present) and runs poetry install in the current working directory to install Python dependencies.

  • npm: If you’re developing a JavaScript or TypeScript project, the npm command runs npm install in the current working directory to install Node.js dependencies.

  • all: The all command runs all the aforementioned bootstrap sub-commands in the current directory and its subdirectories. This command is a comprehensive way to ensure all project dependencies and environment variables are correctly set up.

Predefined Copier Answers

Copier can prompt the user for input when initializing a new project, which is then passed to the template as variables. This is useful for customizing the new project based on user input.

Example:

copier.yaml
project_name:
type: str
help: What is the name of this project?
placeholder: 'algorand-app'

This would prompt the user for the project name, and the input can then be used in the template using the Jinja syntax {{ project_name }}.

Default Behaviors

When creating an AlgoKit template, there are a few default behaviors that you can expect to be provided by algokit-cli itself without introducing any extra code to your templates:

  • Git: If Git is installed on the user’s system and the user’s working directory is a Git repository, AlgoKit CLI will commit the newly created project as a new commit in the repository. This feature helps to maintain a clean version history for the project. If you wish to add a specific commit message for this action, you can specify a commit_message in the _commit option in your copier.yaml file.

  • VSCode: If the user has Visual Studio Code (VSCode) installed and the path to VSCode is added to their system’s PATH, AlgoKit CLI will automatically open the newly created VSCode window unless the user provides specific flags into the init command.

  • Bootstrap: AlgoKit CLI is equipped to execute a bootstrap script after a project has been initialized. This script, included in AlgoKit templates, can be automatically run to perform various setup tasks, such as installing dependencies or setting up databases. This is managed by AlgoKit CLI and not within the user-created codebase. By default, if a bootstrap task is defined in the copier.yaml, AlgoKit CLI will execute it unless the user opts out during the prompt.

By combining predefined Copier answers with these default behaviors, you can create a smooth, efficient, and intuitive initialization experience for the users of your template.

Executing Python Tasks in Templates

If you need to use Python scripts as tasks within your Copier templates, ensure that you have Python installed on the host machine. By convention, AlgoKit automatically detects the Python installation on your machine and fills in the python_path variable accordingly. This process ensures that any Python scripts included as tasks within your Copier templates will execute using the system’s Python interpreter. It’s important to note that the use of _copier_python is not recommended. Here’s an example of specifying a Python script execution in your copier.yaml without needing to explicitly use _copier_python:

- '{{ python_path }} your_python_script.py'

If you’d like your template to be backwards compatible with versions of algokit-cli older than v1.11.3 when executing custom python scripts via copier tasks, you can use a conditional statement to determine the Python path:

- '{{ python_path if python_path else _copier_python }} your_python_script.py'
# _copier_python above is used for backwards compatibility with versions < v1.11.3 of the algokit cli

And to define python_path in your Copier questions:

# Auto determined by algokit-cli from v1.11.3 to allow execution of python script
# in binary mode.
python_path:
type: str
help: Path to the sys.executable.
when: false

Working with Generators

After mastering the use of copier and building your templates based on the official AlgoKit template repositories, you can enhance your proficiency by learning to define custom generators. Essentially, generators are smaller-scope copier templates designed to provide additional functionality after a project has been initialized from the template.

For example, the official algokit-python-template incorporates a generator in the .algokit/generators directory. This generator can be utilized to execute auxiliary tasks on AlgoKit projects that are initiated from this template, like adding new smart contracts to an existing project. For a comprehensive understanding, please consult the architecture decision record and algokit generate documentation.

How to Create a Generator

Outlined below are the fundamental steps to create a generator. Although copier provides complete autonomy in structuring your template, you may prefer to define your generator to meet your specific needs. Nevertheless, as a starting point, we suggest:

  1. Generate a new directory hierarchy within your template directory under the .algokit/generators folder (this is merely a suggestion; you can define your custom path if necessary and point to it via the algokit.toml file).
  2. Develop a copier.yaml file within the generator directory and outline the generator’s behavior. This file bears similarities with the root copier.yaml file in your template directory, but it is exclusively for the generator. The tasks section of the copier.yaml file is where you can determine the generator’s behavior. Here’s an example of a generator that copies the smart-contract directory from the template to the current working directory:
_task:
- "echo '==== Successfully initialized new smart contract 🚀 ===='"
contract_name:
type: str
help: Name of your new contract.
placeholder: 'my-new-contract'
default: 'my-new-contract'
_templates_suffix: '.j2'

Note that _templates_suffix must be different from the _templates_suffix defined in the root copier.yaml file. This is because the generator’s copier.yaml file is processed separately from the root copier.yaml file.

  1. Develop your generator copier content and, when ready, test it by initiating a new project for your template and executing the generator command:
algokit generate

This should dynamically load and display your generator as an optional cli command that your template users can execute.

Recommendations

  • Modularity: Break your templates into modular components that can be combined in different ways.
  • Documentation: Include README files and comments in your templates to explain how they should be used.
  • Versioning: Use .algokit.toml to specify the minimum compatible version of AlgoKit.
  • Testing: Include test configurations and scripts in your templates to encourage testing best practices.
  • Linting and Formatting: Integrate linters and code formatters in your templates to ensure code quality.
  • Algokit Principle: for details on generic principles for designing templates, refer to algokit design principles.

Conclusion

Creating custom templates in AlgoKit is a powerful way to streamline your development workflow for Algorand smart contracts using Python or TypeScript. Leveraging Copier and Jinja for templating and incorporating best practices for modularity, documentation, and coding standards can result in robust, flexible, and user-friendly templates that can be valuable to your projects and the broader Algorand community.

Happy coding!