Skip to main content
This guide will walk you through setting up the full-stack application from clone to making your first API call.

Prerequisites

Before you begin, ensure you have the following installed:
1

Backend Requirements

  • Go 1.21+: Download Go
  • Docker: For running MongoDB locally
2

Frontend Requirements

Optional: Install air for Go live reload during development

Setup Instructions

1

Clone the Repository

Start by cloning the project to your local machine:
git clone <your-repo-url>
cd go-react-scaffold
2

Backend Setup

Navigate to the backend directory and configure your environment:
cd backend

Configure Environment Variables

Copy the example environment file and update it with your values:
cp .env.example .env
Edit the .env file with your configuration:
APP_ENV=development
MONGODB_URI=mongodb://localhost:27017
PORT=8080
SESSION_KEY=your-super-secret-jwt-key-change-this
REDIS_URL=redis://localhost:6379
Important: Always use a strong, unique SESSION_KEY in production. This key is used for JWT token signing.

Start MongoDB

Use Docker to run MongoDB locally:
make docker-run
This command starts MongoDB in a Docker container. The database will be accessible at mongodb://localhost:27017.

Start the Backend Server

Run the Go server:
make run
You should see:
Pinged your deployment. You successfully connected to MongoDB!
The backend API is now running at http://localhost:8080.
For development with automatic reloading:
make watch
If air is not installed, the Makefile will prompt you to install it.
3

Frontend Setup

Open a new terminal window and navigate to the frontend directory:
cd frontend

Install Dependencies

npm install
This installs all required packages including React, TypeScript, Vite, and TailwindCSS.

Start the Development Server

npm run dev
The frontend will start on http://localhost:5173 (default Vite port) with hot module replacement (HMR) enabled.
The Vite dev server provides instant updates when you modify your code.
4

Verify the Setup

Open your browser and visit:
  • Frontend: http://localhost:5173
  • Backend API: http://localhost:8080
You should see the default React + Vite welcome page.

Making Your First API Call

The scaffold comes with authentication endpoints ready to use. Let’s register a user and login.
1

Register a New User

Use curl or your favorite API client to register:
curl -X POST http://localhost:8080/register \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "[email protected]" \
  -d "password=securepassword123"
Expected Response:
"Success"
The user is created with a pending status by default. In a production app, you’d verify the email before activating.
2

Login and Get JWT Token

Authenticate with the registered user:
curl -X POST http://localhost:8080/login \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "[email protected]" \
  -d "password=securepassword123"
Expected Response:
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "status": true,
  "error": null
}
The response includes:
  • token: JWT token for authenticated requests (valid for 24 hours)
  • status: Authentication success status
  • HTTP-only cookies are automatically set for secure session management
3

Understanding Authentication Flow

Here’s how authentication works in the scaffold:
  1. Password Hashing: Passwords are hashed using bcrypt with cost factor 14
  2. JWT Generation: Upon successful login, a JWT token is generated with the user ID
  3. Cookie Storage: The token is stored in HTTP-only cookies for security
  4. Token Expiration: Tokens expire after 24 hours
The authentication logic is in backend/auth/controller.go:
backend/auth/controller.go
func processUserLogin(email, password string) (string, bool, error) {
  user, err := users.GetUserByEmail(email)
  if err != nil {
    return "", false, err
  }
  if user.Status != "active" {
    return "", false, fmt.Errorf("user is not active")
  }
  errr := bcrypt.CompareHashAndPassword(user.Password, []byte(password))
  if errr != nil {
    return "", false, fmt.Errorf("the password provided is not valid")
  }

  return user.ID, true, nil
}
Password hashing with bcrypt cost 14:
backend/auth/controller.go
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 14)

Common Development Commands

Here are the commands you’ll use most often during development:
# Start the server
make run

# Build the application
make build

# Run with live reload
make watch

# Start MongoDB
make docker-run

# Stop MongoDB
make docker-down

# Run tests
make test

# Clean build artifacts
make clean

Next Steps

Now that you have the scaffold running:

Explore the Structure

Learn about the project architecture and how the pieces fit together

Add Custom Endpoints

Extend the API by adding new routes and handlers in the backend

Build the UI

Create React components using TypeScript and TailwindCSS

Deploy

Learn how to deploy your application to production

Troubleshooting

Problem: connection refused or no reachable serversSolution:
  1. Ensure MongoDB is running: make docker-run
  2. Check the MONGODB_URI in your .env file
  3. Verify Docker is running: docker ps
Problem: API calls fail with CORS errors or connection refusedSolution:
  1. Ensure backend is running on port 8080
  2. Check that CORS middleware is enabled in main.go
  3. Verify the API URL in your frontend code
Problem: Authentication fails with invalid tokenSolution:
  1. Ensure SESSION_KEY is set in .env
  2. Check that the token hasn’t expired (24 hour validity)
  3. Verify the token is being sent in requests
Problem: address already in use errorSolution:
  • Backend: Change PORT in .env
  • Frontend: Vite will automatically try the next available port
  • Or kill the process using the port: lsof -ti:8080 | xargs kill

Build docs developers (and LLMs) love