Help us shape the future of Go! Take the 2026 Go Developer Survey

skywalker

package module
v0.0.0-...-5bbce0e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 48 Imported by: 0

README

Skywalker

CI

Skywalker is a batteries-included web framework for Go — an open re-implementation in the lineage of the "Celeritas" course framework. It wires together routing, rendering, sessions, caching, mail, a database + migration layer, pluggable remote filesystems, and a code-generating CLI, so you can start building instead of assembling boilerplate.

One App.New() call reads your .env, creates the project layout, and boots every subsystem.

func main() {
    sky := &skywalker.Skywalker{}
    if err := sky.New(rootPath); err != nil {
        log.Fatal(err)
    }
    sky.ListenAndServe()
}

Features

  • Routing & middleware — chi router, with CSRF (nosurf) and session middleware wired in.
  • Rendering — Jet templates (default) or Go html/template, selected by RENDERER.
  • Sessions — scs with cookie, Redis, MySQL, or Postgres stores.
  • Caching — Redis or Badger behind a single Cache interface.
  • Mail — a queued mailer over channels; SMTP or an API service (Mailgun / SendGrid / SparkPost).
  • Database & migrations — Postgres (pgx) or MySQL, with golang-migrate.
  • Remote filesystems — one FS interface with four real backends: MinIO, S3, SFTP, WebDAV.
  • Extras — authenticated AES-GCM encryption, HMAC-signed URLs, structured logging (slog: text in debug, JSON in production), a cron scheduler, and JSON/XML response helpers.
  • CLI — scaffolds new apps, models, handlers, migrations, auth, sessions, and mail templates.

Requirements

  • Go 1.25+ (both this module and generated apps build in module mode — no vendoring).
  • Optional, depending on which subsystems you enable: Postgres/MySQL, Redis, an SMTP server, and a MinIO/S3/SFTP/WebDAV endpoint.

Install the CLI

git clone https://github.com/stefanlester/Skywalker.git
cd Skywalker
go build -o skywalker ./cmd/cli      # Windows: -o skywalker.exe

Run ./skywalker help to see every command.

Create and run an app

./skywalker new myapp

This clones the skywalker_engine skeleton, generates a fresh .env (with a random 32-char encryption key), rewrites the module path, and runs go mod tidy. Then:

cd myapp
go run .                 # starts on the PORT set in .env (skeleton default: 4000)

Open http://localhost:4000. On first boot New() creates the standard folders: handlers, migrations, views, data, public, tmp, logs, middleware.

For the full guide — handlers, rendering, sessions, DB, cache, mail, filesystems, APIs — see docs/USAGE.md.

Configuration

Everything is driven by environment variables (loaded from .env). The common ones:

Variable Purpose
PORT, APP_URL, SERVER_NAME, SECURE HTTP server
DEBUG true puts Jet in development (re-parse) mode
RENDERER jet or go
DATABASE_TYPE + DATABASE_* postgres / mysql; empty = no DB
CACHE redis or badger; empty = no cache
SESSION_TYPE cookie, redis, mysql, or postgres
COOKIE_* session cookie name/lifetime/domain/secure
KEY AES key — must be exactly 32 characters
SMTP_* / MAILER_API,MAILER_KEY,MAILER_URL SMTP or API mail
MINIO_*, S3_*, SFTP_*, WEBDAV_* filesystem backends (see below)

An app boots with no external services using SESSION_TYPE=cookie, empty DATABASE_TYPE, and empty CACHE — handy for a first run.

Remote filesystems

All four backends implement one interface:

type FS interface {
    Put(fileName, folder string) error
    Get(destination string, items ...string) error
    List(prefix string) ([]Listing, error)
    Delete(itemsToDelete []string) bool
}

New() constructs each backend only if its gate variable is set — MINIO_SECRET, S3_SECRET, SFTP_HOST, WEBDAV_HOST — and stores it in App.FileSystems keyed by name ("MINIO", "S3", "SFTP", "WEBDAV"). Pick one at request time through the interface:

fs, ok := app.FileSystems[fsType].(filesystems.FS)   // fsType: "MINIO" | "S3" | "SFTP" | "WEBDAV"
if ok {
    files, _ := fs.List("/")
}
Backend Library Key env vars
MinIO (any S3-compatible store) minio-go MINIO_ENDPOINT, MINIO_KEY, MINIO_SECRET, MINIO_BUCKET, MINIO_USESSL, MINIO_REGION
S3 minio-go (S3-compatible) S3_ENDPOINT, S3_KEY, S3_SECRET, S3_REGION, S3_BUCKET
SFTP pkg/sftp SFTP_HOST, SFTP_USER, SFTP_PASS, SFTP_PORT
WebDAV studio-b12/gowebdav WEBDAV_HOST, WEBDAV_USER, WEBDAV_PASS

SFTP currently uses InsecureIgnoreHostKey; verify host keys via known_hosts before production use.

Note on MinIO: the MinIO server community edition is no longer maintained upstream (source-only, steered toward commercial AIStor). Skywalker is unaffected in code: both S3-family backends use the still-maintained minio-go client and speak the standard S3 protocol, so they work with any S3-compatible server — SeaweedFS (the dev default bundled with the skeleton, verified end-to-end), Garage, Cloudflare R2, AWS S3, or an existing MinIO deployment.

CLI reference

skywalker new <name>          clone + scaffold a new application
skywalker make migration <n>  create up/down migration files
skywalker make auth           create auth migrations, models, and middleware
skywalker make handler <n>    create a stub handler
skywalker make model <n>      create a model in the data directory
skywalker make session        create a sessions table migration
skywalker make mail <n>       create starter mail templates
skywalker migrate             run all up migrations
skywalker migrate down        reverse the most recent migration
skywalker migrate reset       run all down, then all up migrations
skywalker version | help

Development

go build ./...
go vet ./...
go test ./...     # tests in cache, render, session, mailer, filesystems

Tests run with no external services; the mailer's SMTP tests spin up a MailHog container via dockertest when Docker is available and skip cleanly otherwise. CI (build + vet + test) runs on every push and pull request via GitHub Actions.

Repositories

  • Skywalker — this framework (github.com/stefanlester/skywalker).
  • skywalker_engine — the demo/skeleton app that skywalker new clones.

Status

Actively developed. The filesystem layer (all four backends), module-mode build, and CI are in place. Live end-to-end coverage for the S3/SFTP/WebDAV backends and a project LICENSE are still to come.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Routes

func Routes() http.Handler

Routes are skywalker specific routes, which are mounted in the routes file in Skywalker applications

Types

type Database

type Database struct {
	DataType string
	Pool     *sql.DB
}

type Encryption

type Encryption struct {
	Key []byte
}

Encryption encrypts and decrypts strings using AES-GCM with the supplied Key (16, 24, or 32 bytes for AES-128/192/256).

func (*Encryption) Decrypt

func (e *Encryption) Decrypt(cryptoText string) (string, error)

Decrypt reverses Encrypt. It returns an error if the input is not valid base64, is too short to contain a nonce, was encrypted with a different key, or has been tampered with (GCM authentication failure).

func (*Encryption) Encrypt

func (e *Encryption) Encrypt(text string) (string, error)

Encrypt encrypts text with AES-GCM using a random nonce. The result is base64.URLEncoding(nonce || ciphertext), so it is safe to use in URLs and cookies. GCM is authenticated, so Decrypt detects any tampering.

type Server

type Server struct {
	ServerName string
	Port       string
	Secure     bool
	URL        string
}

type Skywalker

type Skywalker struct {
	AppName string
	Debug   bool
	Version string
	// Log is the structured logger for the application. InfoLog and ErrorLog
	// are compatibility bridges that emit through the same handler.
	Log      *slog.Logger
	ErrorLog *log.Logger
	InfoLog  *log.Logger
	RootPath string
	Routes   *chi.Mux
	Render   *render.Render // render is a pointer to the render package
	Session  *scs.SessionManager
	DB       Database
	JetViews *jet.Set

	EncryptionKey string
	Cache         cache.Cache
	Scheduler     *cron.Cron
	Mail          mailer.Mail
	Server        Server
	FileSystems   map[string]interface{}
	// contains filtered or unexported fields
}

Skywalker is the overall type for the Skywalker package. Members that are exported in this type are are available to any application that uses it

func (*Skywalker) BuildDSN

func (c *Skywalker) BuildDSN() string

func (*Skywalker) CreateDirIfNotExist

func (c *Skywalker) CreateDirIfNotExist(path string) error

CreateDirIf NotExsit creates a new directory if it doesn't exist.

func (*Skywalker) CreateFileIfNotExist

func (c *Skywalker) CreateFileIfNotExist(path string) error

CreateFileIfNotExist creates a new file at path if it does not exist.

func (*Skywalker) DownloadFile

func (s *Skywalker) DownloadFile(w http.ResponseWriter, r *http.Request, pathToFile, fileName string) error

DownloadFile downloads a file

func (*Skywalker) Error404

func (s *Skywalker) Error404(w http.ResponseWriter, r *http.Request)

Error404 returns page not found response

func (*Skywalker) Error500

func (s *Skywalker) Error500(w http.ResponseWriter, r *http.Request)

Error500 returns internal server error response

func (*Skywalker) ErrorForbidden

func (s *Skywalker) ErrorForbidden(w http.ResponseWriter, r *http.Request)

ErrorForbidden returns a forbidden status message (client is known)

func (*Skywalker) ErrorStatus

func (s *Skywalker) ErrorStatus(w http.ResponseWriter, status int)

ErrorStatus returns a response with the supplied http status

func (*Skywalker) ErrorUnauthorized

func (s *Skywalker) ErrorUnauthorized(w http.ResponseWriter, r *http.Request)

ErrorUnauthorized sends an unauthorized status (client is not known)

func (*Skywalker) Init

func (s *Skywalker) Init(p initPaths) error

Init creates necessary folders for our Skywalker application

func (*Skywalker) ListenAndServe

func (s *Skywalker) ListenAndServe()

ListenAndServe starts the web server. WriteTimeout is 30s to match ReadTimeout: a single request/response cycle should never take minutes, and a short write timeout stops slow or stalled clients from pinning handler goroutines. IdleTimeout is 120s so idle keep-alive connections outlive the per-request timeouts and can be reused across many requests.

func (*Skywalker) LoadTime

func (s *Skywalker) LoadTime(start time.Time)

LoadTime calculates function execution time. To use, add defer c.LoadTime(time.Now()) to the function body

func (*Skywalker) MigrateDownAll

func (s *Skywalker) MigrateDownAll(dsn string) error

func (*Skywalker) MigrateForce

func (s *Skywalker) MigrateForce(dsn string) error

func (*Skywalker) MigrateUp

func (s *Skywalker) MigrateUp(dsn string) error

func (*Skywalker) New

func (s *Skywalker) New(rootPath string) error

New reads the .env file, creates our application config, populates the Skywalker type with settings based on .env values, and creates necessary folders and files if they don't exist

func (*Skywalker) NoSurf

func (s *Skywalker) NoSurf(next http.Handler) http.Handler

func (*Skywalker) OpenDB

func (s *Skywalker) OpenDB(dbType, dsn string) (*sql.DB, error)

func (*Skywalker) RandomString

func (c *Skywalker) RandomString(n int) string

RandomString generates a random string of length n from values in the const randomString, drawing each character uniformly via crypto/rand.

func (*Skywalker) ReadJSON

func (s *Skywalker) ReadJSON(w http.ResponseWriter, r *http.Request, data interface{}) error

func (*Skywalker) SessionLoad

func (s *Skywalker) SessionLoad(next http.Handler) http.Handler

func (*Skywalker) Steps

func (s *Skywalker) Steps(n int, dsn string) error

func (*Skywalker) Validator

func (s *Skywalker) Validator(data url.Values) *Validation

func (*Skywalker) WriteJSON

func (s *Skywalker) WriteJSON(w http.ResponseWriter, status int, data interface{}, headers ...http.Header) error

WriteJSON writes compact json from arbitrary data

func (*Skywalker) WriteXML

func (s *Skywalker) WriteXML(w http.ResponseWriter, status int, data interface{}, headers ...http.Header) error

WriteXML writes compact xml from arbitrary data

type Validation

type Validation struct {
	Data   url.Values
	Errors map[string]string
}

func (*Validation) AddError

func (v *Validation) AddError(key, message string)

func (*Validation) Check

func (v *Validation) Check(ok bool, key, message string)

func (*Validation) Has

func (v *Validation) Has(field string, r *http.Request) bool

func (*Validation) IsDateISO

func (v *Validation) IsDateISO(field, value string)

func (*Validation) IsEmail

func (v *Validation) IsEmail(field, value string)

func (*Validation) IsFloat

func (v *Validation) IsFloat(field, value string)

func (*Validation) IsInt

func (v *Validation) IsInt(field, value string)

func (*Validation) NoSpaces

func (v *Validation) NoSpaces(field, value string)

func (*Validation) Required

func (v *Validation) Required(r *http.Request, fields ...string)

func (*Validation) Valid

func (v *Validation) Valid() bool

Directories

Path Synopsis
cmd
cli command
Package urlsigner signs URLs with an embedded timestamp and an HMAC-SHA256 signature, so links such as password-reset URLs can be verified and expired without any server-side state.
Package urlsigner signs URLs with an embedded timestamp and an HMAC-SHA256 signature, so links such as password-reset URLs can be verified and expired without any server-side state.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL