Skip to main content

Develop contract initialization frontend templates

This guide picks up where Build a Dapp Frontend left off, taking a deeper look at the --frontend-template used there. From there, we'll:

  1. Search GitHub for other Soroban templates
  2. Build our own simple template

Building our own template will be a great way to learn how they work. They're not that complicated!

Search GitHub for other Soroban templates​

The official template maintained by Stellar Development Foundation (SDF), as used in Build a Dapp Frontend, lives on GitHub at stellar/soroban-template-astro. It uses the Astro web framework. While Astro works with React, Vue, Svelte, and any other UI library, the template opts not to use them, preferring Astro's own templating language, which uses vanilla JavaScript with no UI library.

(You may wonder why it makes this unpopular choice. A fair question! The team wanted to balance actual utility with broad approachability. Not everyone learning Stellar and Soroban is familiar with React, or any other UI library. It also demonstrates that core Soroban libraries all work with any JavaScript project.)

But note that the CLI's contract init command was made to work with any frontend template. It need not even live on GitHub! Simply pass another valid git URL to the command, and it will clone that instead of the official repository:

# the following is NOT a valid git repository, and will not work πŸ˜„
stellar contract init my-new-project --frontend-template https://whatever.cool/project/you/want

So how can you find other valid frontend templates?

At some point we may set up a DAO or other voting system to curate a list of high-quality templates, but for now... search GitHub! And GitLab. And any other source code site you know about.

In GitHub, in the main search bar, search for "soroban-template-". With the quotes. Here's a direct link to the search results: github.com/search?q=%22soroban-template-%22

You can copy this approach for any other source code website, such as GitLab.

How do you know if any of these are any good? Try them. Look at their source code. How many stars do they have? How active are their maintainers? None of these are perfect metrics, which is why a curated registry might be nice in the future.

If none of them suit, then it might be time to...

Make your own template​

This will be easier than you might imagine. There are a few gotchas, but overall these templates are fairly standard Node projects.

But first, how are these projects organized?​

When you run stellar contract init, it always includes a Rust/Cargo project, with a Cargo.toml that defines a workspace, and workspace members located in a contracts folder. At a minimum, there's one contract, contracts/hello_world, but you can get more by using --with-example.

Separately, you may include a --frontend-template. Frontend templates so far have all been Node projects, which have a package.json in the root. In the final composite project, the Node project and Rust project live side-by-side, and the frontend template expects the Rust project to be there. It expects a contracts folder with one or more subfolders, and it expects a target directory with all the Rust build artifacts.

So keep that in mind. We're making a fairly simple Node project, and telling it about our Soroban stuff, like the contracts folder.

1. Initialize an NPM project​

So let's make a simple Node project! Rather than initializing an Astro project, like the official frontend template, let's try something new. The State of JS survey tells me that something called "Solid" is fairly new and well-loved. What does it say to do?

npx degit solidjs/templates/ts soroban-template-solid
cd soroban-template-solid
npm install
npm run dev

Ok, we have a running Solid template! Now let's turn it into a Soroban template!

2. git init​

Commit early, commit often! You can stop running the dev server (the one you started with npm run dev above; stop it with ctrlc, even on a Mac) if you want, or open a new terminal and:

git init
git add .
git commit -m "init from solid ts template"

3. Copy in the initialize.js script​

The SDF-maintained soroban-template-astro has an initialize.js script in its project root. Copy-paste it into your project.

If you're familiar with Node scripting, you should be able to figure out what it's doing. If not, it's a great way to learn! Tip: start at the bottom, where it does the generateAccount(); buildAll(); deployAll(); stuff.

That stuff at the end should give you a clue about what this script does. It does stuff that a Soroban app needs. Soroban apps make calls to Soroban.

So this script:

  1. generates a Soroban/Stellar account
  2. builds all contracts
  3. deploys all contracts (to a locally-running Soroban network; we'll recap this soon)
  4. binds contracts β€”Β that is, it creates NPM projects for each deployed contract by running stellar contract bindings typescript
  5. imports the contracts for straightforward use in the rest of your project

Remember that it needs to do this all in a contract-agnostic way. That is, the --frontend-template choice is separate from the --with-example choice. The frontend template doesn't know what contracts it might find! But it needs to build, deploy, bind, and import whatever's there.

So this script does that.

But it needs a few other things.

A. devDependencies​

The script uses a couple NPM packages. Install them:

npm install --save-dev dotenv glob

B. .env​

The dotenv package installed above parses environment variables from a .env file. The official template includes a .env.example. Go ahead and copy it into your own project. To set you up for testing it all out, you can also copy it to a local .env.

cp .env.example .env

C. .gitignore​

You'll want to ignore the .env file you created above, as well as some other build artifacts created by the initialize.js script. Paste the bottom of the official template's .gitignore into your template's .gitignore:

# environment variables
.env
.env.production

# generated contract clients
packages/*
# if you have other workspace packages, add them here
!packages/.gitkeep

# generated contract client imports
src/contracts/*
!src/contracts/util.ts

C. package.json​

Make sure users of your template don't forget to run the initialize.js script. Modify the scripts section as follows:

-    "start": "vite",
- "dev": "vite",
- "build": "vite build",
- "serve": "vite preview"
+ "init": "node initialize.js",
+ "start": "npm run init && vite",
+ "dev": "npm run init && vite",
+ "build": "npm run init && vite build",
+ "serve": "npm run init && vite preview"

Alternatively, rather than adding the repetitive npm run init statements, you could opt to add a postinstall script where you npm run init, or just node initialize.js in there.

You also need to tell NPM to treat this as a workspace. Yes, this project is a Cargo workspace and an NPM workspace! The bindAll step of initialize.js puts the generated NPM packages in packages/*. At the bottom of package.json, add:

   "dependencies": {
"solid-js": "^1.8.11"
- }
+ },
+ "workspaces": [
+ "packages/*"
+ ]
}

Also make sure that this project is set up to allow the import statements in the initialize.js script. Add this at the top-level:

   "description": "",
+ "type": "module",
"scripts": {

While you're here, you can also update the name (maybe "soroban-template-solid") and description.

E. src/contracts/util.ts​

In the .gitignore above, you may have noticed that this file is explicitly included. Copy it in from the official template. You'll need to create the src/contracts folder.

As you can see, it just makes it easy to import { rpcUrl, networkPassphrase } from 'util' in the files generated in the importAll step.

F. README​

You might want to start by copying the official template's README to explain how to cp .env.example .env. From there, this might also be a good time to explain anything else that makes your template unique! Why might people want to use it?

4. git commit​

Commit changes!

git add .
git commit -m "add initialize.js script and supporting changes"

5. Try it!​

That's it! You have an NPM project with an initialize.js script (and its supporting cast). That's all you really need!

To try it, soon we will run stellar contract init . in this project to add the Cargo stuff and a contracts folder. But be careful! You don't want to commit these changes! You can git restore . at the end of your testing to get rid of the new files.

Let's try it. First, make sure you're running a local Stellar network. Start Docker Desktop or whatever alternative you prefer, then:

stellar network container start local

Now we can run contract init. Let's include one extra contract. Then we'll run the dev script (which, remember, will run the initialize.js script first):

stellar contract init . --with-example increment
npm run dev

After you do this, you may notice lots of new changes in the project. All that Rust, Cargo, and Soroban stuff!

$ git status --short

?? .soroban/
?? Cargo.lock
?? Cargo.toml
?? contracts/
?? target/

Q: Should you commit this stuff?
A: NO!

Q: Should you gitignore this stuff?
A: NO!

The .soroban and target folders are gitignored by the core Rust/Cargo template. In projects that specify yours as their --frontend-template, that .gitignore will be merged with yours. No need to include those lines twice.

And projects that use yours will want to commit the Cargo.* files and contracts, but your template should not include them. That can cause problems with project initialization later. Nor should it gitignore them, because your .gitignore will be part of projects started with your template! It would cause problems and confusion, if people didn't realize that some of their most important files were gitignored!

Alright. Go ahead and open the app in your browser. Solid runs its dev server on http://localhost:3000. Does it load? It should! We didn't actually use the new src/contracts/* stuff in the app itself!

6. Wait. Should the template actually use the contracts?​

Good question!

You know that the hello_world contract will always be there. So you could demonstrate to your users how to import and use it in an app file (like src/App.tsx, in the Solid template). But remember: no other contracts are guaranteed to be there! So don't commit any changes that import and use something like increment!

Here's a way you could demonstrate how to import and use the hello_world contract in the Solid template's App.tsx:

+import greeter from "./contracts/hello_world";

const App: Component = () => {
return (
<div class={styles.App}>
<header class={styles.header}>
+ <form
+ onSubmit={async (e) => {
+ e.preventDefault();
+ const { result } = await greeter.hello({
+ to: e.currentTarget.toWhom.value,
+ });
+ alert(result);
+ }}
+ >
+ <label>
+ Who you gonna call? &nbsp;
+ <input name="toWhom" value="World" /> &nbsp;
+ </label>
+ <button type="submit">Say Hello</button>
+ </form>

7. Make it as complex as you want!​

This is your template. Go ahead and add helpful dependencies and utility files that you always want, like wallet management or whatever. If you want to add a whole complex stack of UI components, styles, and state-management libraries, go ahead!

The official template strives for simplicity. For shallowness, even. It's meant as a teaching tool, for people with all different levels of JS and Soroban experience. Yours has no such constraints! It should be useful to you.

And templates are cheap to make! If you want to have one soroban-template-framework-x-basic for a broader audience, and another soroban-template-framework-x-opinionated for your own projects, you can do that!

Wrapping up​

Some things we did in this section:

  • Searched GitHub for new frontend templates
  • Learned that some templates might not be on GitHub
  • Saw how frontend templates work and interact with the "backend" template that always comes with stellar contract init
  • Built our own template by adding an initialize.js script to a basic NPM template

After you're done building your own frontend template, what's next? You choose! You can: