defmodule Orbit do
@moduledoc """
A simple framework for a simple protocol.
Orbit is a framework for building [Gemini](https://geminiprotocol.net/) applications, known as "capsules".
This framework focuses primarily on the Gemini protocol itself, intent on getting a request into your application,
handling it, and sending a Gemtext response.
It doesn't make any assumptions about your business logic, backing database, migrations, or anything like that.
If you need a database, you can add it manually ([see below](#module-adding-a-database)).
## Concepts
Orbit borrows a lot of ideas from Plug and Phoenix.
- `Orbit.Endpoint` - the TLS server that accepts incoming requests (`Phoenix.Endpoint` + `cowboy`)
- `Orbit.Request` - encapsulates the request-response lifecyle (`Plug.Conn`)
- `Orbit.Pipe` - the behaviour for request middleware (`Plug`)
- `Orbit.Router` - defines pipelines and routes (`Phoenix.Router`)
- `Orbit.Controller` - processes requests (`Phoenix.Controller`)
- `Orbit.Gemtext` - renders Gemtext templates (`Phoenix.Component`)
Some additional niceties:
- `Orbit.Static` - serves up files from `priv/statc` (`Plug.Static`)
- `Orbit.Status` - a canonical list of all status codes
- `Orbit.ClientCertificate` - extracts client certificates from the request
## Conventions
A basic Orbit application is structured as follows.
- `MyApp` - the main application business logic
- `MyAppCapsule` - the namespace for the Gemini app
- `MyAppCapsule.Endpoint` - the combined TLS server and router
- `MyAppCapsule.LayoutGmi` - layout templates
- `MyAppCapsule.PageController` - a basic controller
- `MyAppCapsule.PageGmi` - templates for that controller
## Quickstart
Orbit does not have a fancy project generator like `mix phx.new`. Instead, you add the dependency to a new
(or existing!) application, and then run `mix orbit.init` to get started.
Create a new application:
$ mix new my_app --sup
Add the dependency:
# mix.exs
def deps do
[
{:orbit, "~> #{Orbit.MixProject.project()[:version]}"}
]
end
Generate some files (don't worry, existing files won't be modified):
$ mix deps.get
$ mix orbit.init my_app MyAppCapsule
Follow the instructions from the task's output.
Finally, start the application and visit `gemini://localhost/`
## Adding a Database
This example for setting up Postgres was cribbed from the [Ecto](https://hexdocs.pm/ecto/Ecto.html) docs. You might
prefer [SQLite](https://hexdocs.pm/ecto_sqlite3/Ecto.Adapters.SQLite3.html) as an alternative.
Add the dependencies:
# mix.exs
def deps do
[
# Check hex.pm for the latest versions!
{:ecto, "~> 3.11.2"},
{:ecto_sql, "~> 3.11.1"},
{:postgrex, "~> 0.17.5"}
]
end
Add some config:
# config/config.exs
config :my_app, ecto_repos: [MyApp.Repo]
# config/runtime.exs
config :my_app, MyApp.Repo, url: System.fetch_env!("DATABASE_URL")
Create the repo module:
# lib/my_app/repo.ex
defmodule MyApp.Repo do
use Ecto.Repo,
otp_app: :my_app,
adapter: Ecto.Adapters.Postgres
end
Add the repo to the supervision tree:
# lib/application.ex
children = [
MyApp.Repo
]
Finally, create the DB.
$ mix ecto.create
Migrations can be generated with `mix ecto.gen.migration`, and schemas are written by hand.
"""
end