diff --git a/.github/actions/install/action.yml b/.github/actions/install/action.yml
new file mode 100644
index 0000000..76679f3
--- /dev/null
+++ b/.github/actions/install/action.yml
@@ -0,0 +1,28 @@
+name: Install
+
+inputs:
+  os:
+    description: The operating system to run the action on, should be the 'runs-on' in workflows
+    required: true
+    default: "ubuntu-22.04"
+  repo-token:
+    description: The token to use to authenticate with the GitHub API
+    required: true
+
+runs:
+  using: "composite"
+  steps:
+    - uses: actions/setup-go@v5
+      with:
+        go-version: 1.22
+        cache: true
+
+    - name: Install Task
+      uses: arduino/setup-task@v2
+      with:
+        version: 3.x
+        repo-token: ${{ inputs.repo-token }}
+
+    - name: Install Dependencies
+      run: task install
+      shell: bash
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..b13d26d
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,80 @@
+name: build and upload artifacts
+
+on:
+  push:
+    branches: [main]
+  pull_request:
+  workflow_dispatch:
+  workflow_call:
+    inputs:
+      tag_name:
+        type: string
+        description: "The tag name of the release without v prefix"
+
+env:
+  VERSION: ${{ inputs.tag_name }}
+
+jobs:
+  build:
+    name: build and upload artifacts
+    strategy:
+      matrix:
+        include:
+          - os: windows-2022
+            arch: amd64
+            target: windows
+            ext: .exe
+          - os: ubuntu-20.04
+            arch: amd64
+            target: linux
+          - os: macos-13
+            arch: amd64
+            target: darwin
+          - os: macos-14
+            arch: arm64
+            target: darwin
+
+    runs-on: ${{ matrix.os }}
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+
+      - name: installing dependencies
+        uses: ./.github/actions/install
+        with:
+          os: ${{ matrix.os }}
+          repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Check if VERSION exists
+        shell: bash
+        id: check_version
+        run: |
+          if [ ! -z "${{ env.VERSION }}" ]; then
+            echo "PRODUCTION=true" >> $GITHUB_ENV
+          fi
+
+      - name: Build CLI
+        shell: bash
+        run: task build:cli
+        env:
+          OS: ${{ matrix.target }}
+          ARCH: ${{ matrix.arch }}
+
+      - name: Upload CLI artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: cli-${{ matrix.target }}-${{ matrix.arch }}-${{ env.VERSION }}
+          path: build/cli${{ matrix.ext }}
+
+      - name: Build Server
+        shell: bash
+        run: task build:server
+        env:
+          OS: ${{ matrix.target }}
+          ARCH: ${{ matrix.arch }}
+
+      - name: Upload Server artifact
+        uses: actions/upload-artifact@v4
+        with:
+          name: server-${{ matrix.target }}-${{ matrix.arch }}-${{ env.VERSION }}
+          path: build/server${{ matrix.ext }}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 0000000..2993b41
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,31 @@
+name: Lint
+
+on:
+  push:
+    branches: [main]
+  pull_request:
+
+jobs:
+  lint:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-go@v5
+        with:
+          go-version: 1.22
+          cache: true
+      - name: run golangci-lint
+        uses: golangci/golangci-lint-action@v6
+        with:
+          version: v1.59
+          args: --timeout=3m
+      - name: install gofumpt
+        run: go install mvdan.cc/gofumpt@latest
+      - name: run gofumpt
+        run: |
+          ERRORS=$(gofumpt -l . | wc -l)
+          if [[ "$ERRORS" != "0" ]]; then
+            echo "following files are not gofumpted:"
+            gofumpt -l .
+            exit 1
+          fi
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cddd635
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+build
+
+# MacOS
+.DS_Store
\ No newline at end of file
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..3da60a3
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,43 @@
+linters:
+  enable:
+    - wsl
+
+linters-settings:
+  wsl:
+    # See https://github.com/bombsimon/wsl/blob/master/doc/configuration.md for documentation of available settings.
+    # These are the defaults for `golangci-lint`.
+
+    # Allows assignments to be cuddled with variables used in calls on
+    # line above and calls to be cuddled with assignments of variables
+    # used in call on line above.
+    allow-assign-and-call: true
+    # Allows assignments to be cuddled with anything.
+    allow-assign-and-anything: true
+    # Allows cuddling to assignments even if they span over multiple lines.
+    allow-multiline-assign: true
+    # If the number of lines in a case block is equal to or lager than this
+    # number, the case *must* end white a newline.
+    force-case-trailing-whitespace: 2
+    # Allow blocks to end with comments.
+    allow-trailing-comment: true
+    # Allow multiple comments in the beginning of a block separated with newline.
+    allow-separated-leading-comment: false
+    # Allow multiple var/declaration statements to be cuddled.
+    allow-cuddle-declarations: true
+    # A list of call idents that everything can be cuddled with.
+    # Defaults to calls looking like locks.
+    allow-cuddle-with-calls: ["Lock", "RLock"]
+    # AllowCuddleWithRHS is a list of right hand side variables that is allowed
+    # to be cuddled with anything. Defaults to assignments or calls looking
+    # like unlocks.
+    allow-cuddle-with-rhs: ["Unlock", "RUnlock"]
+    # Causes an error when an If statement that checks an error variable doesn't
+    # cuddle with the assignment of that variable.
+    force-err-cuddling: true
+    # When force-err-cuddling is enabled this is a list of names
+    # used for error variables to check for in the conditional.
+    error-variable-names: ["err"]
+    # Causes an error if a short declaration (:=) cuddles with anything other than
+    # another short declaration.
+    # This logic overrides force-err-cuddling among others.
+    force-short-decl-cuddling: false
\ No newline at end of file
diff --git a/Taskfile.yml b/Taskfile.yml
new file mode 100644
index 0000000..ca46602
--- /dev/null
+++ b/Taskfile.yml
@@ -0,0 +1,82 @@
+version: '3'
+
+tasks:
+  install:
+    cmds:
+      # Empty for now
+
+  generate:
+    cmds:
+      - cmd: go generate ./...
+
+  build:
+    cmds:
+      - task: build:server
+      - task: build:cli
+
+  build:internal:
+    build:
+    desc: Internal build task
+    internal: true
+    cmds:
+      - cmd: echo Building DeWeb {{.APP_NAME}} for {{.OS | default OS}}/{{.ARCH | default ARCH}}
+        silent: true
+      - cmd: 'echo Mode: {{if eq .PRODUCTION "true"}}Production{{else}}Development{{end}}'
+        silent: true
+      - cmd: 'echo Version: {{.VERSION | default "Development"}}'
+        silent: true
+      - cmd: go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}{{.BIN_EXT}} ./cmd/{{.APP_NAME}}
+    vars:
+      # We need this check for nil and empty string because a simple check for empty string doesn't work as expected
+      VERSION_FLAG: '{{if ne .VERSION nil}}{{if ne .VERSION ""}}-X github.com/massalabs/DeWeb/int/config.Version=v{{.VERSION}}{{end}}{{end}}'
+      BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production {{end}}-ldflags="{{.VERSION_FLAG}}{{if eq .PRODUCTION "true"}} -w -s{{end}}"'
+      BIN_EXT: '{{if eq .OS "windows"}}.exe{{end}}'
+    env:
+      GOOS: "{{.OS | default OS}}"
+      GOARCH: "{{.ARCH | default ARCH}}"
+      PRODUCTION: '{{.PRODUCTION | default "false"}}'
+      VERSION: "{{.VERSION | default nil}}"
+
+  build:server:
+    cmds:
+      - task: build:internal
+        vars:
+          APP_NAME: server
+          BIN_DIR: build
+
+  build:cli:
+    cmds:
+      - task: build:internal
+        vars:
+          APP_NAME: cli
+          BIN_DIR: build
+
+  run:cli:
+    cmds:
+      - cmd: ./build/cli
+
+  run:server:
+    cmds:
+      - cmd: ./build/server
+
+  clean:
+    cmds:
+      - cmd: rm -rf build
+
+  test:
+    cmds:
+      - cmd: go test ./...
+
+  install:tools:
+    cmds:
+      - cmd: go install mvdan.cc/gofumpt@latest
+      - cmd: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
+
+  lint:
+    cmds:
+      - cmd: golangci-lint run
+
+  fmt:
+    cmds:
+      - cmd: go fmt ./...
+      - cmd: go mod tidy
diff --git a/cmd/cli/main.go b/cmd/cli/main.go
new file mode 100644
index 0000000..5f20207
--- /dev/null
+++ b/cmd/cli/main.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+	"log"
+
+	"github.com/massalabs/DeWeb/int/config"
+)
+
+func main() {
+	log.Println("Hello, World from DeWeb CLI", config.Version, "!")
+}
diff --git a/cmd/server/main.go b/cmd/server/main.go
new file mode 100644
index 0000000..7598dd2
--- /dev/null
+++ b/cmd/server/main.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+	"log"
+
+	"github.com/massalabs/DeWeb/int/config"
+)
+
+func main() {
+	log.Println("Hello, World from DeWeb Server", config.Version, "!")
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..0cf5490
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module github.com/massalabs/DeWeb
+
+go 1.22.5
diff --git a/int/config/version.go b/int/config/version.go
new file mode 100644
index 0000000..6c39645
--- /dev/null
+++ b/int/config/version.go
@@ -0,0 +1,4 @@
+package config
+
+//nolint:gochecknoglobals
+var Version = "dev"