Note that before getting started with TFW you should already know how to create simpler Avatao challenges.
To learn about Avatao challenge creation in general please consult the [challenge-toolbox](https://github.com/avatao-content/challenge-toolbox) repository.
To learn the stuff you need to know about TFW in order to get started you should consult the [baseimage-tutorial-framework](https://github.com/avatao-content/baseimage-tutorial-framework) repo first.
Our magical bash script `hack/tfw.sh` can handle everything for you. Just run it without any arguments to see usage information.
It is advisable to run the frontend locally while developing to avoid really looooong build times. The `hack/tfw.sh` script handles this for you automagically.
This will create a Docker image without the frontend, which you can run locally. For procudtion builds exclude the argument `--build-arg NOFRONTEND=1` to include a frontend instance.
In case of a build without frontend (built with `--build-arg NOFRONTEND=1` included) you will need to run `yarn start` from the `solvable/frontend` directory as well.
This will serve the frontend locally on `http://localhost:4200` and take care of proxying.
If you've created a production build (without `--build-arg NOFRONTEND=1`) you don't have to run the frontend locally and you can access the challenge on `http://localhost:8888`.
### Building the TFW baseimage without test-tutorial-framework
You might need to build our baseimage separately in case you've cloned an existing challenge depending on a specific version.
To do this simply issue `BASEIMAGE_ONLY=version bash -c "$(curl -fsSL https://git.io/vxBfj)"`, where `version` is a tag or commit of the [baseimage-tutorial-framework](https://github.com/avatao-content/baseimage-tutorial-framework) repository.
The only notable difference is that the `solvable` Docker image is a child of our baseimage: `solvable/Dockerfile` begins with `FROM eu.gcr.io/avatao-challengestore/tutorial-framework`.
Note that our baseimage *requires* the `nginx`, `supervisor` and `frontend` folders to be in these **exact** locations and to be used as described below.
It is very important to understand that from now on your application must behave well behind a reverse proxy.
What this means is all `href`s must point the proxied paths (e.g. links should refer to `/yoururl/register` instead of `/register`) on your HTML pages.
You can learn about configuring nginx in [this](https://www.digitalocean.com/community/tutorials/understanding-the-nginx-configuration-file-structure-and-configuration-contexts) handy little tutorial.
The programs, you define this way, are easy to manage (starting/stopping/restarting) using the `supervisorctl` command line tool or our built-in event handler.
This starts the `/home/user/example/server.py` script using `python3` after your container entered the running state (because of `autostart=true`, supervisor does not start programs by default).
A good state machine is the backbone of a good TFW challenge.
There are two ways to define a state machine:
- Using a YAML configuration file
- Implementing it in Python by hand
The first option enables you to handle FSM callbacks and custom logic in any programming language (not just Python) and is generally really easy to work with.
You should choose this method unless you have good reason not to.
This involves creating your YAML file (see `test_fsm.yml` for an example) and parsing it using our `YamlFSM` class (see `event_handler_main.py` for an example).
The second option allows you to implement your FSM in Python, using the transitions library.
To do this just subclass our `FSMBase` class or use our `LinearFSM` class for simple machines (see `test_fsm.py` for an example).
In your FSM you can define callbacks for states and transitions.