Skip to main content

Module 04: Frontend Deployment

Objective

Deploy the HTML/CSS/JS frontend on app-server and verify it communicates with the Go backend from Module 03. By the end, you will have a working web UI for the Customer Information App.

Prerequisites

  • Module 03 complete (Go backend running on app-server at port 8080)
  • Frontend source files available in src/frontend/ on your Mac

1. Understanding the Frontend Architecture

The frontend is a simple single-page application built with plain HTML, CSS, and JavaScript — no frameworks, no build tools.

How it works:

  • The Go backend already serves static files from ./static/ (via http.FileServer in main.go)
  • The frontend calls the API using relative URLs (e.g., /api/customers instead of http://192.168.56.12:8080/api/customers)
  • Because the frontend and API are served from the same origin, there are no CORS issues
  • The three files (index.html, style.css, app.js) go in ~/customerapp/static/ on app-server

File overview:

FilePurpose
index.htmlPage structure: login form, customer table, add/edit form
style.cssVisual styling: layout, colors, table, buttons
app.jsAll logic: login, CRUD operations, DOM manipulation

2. Transfer Frontend Files to app-server

First, create the static directory on app-server:

ssh app-server "mkdir -p ~/customerapp/static"

Copy the frontend files from your Mac:

scp src/frontend/* app-server:~/customerapp/static/

Verify the files are in place:

ssh app-server "ls -la ~/customerapp/static/"

You should see:

index.html
style.css
app.js

3. Restart the Go Backend

The Go backend is already configured to serve static files from ./static/. Restart it to make sure everything is clean:

ssh app-server "sudo systemctl restart customerapp"

Check the service status:

ssh app-server "sudo systemctl status customerapp"

Now open your browser and go to:

http://192.168.56.12:8080/

You should see the login page with "Customer Information App" as the heading, a username field, a password field, and a Login button.

4. Walk Through the Frontend Code

index.html

The page has two main sections controlled by the hidden CSS class:

  • Login section (#login-section): Shown by default. Contains the username/password form.
  • App section (#app-section): Hidden by default. Contains the customer table and add/edit form. Shown after successful login.

style.css

Provides clean, minimal styling:

  • Centered container with max-width 800px
  • Table with borders and alternating row colors
  • Blue primary buttons, red danger buttons
  • A .hidden class that sets display: none

app.js

All API communication uses fetch() with relative URLs:

  • Login flow: POST /api/login with JSON body. On success, the server sets a session cookie, and the JS hides the login section and shows the app section.
  • Load customers: GET /api/customers returns a JSON array. Each customer is rendered as a table row.
  • Create customer: POST /api/customers with JSON body containing name, email, phone, address.
  • Update customer: PUT /api/customers/{id} with JSON body.
  • Delete customer: DELETE /api/customers/{id} after a confirm dialog.
  • Session check: On page load, the app checks for a session cookie. If found, it skips the login screen and loads customers directly.
  • Logout: Deletes the session cookie and shows the login form again.

API_BASE is set to an empty string — all fetch calls use relative paths since the frontend and backend share the same origin.

5. Test the Full Flow from the Browser

Step 1: Open the app

Navigate to http://192.168.56.12:8080 in your browser.

What you should see: A centered white card with "Customer Information App" heading and a login form with username and password fields.

Step 2: Login

Enter admin as the username and admin123 as the password. Click Login.

What you should see: The login form disappears. A header appears saying "Welcome, admin!" with a red Logout button. Below that is an "Add Customer" form and an empty customer table with columns: ID, Name, Email, Phone, Address, Actions.

Step 3: Add a customer

Fill in the form:

  • Name: John Doe
  • Email: john@example.com
  • Phone: 555-0100
  • Address: 123 Main St

Click Add Customer.

What you should see: The form clears. The table now shows one row with John Doe's information and Edit/Delete buttons.

Step 4: Edit the customer

Click the Edit button on John Doe's row.

What you should see: The form title changes to "Edit Customer". The form fields are populated with John's current data. A Cancel button appears next to the Update Customer button.

Change the phone to 555-0199 and click Update Customer.

What you should see: The table updates to show the new phone number.

Step 5: Delete the customer

Click the Delete button on John Doe's row.

What you should see: A browser confirmation dialog asks "Are you sure you want to delete this customer?" Click OK. The row disappears from the table.

Step 6: Logout

Click the red Logout button.

What you should see: The app section disappears and the login form is shown again.


Troubleshooting

"Login fails"

  • Is the Go backend running? Check with: ssh app-server "sudo systemctl status customerapp"
  • Are the credentials correct? The default is admin / admin123 (set up in the database from Module 02)
  • Check the backend logs: ssh app-server "sudo journalctl -u customerapp --no-pager -n 20"

"Blank page"

  • Are the static files in the right directory? Check: ssh app-server "ls ~/customerapp/static/"
  • The files must be in ~/customerapp/static/, not in a subdirectory like ~/customerapp/static/frontend/
  • Restart the service after adding files: ssh app-server "sudo systemctl restart customerapp"

"API calls fail"

  • Open the browser developer console (F12 > Console tab) and look for error messages
  • Check that the Go backend is running and healthy: curl http://192.168.56.12:8080/health
  • If you see 401 errors, your session may have expired — try logging in again

"CORS errors in console"

  • This should not happen if you are accessing the app at http://192.168.56.12:8080 — the frontend and API are on the same origin
  • If you are accessing via a different URL or port, CORS errors will appear. Always use the same origin

What We Built

At this point you have a fully functional web application:

  • db-server (192.168.56.11): PostgreSQL database with customer and user tables
  • app-server (192.168.56.12): Go backend serving the API and static frontend files on port 8080

In the next module, we will add Nginx as a reverse proxy to sit in front of the Go backend.