Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,27 @@ A Go service that:

## Getting Started

### Option 1: Manual Setup

Check the individual README files in each project directory for specific setup instructions:
- [Frontend Setup](/app/README.md)
- [Backend Setup](/api/README.md)

### Option 2: Docker Compose

Run all services with Docker Compose:

```bash
docker-compose up -d
```

This will start:
- PostgreSQL database on port 5432
- Next.js app on port 3000 (with automatic database migration)
- Go API on port 8080

Both app and API services support hot reload for development.

## Video Tutorial

This project accompanies a tutorial video by Dreams of Code explaining the implementation details and best practices for integrating Better-Auth with Go.
44 changes: 44 additions & 0 deletions api/.air.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ."
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_root = false

[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"

[log]
main_only = false
time = false

[misc]
clean_on_exit = false

[screen]
clear_on_rebuild = false
keep_scroll = true
20 changes: 20 additions & 0 deletions api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM golang:1.24.2-alpine

WORKDIR /app

# Install air for hot reload
RUN go install github.com/air-verse/air@latest

# Copy go mod and sum files
COPY go.mod go.sum ./

# Download dependencies
RUN go mod download

# Copy source code
COPY . .

EXPOSE 8080

# Use air for hot reload
CMD ["air", "-c", ".air.toml"]
2 changes: 1 addition & 1 deletion api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ go mod download

Start the server:
```bash
go run main.go
go run ./
```

The API will start on port 8080 by default.
Expand Down
8 changes: 7 additions & 1 deletion api/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"net/http"
"os"

"github.com/lestrrat-go/jwx/v3/jwk"
"github.com/lestrrat-go/jwx/v3/jwt"
Expand All @@ -20,7 +21,12 @@ var (
)

func UserFromRequest(r *http.Request) (User, error) {
keyset, err := jwk.Fetch(r.Context(), "http://localhost:3000/api/auth/jwks")
authAPIURL := os.Getenv("AUTH_API_URL")
if authAPIURL == "" {
authAPIURL = "http://localhost:3000/api/auth"
}

keyset, err := jwk.Fetch(r.Context(), authAPIURL+"/jwks")
if err != nil {
return User{}, fmt.Errorf("fetch jwks: %w", err)
}
Expand Down
3 changes: 1 addition & 2 deletions api/middleware/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"net/http/httptest"
"os"
"testing"
"time"

"github.com/dreamsofcode-io/authly/api/middleware"
"github.com/stretchr/testify/assert"
)

Expand All @@ -23,5 +23,4 @@ func TestLogging(t *testing.T) {
testHandler.ServeHTTP(w, req)

assert.Equal(t, http.StatusOK, w.Code)
assert.Greater(t, time.Since(req.Context().Value("startTime").(time.Time)), 0)
}
22 changes: 22 additions & 0 deletions app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM oven/bun:1-alpine

WORKDIR /app

# Install build dependencies for native modules
RUN apk add --no-cache python3 make g++

# Copy package files
COPY package.json bun.lockb* ./

# Install dependencies
RUN bun install

# Copy source code
COPY . .

# Make entrypoint executable
RUN chmod +x /app/entrypoint.sh

EXPOSE 3000

CMD ["/app/entrypoint.sh"]
22 changes: 21 additions & 1 deletion app/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Prerequisites

- PostgreSQL database running
- DATABASE_URL configured in app/.env file
```
DATABASE_URL="postgresql://username:password@localhost:5432/database_name"
```

## Getting Started

First, run the development server:
First, run the database migration:

```bash
npm run db:migrate
# or
yarn db:migrate
# or
pnpm db:migrate
# or
bun run db:migrate
```

Then, run the development server:

```bash
npm run dev
Expand Down
9 changes: 9 additions & 0 deletions app/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh
set -e

echo "Running database migration..."
bun run db:migrate

echo "Starting development server..."
bun run dev

6 changes: 3 additions & 3 deletions app/src/components/go-api-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export function GoAPITest() {

const response = await fetch("/api/me")
.then(x => x.json())
.then(x => ({data: x}))
.catch(e => ({error: e}))
.then(x => ({ data: x }))
.catch(e => ({ error: e }))

if (response.error) {
if ('error' in response) {
setApiResponse(`❌ Go API Error: ${response.error}`)
} else {
setApiResponse(`✅ Go API Success: ${JSON.stringify(response.data, null, 2)}`)
Expand Down
6 changes: 6 additions & 0 deletions app/src/db/migrations/0001_flawless_klaw.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE "jwks" (
"id" text PRIMARY KEY NOT NULL,
"public_key" text NOT NULL,
"private_key" text NOT NULL,
"created_at" timestamp NOT NULL
);
Loading