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/(viahttp.FileServerinmain.go) - The frontend calls the API using relative URLs (e.g.,
/api/customersinstead ofhttp://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:
| File | Purpose |
|---|---|
index.html | Page structure: login form, customer table, add/edit form |
style.css | Visual styling: layout, colors, table, buttons |
app.js | All 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
.hiddenclass that setsdisplay: none
app.js
All API communication uses fetch() with relative URLs:
- Login flow:
POST /api/loginwith JSON body. On success, the server sets asessioncookie, and the JS hides the login section and shows the app section. - Load customers:
GET /api/customersreturns a JSON array. Each customer is rendered as a table row. - Create customer:
POST /api/customerswith 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
sessioncookie. 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.