https://github.com/bastean/codexgo
Example CRUD project applying Hexagonal Architecture, DDD, EDA, CQRS, BDD, CI, and more... in Go.
https://github.com/bastean/codexgo
codexgo fomantic-ui gin go mongodb rabbitmq sqlite templ
Last synced: 2 months ago
JSON representation
Example CRUD project applying Hexagonal Architecture, DDD, EDA, CQRS, BDD, CI, and more... in Go.
- Host: GitHub
- URL: https://github.com/bastean/codexgo
- Owner: bastean
- License: mit
- Created: 2023-12-07T23:54:13.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-25T03:50:11.000Z (3 months ago)
- Last Synced: 2025-04-09T15:06:06.144Z (2 months ago)
- Topics: codexgo, fomantic-ui, gin, go, mongodb, rabbitmq, sqlite, templ
- Language: Go
- Homepage:
- Size: 5.12 MB
- Stars: 83
- Watchers: 3
- Forks: 8
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/bastean/codexgo)
> Example CRUD project applying Hexagonal Architecture, Domain-Driven Design (DDD), Event-Driven Architecture (EDA), Command Query Responsibility Segregation (CQRS), Behavior-Driven Development (BDD), Continuous Integration (CI), and more... in Go.
[](LICENSE)
[](https://goreportcard.com/report/github.com/bastean/codexgo/v4)
[](https://github.com/commitizen/cz-cli)
[](https://github.com/release-it/release-it)[](https://github.com/bastean/codexgo/actions/workflows/upgrade.yml)
[](https://github.com/bastean/codexgo/actions/workflows/ci.yml)
[](https://github.com/bastean/codexgo/actions/workflows/release.yml)[](https://pkg.go.dev/github.com/bastean/codexgo/v4)
[](https://github.com/bastean/codexgo/releases)## Showcase
## CLI
### Run (Demo)
```bash
go run github.com/bastean/codexgo/v4/cmd/codexgo@latest -demo
```> [!NOTE]
>
> - Demo version does not require any configuration, because the required **ENV** values are already preset.
> - Here we can find the **ENV** preset values that are used in the [Demo](internal/pkg/service/env/demo.go).
> - `In-Memory` implementation will be used for EventBus, CommandBus, QueryBus and Database (`SQLite`).
> - Links to confirm and recover the account are sent through the `Terminal` with the following messages:
> - _"Hi \, please confirm your account through this link: \"_.
> - _"Hi \, please reset your password through this link: \"_.### Installation
```bash
go install github.com/bastean/codexgo/v4/cmd/codexgo@latest
``````bash
codexgo -h
``````text
_________ ________________
_____________ ______ /_____ ____ __ __ ____/__ __ \
_ ___/_ __ \_ __ / _ _ \__ |/_/ _ / __ _ / / /
/ /__ / /_/ // /_/ / / __/__> < / /_/ / / /_/ /
\___/ \____/ \__,_/ \___/ /_/|_| \____/ \____/Example CRUD project applying Hexagonal Architecture, DDD, EDA, CQRS, BDD, CI, and more... in Go.
Usage: codexgo [flags]
-demo
Use preset ENV values
-env string
Path to custom ENV file
```### Usage
> [!NOTE]
>
> - We can use the [.env.demo.cli](deployments/.env.demo.cli) file or we can create our own `.env` file where we define our own values.
> - In the [.env.example.cli](deployments/.env.example.cli) file, we can see the values that can be used.
> - If `CODEXGO_SMTP_*` is omitted, the links to confirm and recover the account are sent through the `Terminal` with the following messages:
> - _"Hi \, please confirm your account through this link: \"_.
> - _"Hi \, please reset your password through this link: \"_.
> - We can define our own **SMTP** configuration by simply modifying the `CODEXGO_SMTP_*` variables, then we will be able to receive the links by mail.
> - If `CODEXGO_BROKER_*` is omitted, an in-memory EventBus will be used.
> - `In-Memory` implementation will be used for CommandBus and QueryBus.
> - If `CODEXGO_DATABASE_*` is omitted, a `SQLite` in-memory database will be used.
> - We can use a file as a database instead of memory by defining the file name in the `CODEXGO_DATABASE_SQLITE_DSN` variable.```bash
codexgo -env path/to/.env
```## Docker
### Run (Demo)
> [!NOTE]
>
> - [System Requirements](#locally)
> - In the Demo version ([.env.demo](deployments/.env.demo)):
> - `RabbitMQ` implementation will be used for the EventBus.
> - **URL:** `http://localhost:15672`
> - **User/Password:** `codexgo-demo`
> - `In-Memory` implementation will be used for CommandBus and QueryBus.
> - `MongoDB` implementation will be used as Database.
> - **Compass:** `mongodb://codexgo-demo:codexgo-demo@localhost:27017`
> - `Mailpit` will be used as SMTP to receive emails with the links to confirm and recover the account.
> - **URL:** `http://localhost:8025`
> - `codexGO` Server.
> - **URL:** `http://localhost:8080````bash
task demo
```## Features
### Project Layout
- Based on [Standard Go Project Layout](https://github.com/golang-standards/project-layout).
### Git
- Hooks managed by [husky](https://github.com/typicode/husky):
- Pre-Push:
- Scanning Repository for secrets using [TruffleHog CLI](https://github.com/trufflesecurity/trufflehog) and [Trivy](https://github.com/aquasecurity/trivy)
- Pre-Commit: [lint-staged](https://github.com/lint-staged/lint-staged)
- Scanning files for secrets using [TruffleHog CLI](https://github.com/trufflesecurity/trufflehog?tab=readme-ov-file#8-scan-individual-files-or-directories)
- Formatting files using [gofmt](https://pkg.go.dev/cmd/gofmt), [goimports](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) and [Prettier](https://prettier.io/docs/en/install).
- Commit-Msg: [commitlint](https://github.com/conventional-changelog/commitlint)
- Check [Conventional Commits](https://www.conventionalcommits.org) rules
- Commit message helper using [czg](https://github.com/Zhengqbbb/cz-git).
- Interactive prompt that allows you to write commits following the [Conventional Commits](https://www.conventionalcommits.org) rules:
```bash
task commit
```### Scanners
- [TruffleHog CLI](https://github.com/trufflesecurity/trufflehog): Secrets.
- [Trivy](https://github.com/aquasecurity/trivy): Secrets, Vulnerabilities and Misconfigurations.
- [OSV-Scanner](https://github.com/google/osv-scanner): Vulnerabilities.### Linters/Formatters
- `*.go`: [GolangCI-Lint](.golangci.yml).
- `*.templ`: [templ fmt](https://templ.guide/commands-and-tools/cli#formatting-templ-files).
- `*.feature` (Gherkin): [Cucumber extension](https://cucumber.io/docs/tools/general).
- `*.*`: [Prettier cli/extension](https://prettier.io/docs/en/install).### Debuggers
- `*.go`: [deadcode](https://pkg.go.dev/golang.org/x/tools/cmd/deadcode).
### Tests
- Random data generator: [Gofakeit](https://github.com/brianvoe/gofakeit).
- Unit/Integration: [Testify](https://github.com/stretchr/testify).
- Acceptance: [Testify](https://github.com/stretchr/testify), [Godog (Cucumber)](https://github.com/cucumber/godog) and [Playwright](https://github.com/playwright-community/playwright-go).### Releases
- Automatically managed by [Release It!](https://github.com/release-it/release-it):
- Before/After Hooks for:
- Linting
- Testing
- Bump version based on [Conventional Commits](https://www.conventionalcommits.org) and [SemVer](https://semver.org/):
- CHANGELOG generator
- Commits and Tags generator
- GitHub Releases### GitHub
- Actions for:
- Setup Languages and Dependencies
- Workflows running:
- Automatically (Triggered by **Push** or **Pull requests**):
- Secrets
- Vulnerabilities
- Misconfigurations
- Linting
- Testing
- Manually (Using the **Actions tab** on GitHub):
- Upgrade Dependencies
- Automate Release
- Issue Templates **(Defaults)**.### Devcontainer
- Multiple Features already pre-configured:
- Go
- Task
- Docker in Docker
- Light-weight Desktop (Fluxbox)
- SSH
- Extensions and their respective settings to work with:
- Go
- Task
- Docker
- templ
- Cucumber
- Gherkin
- YAML
- TOML
- Prettier
- Better Comments
- Todo Tree
- cSpell### Docker
- Dockerfile
- **Multi-stage builds**:
- Development
- Testing
- Build
- Production
- Compose
- Switched by ENVs and Profiles.### Broker
- Message (Event/Command):
- Routing Key based on [AsyncAPI Topic Definition](https://github.com/fmvilas/topic-definition).### Server
- [Progressive Web App (PWA)](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Making_PWAs_installable)
- [Manifest](internal/app/server/static/manifest.json)### Security
- Server log files.
- Requests **Rate Limiting**.
- Data **authentication** via **JWT** managed by **Session Cookies**.
- [Captcha](https://github.com/mojocn/base64Captcha) implementation in forms.
- Form validation at the client using [Fomantic - Form Validation](https://fomantic-ui.com/behaviors/form.html).
- On the server, the validations are performed using the **Value Objects** defined in the **Context**.
- Account confirmation and recovery via **Mail** or **Terminal**.
- Password hashing using [Bcrypt](https://pkg.go.dev/golang.org/x/crypto/bcrypt).### Scripts
- [syncenv](scripts/syncenv/syncenv.go)
- Synchronize all **.env\*** files in the directory using an **.env** model.
- [copydeps](scripts/copydeps/copydeps.go)
- Copies the files required by the browser dependencies from the **node_modules** folder and places them inside the **static** folder on the server.
- [run](deployments/run.sh)
- Display the logs and redirect them to a file whose name depends on the time at which the service was run.
- Used in Production Image.## Domain > (Infrastructure | Application) > Presentation
### Bounded Context (App/Business/Department) > Modules (Troubleshooting) > Layers (Domain, Infrastructure & Application)
- **Domain (Logic Core)**
- Value Objects (Entities)
- Mother Creators
- Unit Tests
- Messages (Event/Command)
- Mother Creators
- Aggregates (Sets of Entities)
- Aggregate Root (Core Set)
- Mother Creators
- Role Interfaces (Ports)
- Repository
- Broker
- Model Interfaces
- Use Cases
- Handlers/Consumers
- Services (Abstract Logic)
- Errors (Management)
- **Infrastructure (Port Adapters)**
- Persistence
- Repository Mocks
- Implementations (Adapters)
- Integration Tests
- Communication
- Broker Mocks
- Implementations (Adapters)
- Integration Tests
- **Application (Orchestration of Domain Logic)**
- Use Cases
- Implementations
- Commands
- Mother Creators
- Queries/Responses
- Mother Creators
- Handlers/Consumers
- Implementations
- Unit Tests### Services > App > (Presentation)
- **Presentation (Consumers of Bounded Context Modules)**
- Services (Mapping)
- Centralize Imports
- Initializations
- Server
- Templates
- Handlers
- API
- Views
- Routes
- API `/v*`
- Views
- Features (Gherkin)
- Acceptance Tests## Workflow
### Idea
The system allows users to register a new account, log in and update their data or permanently delete their account, as well as verify it through a link sent to their email.
### Functionality
It is a monolith where CRUD operations can be performed from different presentations to the same database, this allows us to manage users from the different presentations available, in addition to having a messaging system that allows to communicate the events occurred, thus avoiding a coupling to the source of the same.
### Folders
1. `pkg/context/(modules)`
- It is the logical core that contains all the necessary functionalities that are agnostic of any **presentation**.
2. `internal/pkg/service`
- It is responsible for initializing all **context** functionalities so that they are ready for use, as well as for **"mapping"** certain values to centralize all imports required for **presentations** in a single place.
3. `internal/app/(presentations)`
- These **applications** will be used as **presentations** in order to serve the functionalities to an end user.
### Idiomatic
- **Domain**
- `errors.New*()`, `errors.BubbleUp()` & `errors.Panic()`
- Only in the `Domain` layer and in the `*_test.go` files can we throw `errors.Panic()`.
- **Infrastructure**
- `New*()`, `Open()` & `Close()`
- `session`
- `errors.New*()` & `errors.BubbleUp()`
- **Application**
- `Run()`, `Handle()` & `On()`
- `errors.New*()` & `errors.BubbleUp()`
- **Presentation**
- **Modules**
- `Start()` & `Stop()`
- `errors.BubbleUp()`
- **Services / Apps**
- `Init()`, `Up()` & `Down()`
- `log.[Wrap]()`
- `errors.New*()` & `errors.BubbleUp()`
- In `Apps` we will handle `Bubble Errors`.
- **Main**
- `log.Fatal()` & `log.[Wrap]()`
- Only `main()` can use `log.Fatal()`.
- **Logs**
- `[embed]`
- We use `[]` to **"embed"** external values such as error messages, fields, etc... inside our messages.
- **ENVs**
- `os.[Getenv/LookupEnv]()`
- Only handle `ENVs` directly in the `Presentation` layer and in the `*_test.go` files.
- At the `Infrastructure` layer, `ENVs` are received via arguments through function parameters.
- **Blocks**
- `const`, `var`, & `type`
- We will group only those that are declared on a single line.### ...`v0` > `dev0.1.0` > `ci/dev0.1.0` > `main` > `v0`...
Create `v0` branch from `main`.
```bash
task git-v0
```Create development branch `dev0.1.0` from `v0`.
```bash
task git-dev0.1.0
```Create branch `ci/dev0.1.0` from `dev0.1.0` to ensure that the workflows run correctly with the new changes before merging them with `main`.
```bash
task git-ci/dev0.1.0
```Once the workflows have been successfully passed, the new changes from `ci/dev0.1.0` will be merged into `main`.
```bash
task git-main-ci/dev0.1.0
```After releasing the new version `v0.1.0`, the `main` and `v0` branches in our local repository will be updated.
```bash
task git-pull-v0
```To end the cycle, the `dev0.1.0` and `ci/dev0.1.0` branches will be deleted.
```bash
task git-cleanup-dev0.1.0
```## First Steps
### Clone
#### HTTPS
```bash
git clone https://github.com/bastean/codexgo.git && cd codexgo
```#### SSH
```bash
git clone [email protected]:bastean/codexgo.git && cd codexgo
```### Initialize
#### Dev Container **(Recommended)**
1. System Requirements
- [Docker](https://docs.docker.com/get-docker)
- [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
2. Start VS Code
```bash
code .
```3. Open Command Palette
- F1
4. Run
```text
Dev Containers: Reopen in Container
```5. SSH **(Optional)**
- We can connect to our `Dev Container` via `SSH` in the following ways:
- If we have [Task](https://taskfile.dev/installation) installed on our host, being in the root of the repository
```bash
task connect-2222-vscode-localhost
```
- Using the SSH Client of our host
```bash
ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null vscode@localhost
```
- **Password:** `vscode`6. Desktop **(Optional)**
- We can connect to our `Dev Container` via `VNC` using our web browser.
- **URL:** `http://localhost:6080`
- **Password:** `vscode`
- No password is required to connect from the **local host**.
- Change the default applications of the context menu **(Optional)**
```bash
task desktop
```
- **File Manager:** `xfe`
- **Terminal:** `terminator`
- **Web Browser:** `chromium`#### Locally
1. System Requirements
- [Go](https://go.dev/doc/install)
- [Task](https://taskfile.dev/installation)
- [Docker](https://docs.docker.com/get-docker)2. Run
```bash
task init
```### ZIP
> [!NOTE]
>
> - [System Requirements](#locally)
> - We need to change `` and `` with our own values.```bash
curl -sSfLO https://github.com/bastean/codexgo/archive/refs/heads/main.zip \
&& unzip main.zip \
&& mv codexgo-main \
&& rm main.zip \
&& cd \
&& task genesis \
&& git commit -m "feat(genesis): codexgo" \
&& git branch -M main \
&& git remote add github https://github.com//.git \
&& git push -u github main \
&& git status
```Repository initialization from ZIP (Optional)
## Design
#### Icons (Template: [Icon Safe Zone SVG](https://www.w3.org/TR/appmanifest/images/icon-safe-zone.svg))
- `favicon-512.png` (512x512)
#### Screenshots
- `desktop.png` (1536x860)
- `mobile.png` (425x800)#### Readme
- `logo.png`
#### Social Preview (Template: [GitHub Repository > Settings > General > Social preview > Download template]())
- `social-preview.png`
#### Mocks
- Wireframe
- UML## Repository
#### Genesis
- Run initialization from `ZIP` ([codexGO](https://github.com/bastean/codexgo#zip))
- Cleanup
- `CHANGELOG`
- Everything not required- Add `` > `assets/`
- Compress `assets`
- Update `#colors` > `#`
- Update (`codexgo/v*`|`codexgo`|`codexGO`) > ``
- `Source Code`, `Files` & `Folders`
- Update `README`
- Update `Logo`
- Update `Description`
- Add `Disclaimer`
```markdown
> [!IMPORTANT]
>
> `` is still in the early stages of development.
```
- Update `Tech Stack`
- Remove all other sections, except:
- `Logo`, `Description`, `Disclaimer`, `Badges`, `Tech Stack`, `Contributing` & `License`
- Change `v*.*.*` > `v0.0.0`- Commit, Upgrade & Push
```bash
git commit -m "chore: update codexgo to " \
&& task upgrade \
&& git push \
&& git status
```## GitHub
#### Settings
- Rulesets
- `New branch ruleset`
- Ruleset Name \*
- Branches
- Enforcement status
- Active
- Target branches
- Include by pattern
- `main`
- `v*`
- Branch rules
- Restrict deletions
- Require signed commits **(Optional)**
- Block force pushes
- `New tag ruleset`
- Ruleset Name \*
- Tags
- Enforcement status
- Active
- Target tags
- Include by pattern
- `v*`
- Tag rules
- Restrict deletions
- Require signed commits **(Optional)**
- Block force pushes- Secrets and variables **(Optional)**
- Actions
- New repository secret
- `BOT_GPG_PASSPHRASE`
- `BOT_GPG_PRIVATE_KEY`
```bash
gpg --armor --export-secret-key [Pub_Key_ID (*-BOT)]
```- Social preview
- Upload an image…
#### Actions
- Workflows
- Release
- Run workflow
- Use workflow from
- Branch: `main`
- Status
- `alpha`
- Bump
- `minor`
- Pre-release
- `v0.1.0-alpha.0`### GitHub Actions **(Optional)**
> [!IMPORTANT]
> By default, the user used to create commits and tags in workflows is `github-actions[bot]`, whose creations are not signed. If we want the creation of commits and tags to be signed, we must create the specified **"Repository Secrets"**, this way by selecting `GPG Sign` when manually launching a workflow everything will be created using the information obtained from the **"GPG Key"**.#### Settings tab
##### Secrets and variables
- Actions
- New repository secret
- `BOT_GPG_PASSPHRASE`
- `BOT_GPG_PRIVATE_KEY`
```bash
gpg --armor --export-secret-key [Pub_Key_ID (*-BOT)]
```### Run
#### ENVs
> [!IMPORTANT]
> If we want to modify the values inside some `.env` file, here [.env.example.demo](deployments/.env.example.demo) we can see the values that can be used.#### Development ([.env.demo.dev](deployments/.env.demo.dev))
> [!NOTE]
>
> - `RabbitMQ`
> - **URL:** `http://localhost:15672`
> - **User/Password:** `codexgo-dev`
> - `MongoDB`
> - **Compass:** `mongodb://codexgo-dev:codexgo-dev@localhost:27017`
> - `Mailpit`
> - **URL:** `http://localhost:8025`
> - `codexGO` Server
> - **URL:** `http://localhost:8080`
> - `codexGO` Live-Reloading Server
> - **URL:** `http://localhost:8090````bash
task compose-dev
```#### Tests
##### Unit
```bash
task test-unit
```##### Integration ([.env.demo.test](deployments/.env.demo.test) | [.env.demo.test.integration](deployments/.env.demo.test.integration))
```bash
task compose-test-integration
```##### Acceptance ([.env.demo.test](deployments/.env.demo.test) | [.env.demo.test.acceptance](deployments/.env.demo.test.acceptance))
```bash
task compose-test-acceptance
```##### Unit / Integration / Acceptance ([.env.demo.test](deployments/.env.demo.test))
```bash
task compose-tests
```#### Production ([.env.demo.prod](deployments/.env.demo.prod))
> [!NOTE]
>
> - We must define our own **SMTP** configuration in the `CODEXGO_SMTP_*` variables, to receive the links by mail.
> - By default, as there are no values set, the links will be sent through the terminal.
> - `RabbitMQ`
> - **URL:** `http://localhost:15672`
> - **User/Password:** `codexgo`
> - `MongoDB`
> - **Compass:** `mongodb://codexgo:codexgo@localhost:27017`
> - `codexGO` Server
> - **URL:** `http://localhost:8080````bash
task compose-prod
```## Tech Stack
#### Base
- [Go](https://go.dev)
- [Gin](https://gin-gonic.com)
- [templ](https://templ.guide)
- [Fomantic-UI](https://fomantic-ui.com)
- [RabbitMQ](https://www.rabbitmq.com/tutorials/tutorial-one-go)
- [MongoDB](https://www.mongodb.com/docs/drivers/go)
- [SQLite](https://gorm.io/docs/connecting_to_the_database.html#SQLite)#### Please see
- [go.mod](go.mod)
- [package.json](package.json)## Contributing
Contributions and Feedback are always welcome!
- [Open a new issue](https://github.com/bastean/codexgo/issues/new/choose)
## License
[MIT](LICENSE)