Gohtwind is an opinionated and lightweight full-stack framework designed for rapid web application development using Go, TailwindCSS, and htmx. Streamline your development process, from backend to frontend, with Gohtwind's fast and simple approach!
- Backend: Go backend setup with a focus on performance and simplicity
- Frontend: Integrated with TailwindCSS for utility-first CSS styling and htmx for efficient frontend enhancements
- Live Reloading: Includes tooling for live-reloading during development
- Deploying: Comes with Docker configurations tailored for production deployments
- Language: Go (Golang)
- Routing: Standard net/http library
- Templating: Standard html/template library
- Authentication: Authboss (coming soon)
- Authorization: Casbin (coming soon)
- Database Interaction: go-jet/jet
- Dynamic Behavior: htmx
- Styling: Tailwind CSS
- IDE: GoLand by JetBrains
- Version Control: GitHub
- Automation: GitHub Actions (coming soon)
- Automated deployment to Google Cloud Run when merging a PR from the main branch to the prod branch.
- Deployment Setup: Docker (with a production-specific Dockerfile)
- Deployment & Hosting:
- Containerization: Docker
- Hosting: Google Cloud Run
- Database:
- Database Service: Google Cloud SQL
- Database Engine: MySQL
To get started with Gohtwind:
- Ensure you have Go installed on your machine.
- Optional: Ensure you have Docker installed on your machine. (For development database)
- Clone/download the Gohtwind repository.
- Navigate to the Gohtwind directory and run:
go build
sudo cp gohtwind /usr/local/bin/
Now, you can use the gohtwind
command from anywhere in your terminal!
- Create a new Gohtwind project:
# gohtwind name your_project_name
# ex:
gohtwind new town
- Navigate to your project directory:
# cd your_project_name
# ex:
cd town
- Create a page (a.k.a. feature) within your project:
# gohtwind gen-feature [feature_name]
# ex:
gohtwind gen-feature market
- Add feature routes to the
main.go
in the root of your project directory:
package main
// the ide will automatically import the packages for you
// if not, you can manually import them like so:
import (
// ...
// "<project_name>/infra"
"town/infra"
// "<project_name>/auth"
"town/auth"
// "<project_name>/<feature_name>"
"town/market"
// ...
)
func main() {
// ...
}
func setUpEnv() {
// ...
}
func setUpDBs() {
// ...
}
func setUpRoutes() {
// ...
http.Handle("/static/", infra.LoggingMiddleware(http.StripPrefix("/static/", http.FileServer(http.Dir("./frontend/static/")))))
auth.SetupRoutes(dbs, infra.LoggingMiddleware)
/**
Replace feature_name with the name of your feature like so:
feature_name_1.SetupRoutes(dbs, infra.LoggingMiddleware)
...
feature_name_2.SetupRoutes(dbs, infra.LoggingMiddleware)
...
feature_name_n.SetupRoutes(dbs, infra.LoggingMiddleware)
**/
// ex:
market.SetupRoutes(dbs, infra.LoggingMiddleware)
// Activate the routes
infra.ActivateRoutes()
}
- Optional: Run containerized database for development:
docker build -t gohtwind-db -f Dockerfile.db .
docker run -d -p 3306:3306 --name gohtwind-db gohtwind-db
- Generate sql models using:
# gohtwind gen-models -adapter=mysql -dsn="<username>:<password>@tcp(<host>:<port>)/<dbname>"
# or
# gohtwind gen-models -adapter=postgres -dsn="postgresql://<user>:<password>@<host>:<port>/<dbname>?sslmode=disable -schema=<schema>"
# using the containerized database
gohtwind gen-models -adapter=mysql -dsn="root:root@tcp(localhost:3306)/dev"
- Generate a repository file for the feature:
# Make sure that the model_name is the same as the generated model name (Usually the table name in TitleCase)
# gohtwind gen-repository -feature-name=<feature_name> -model-name=<model_name> -db-name=<dbname> -adapter=<mysql | postgres> -schema=<schema postgres only>
# using the model from containerized database
gohtwind gen-repository -feature-name=market -model-name=Products -db-name=dev -adapter=mysql
- Copy the example.env file and rename it to .env:
cp example.env .env
- Start the development server:
./dev-run.sh
- Start developing your application!
/myapp
|-- dev-run.sh
|-- Dockerfile.prod
|-- example.env
|-- .gitignore
|-- .gen/ # Generated sql models
|-- config/ # Configuration files
|-- go.mod
|-- go.sum
|-- templates/ # base template and shared templates
| |-- shared/
| |-- base.html
|-- frontend/
| |-- static/
| | |-- css/
| | | |-- main.css # Base CSS file for Tailwind
| |
| |-- output.css # Generated CSS after processing with Tailwind
| |-- tailwind.config.js
|-- author-books/ # Example feature module
| |-- handler.go
| |-- repository.go
| |-- view.go
| |-- routes.go
| |-- static/
| | |-- js/
| | |-- css/
| |-- templates/
| |-- create.html
| |-- read.html
| |-- update.html
| |-- delete.html
| |-- list.html
|-- other-feature/ # Another example feature module
| ... # Similar structure as above
|-- ... # Other project-wide files, utilities, shared components, etc.
- To generates a new feature within your project run the gohtwind command with the gen-feature flag:
gohtwind gen-feature [feature_name]
- This will create a new feature module with the name
feature_name
in the root of your project directory. - A feature is a page within the web application.
- The feature script generates boilerplate code for basic CRUD operations.
- All the CRUD operations are done within the context of a single page.
- Traditionally, CRUD operations are done across multiple pages.
- Gohtwind's approach is to keep all the CRUD operations within a single page using dialog modals.
- This approach is more efficient and provides a better user experience (IMO).
- To generate sql models, use the following gohtwind command:
gohtwind gen-models -adapter=<mysql | postgres> -dsn=<dsn> -schema=<schema>
- It wraps the go-jet/jet run the jet command
- Generated models are placed in the
.gen
directory at the root of your project directory. - The
-adapter
flag specifies the database source. Currently, only MySQL and Postgres is supported. - The
-dsn
flag specifies the database connection string. - The
-schema
flag specifies the database schema to generate models for. (Only applicable for Postgres)
- To generate repository boilerplate code, use the following gohtwind command:
gohtwind gen-repository -feature-name=<feature_name> -model-name=<model_name> -db-name=<dbname> -adapter=<mysql | postgres> -schema=<schema postgres only>
- This will generate a repository file for the specified feature and model.
- The repository file contains boilerplate code for basic CRUD operations.
- The repository file is used by the feature's handler to interact with the database.
- The
-feature-name
flag specifies the name of the feature the repository is for. - The
-model-name
flag specifies the name of the model (sql table) the repository is for. - The
-db-name
flag specifies the name of the database - The
-schema
schema (postgres only) the model is in. - The
-adapter
flag specifies the database adapter to use. Currently, only MySQL and Postgres is supported.
- To generate a form inside a template, use the following gohtwind command:
gohtwind gen-form -feature-name=<feature_name> -model-name=<model_name>
- This command replaces {{GEN_FORM}} in the specified template with a form for the specified model
- The form is generated using the model's form tags
- When an instance name is provided, the form is generated with the instance's values
- The
-feature-name
flag specifies the name of the feature the form is for. - The
-model-name
flag specifies the name of the model the form is for. - The
-template-name
flag specifies the name of the template the form is for. - The
-instance-name
flag specifies the name of the instance the form is for. Use this flag for update forms. Omit this flag for create forms. - The
-action
flag specifies the action of the form.
- To start the development server run the script:
./dev-run.sh
Contributions to Gohtwind are welcome. Please read our Contributing Guide (coming soon) for more information.
Gohtwind is licensed under the MIT License.
Feel free to modify or expand any sections to better fit the specifics of your project.