# Folder structure

> Where everything goes in an App created from the skeleton starter kit, and how its packages depend on each other.

This guide covers the folder structure of an App created from the skeleton starter kit. You will learn:

- What each top-level directory holds
- How `main.go` and `start` assemble the App
- Where your own code goes as the App grows
- Which package may import which

## Overview

The skeleton gives every App the same shape, so you, your team, the docs and [generators](guides/concepts/scaffolding.md) such as `act make:handler` all know where things go. Every directory is a Go package, imported by the App's module path, such as `blog/start`.

```text
blog/
├── app/
│   ├── exceptions/
│   └── handlers/
├── config/
├── start/
├── tests/
│   └── functional/
├── main.go
├── go.mod
├── .env.example
└── .env.test
```

The core starter kit has none of this: a single `main.go`, to structure as you choose.

## main.go

`main.go` is the App's entry point. It reads the configuration with `config.Load`, builds the App with `start.App`, and hands it the command line:

```go title="main.go"
package main

import (
	"fmt"
	"os"

	"blog/config"
	"blog/start"
)

func main() {
	cfg, err := config.Load()
	if err != nil {
		fmt.Fprintln(os.Stderr, err) // every missing or invalid variable, at once
		os.Exit(1)
	}
	app, err := start.App(cfg)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	os.Exit(app.Main(os.Args[1:]))
}
```

One binary does everything: with no arguments it serves requests, and with arguments it runs one of the App's [Commands](guides/command-line/introduction.md), such as `./blog about`. `act` runs the same binary for you during development.

## start

`start` assembles the App, in three files:

::::options

:::option{name="start/app.go" type="file"}
`App` creates the App and its services from the configuration, and adds the middleware and routes. `main` runs the App it returns, and tests build it the same way, with a configuration of their own.
:::

:::option{name="start/kernel.go" type="file"}
`Kernel` adds the middleware every request passes through, in order.
:::

:::option{name="start/routes.go" type="file"}
`Routes` registers the App's routes. It runs when the App starts.
:::

::::

## app

`app` holds your code, in a package for each kind: `app/handlers` for [handlers](guides/basics/routing.md), `app/middleware` for [middleware](guides/basics/middleware.md), `app/providers` for [service providers](guides/concepts/service-providers.md), `app/commands` for [Commands](guides/command-line/commands.md), and `app/exceptions`, whose `Handler` decides how errors reach clients. A new App has `handlers` and `exceptions`; the others appear as you add to them.

## config

`config` reads the App's configuration from the environment, once, at boot, into typed structs: `config/app.go` for the App's URL and key, `config/http.go` for the HTTP server, `config/logger.go` for logging. `config.Load` reports every missing or invalid variable together, so a misconfigured App stops at boot. See [Configuration & Environment](configuration.md).

`.env.example` lists the variables the App reads, without their values. `.env`, which `tinka new` creates with a fresh `APP_KEY`, holds your machine's values and stays out of git. `.env.test` holds the values tests use, and is committed.

## tests

`tests` holds what tests share. `tests.App` builds the App as `main` does, in the `test` Mode, with a fast password hasher and its logs in the test's output, without starting it: [`tinkatest`](guides/testing/http-tests.md) starts it. HTTP tests that exercise the whole App go in `tests/functional`:

```go title="tests/functional/home_test.go"
package functional_test

import (
	"net/http"
	"testing"

	"github.com/mucolabs/tinka/tinkatest"

	"blog/tests"
)

func TestHome(t *testing.T) {
	t.Parallel()
	c := tinkatest.New(t, tests.App(t))
	c.Get("/").Send(t).
		AssertStatus(http.StatusOK).
		AssertJSON(map[string]string{"hello": "world"})
}
```

Tests of a single package go next to it, as Go tests do, such as `app/handlers/home_test.go`. Run them all with [`act test`](guides/testing/introduction.md).

## Which package imports which

Go refuses two packages that import each other, so the skeleton's packages depend in one direction:

- `main` imports `start`.
- `start` imports `config` and `app/...`.
- `app/...` packages import Tinka, and each other where one builds on another, but never `start` or `main`.

A handler that needs a service gets it from the App's [container](guides/concepts/dependency-injection.md), with `c.Make`, rather than importing the package that creates it. That keeps every dependency pointing toward `start`, where the App is assembled.

See also: [Installation](installation.md), [Configuration & Environment](configuration.md), [Application lifecycle](guides/concepts/application-lifecycle.md)
