Building a CRUD Interface on the Scaffold with AI

This guide is a schaffolding walkthrough. It uses the existing React + Vite + Express scaffold and the papers table from schema.sql.

The goal is not just to end with a working app. The deeper goal is to model a disciplined way to use AI to extend a codebase step by step without losing control of the design.

It is based on this project: https://github.com/jimskon/Demo-Scadfold-project


1. What we already have

The scaffold currently contains:

  • a React frontend in client/
  • an Express backend in server/
  • a papers table in schema.sql
  • .env already populated with database credentials
  • a simple API with:
    • GET /api/hello
    • GET /api/status

The papers table looks like this:

  • id
  • title
  • authors
  • year
  • url
  • status (to_read, reading, read)
  • tags
  • summary
  • notes
  • date_added
  • date_read

This is enough to build a complete CRUD example.


2. The goal

  1. inspect the starting system
  2. make design decisions before coding
  3. ask AI for one bounded change at a time
  4. test after each change
  5. refine behavior and validation deliberately
  6. keep the code understandable

This is much better than saying: “Build me a full CRUD app.”


3. Scope

Core work

  • connect Express to MySQL
  • add backend CRUD routes for papers
  • add Bootstrap to the React app
  • replace the starter page with a papers UI
  • support:
    • list all papers
    • add a paper
    • edit a paper
    • delete a paper

Important design topics

  • required vs optional fields
  • frontend vs backend validation
  • how to report errors to the user
  • how to keep data contracts simple and predictable

Login

Lets keep it intentionally simple.

Very light:

  • no password hashing
  • no database-backed auth yet
  • one demo login screen
  • hardcoded users or credentials in .env
  • role is either admin or student
  • student can view only
  • admin can create, edit, delete

That gives us role-based UI without letting login swallow the process.


4. Architectural decisions to make before asking AI for code

Decision 1: Validation rules

Suggested rules for this demo:

  • title: required, non-empty
  • year: optional, but if present must be an integer in a reasonable range
  • url: optional, but if present should look like a URL
  • status: required, must be one of to_read, reading, read
  • everything else: optional
  • if status = read, then date_read may be set; otherwise it can be null

Decision 2: Where validation happens

Use both layers, but for different reasons:

  • frontend validation for quick user feedback
  • backend validation as the source of truth

The frontend helps the user. The backend protects the system.

Decision 3: Error response format

Lets pick one format and keep it consistent.

{
"ok": false,
"error": "Validation failed",
"details": {
"title": "Title is required",
"year": "Year must be between 1900 and 2100"
}
}

Success format:

{
"ok": true,
"data": { ... }
}

Decision 4: Single source of truth

Lets eep the database and backend contract authoritative.

We should not not scatter business logic across many React components.

Decision 5: UI structure

Suggested UI:

  • top title bar
  • table of papers
  • button to add a paper
  • modal or inline form for add/edit
  • alerts for success and error messages

5. Steps to creation


Step 0. Inspect the scaffold before changing anything

Goal

Understand the existing structure and confirm what is already working.

Lets reveiw

  • show server/index.js
  • show client/src/App.jsx
  • show schema.sql
  • run the app
  • demonstrate /api/status

Important point

Never ask AI to modify a codebase you have not first inspected.

Suggested AI prompt

I have a small full-stack scaffold with a React client and an Express server. Here are the current files. Explain the current architecture, identify what is already working, and tell me the minimum set of changes needed to turn this into a CRUD app for the papers table.

Step 1. Connect the Express server to MySQL

Goal

Move from a static scaffold to a database-backed server.

What to add

  • server/db.js
  • a MySQL connection pool using mysql2/promise
  • environment variables for DB host, port, user, password, and database name

Suggested AI prompt

Add database connectivity to this Express server using mysql2/promise and a connection pool. Create a clean db.js file and update the server only as needed. Assume the .env file already contains DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, and DB_NAME. Show the exact code for db.js and any needed edits.

What to test

  • restart server
  • add a temporary route like /api/db-test
  • run a simple SELECT NOW()

Step 2. Add a backend route to list all papers

Goal

Build the first real feature in the smallest possible slice.

Route

  • GET /api/papers

Suggested behavior

  • return papers ordered by date_added DESC
  • wrap response in { ok: true, data: rows }

Suggested AI prompt

Using this Express + mysql2 scaffold, add a GET /api/papers route that fetches all rows from the papers table ordered by date_added descending. Use the existing connection pool. Return JSON in the form { ok: true, data: rows } and return a 500 error in the form { ok: false, error: '...' } if something fails. Show the full updated server/index.js.

What to test

  • call route in browser or with curl
  • confirm records come back
  • test failure case if DB name is wrong

Important

Start with read-only features. CRUD should begin with the easiest successful path.


Step 3. Add Bootstrap to the frontend

Goal

Improve the UI quickly without writing custom CSS.

What to add

  • install bootstrap
  • import Bootstrap CSS in main.jsx

Suggested AI prompt

Show me the exact steps to add Bootstrap to a Vite React frontend. Then update my main entry file so Bootstrap CSS is loaded correctly. Keep the existing app structure intact.

What to test

  • verify styling changes
  • use a simple Bootstrap container, table, and button

Step 4. Replace the starter React page with a papers list page

Goal

Have React call GET /api/papers and render the data.

Suggested UI first pass

  • page title
  • “Add Paper” button
  • Bootstrap table with columns:
    • title
    • authors
    • year
    • status
    • actions
  • loading indicator
  • error alert

Suggested AI prompt

Replace this starter React App with a Bootstrap-based papers list page. Fetch data from /api/papers, show a loading message, show an error alert if the request fails, and render the papers in a Bootstrap table with columns for title, authors, year, status, and actions. Keep it in a single App.jsx for now unless there is a strong reason to split components.

What to test

  • empty table state
  • table with data
  • backend down

Important

AI should be asked for a bounded UI milestone, not the final polished system all at once.


Step 5. Add the Create form

Goal

Support adding a new paper.

Route

  • POST /api/papers

Backend validation to implement

  • title required
  • status must be valid
  • year must be integer if present

Frontend behavior

  • Bootstrap form or modal
  • submit button
  • show field-level or form-level errors
  • refresh list after success

Suggested AI prompt for backend

Add a POST /api/papers route to my Express server. Validate title, status, and year. Return 400 with { ok: false, error: 'Validation failed', details: { ... } } for invalid input. Insert the row into the papers table and return the created record or insert id in { ok: true, data: ... }.

Suggested AI prompt for frontend

Extend my Bootstrap React papers page to include a form for creating a paper. The form should include title, authors, year, url, status, tags, summary, notes, and date_read. Add basic client-side validation for title and year, submit to POST /api/papers, show validation errors clearly, and refresh the table after a successful create.

Lets consider

  • Should tags be a comma-separated string or something more structured?
  • Should summary and notes both be multiline fields?
  • Should date_read appear only when status is read?

Consider

Validation is not a detail to add later. It is part of the design.


Step 6. Add Edit

Goal

Support updating existing papers.

Route

  • PUT /api/papers/:id

Suggested UI

  • “Edit” button in each row
  • open form prefilled with row values
  • reuse the same form component for add and edit if possible

Suggested AI prompt

Refactor my React papers CRUD UI so the add form can also be used for editing. Add an Edit button for each paper, prefill the form with the selected row, submit updates to PUT /api/papers/:id, and keep the UI simple and readable for students.

Step 7. Add Delete

Goal

Complete CRUD.

Route

  • DELETE /api/papers/:id

Suggested UI behavior

  • delete button in each row
  • confirmation prompt before deleting
  • refresh list afterward

Suggested AI prompt

Add delete support to this papers CRUD app. On the backend, add DELETE /api/papers/:id. On the frontend, add a Delete button in each row with a confirmation step. After deletion, refresh the list and show a Bootstrap success or error alert.

Delete is easy to code and easy to misuse. Good software makes destructive actions explicit.


Step 8. Improve validation and error reporting

Goal

Make the app feel trustworthy.

  • What should happen if the server is down?
  • What should happen if the database rejects a value?
  • Should the frontend show one general message or per-field messages?
  • What counts as a user error versus a system error?

Good practice for this project

  • field-level validation on forms
  • general alert for server/network errors
  • backend always returns structured JSON errors
  • React should not assume every error response has the same shape unless you designed it that way

Suggested AI prompt

Review this Express + React CRUD app and improve the validation and error-reporting flow. I want a clear distinction between field validation errors, server errors, and network errors. Keep the code beginner-friendly and use a consistent JSON response structure from the backend.

A working CRUD demo is not enough. A good CRUD demo handles mistakes cleanly.


Step 9. Add a very small login with roles (optional 10-minute extension)

If you include login, keep it deliberately tiny.

Recommended tiny version

  • React login form with username and password
  • backend route POST /api/login
  • credentials checked against values in .env or a tiny in-memory array
  • response includes role: admin or student
  • store current user in React state only
  • hide create/edit/delete for student

This is not production authentication. That is fine. It is a demo for role-based UI and route design.

Suggested AI prompt

Add a very small demo login system to this scaffold. Keep it intentionally simple for classroom use: no database users, no hashing, no sessions yet. Use a POST /api/login route that checks credentials against a small hardcoded list or environment variables and returns { ok: true, data: { username, role } }. In the React frontend, show a login form first, store the logged-in user in state, and allow only admin users to create, edit, or delete papers. Students should have read-only access.


6. How to keep AI use disciplined

This part matters as much as the code.

Rule 1

Do not ask for everything at once.

Bad:

Build me a full papers app with login and bootstrap.

Better:

Add only GET /api/papers using the existing scaffold and show the exact code changes.

Rule 2

Paste in the real current code.

Do not let AI guess your existing files.

Rule 3

State constraints clearly.

Example:

  • keep Express in one file for now
  • do not add TypeScript
  • use Bootstrap only
  • keep the JSON response format consistent
  • do not add authentication libraries yet

Rule 4

Test after every AI-generated change.

Rule 5

Refactor only after the feature works.

First make it work. Then make it cleaner.


7. Project Shape

Backend

Possible files:

  • server/index.js
  • server/db.js
  • optionally later:
    • server/routes/papers.js
    • server/utils/validatePaper.js

Frontend

Possible files:

  • client/src/App.jsx
  • optionally later:
    • client/src/components/PaperForm.jsx
    • client/src/components/PapersTable.jsx
    • client/src/components/LoginForm.jsx

For the first classroom pass, keeping things in fewer files is often better.


8. Concrete validation policy for the papers table

A reasonable classroom policy would be:

  • title
    • required
    • trim whitespace
    • minimum 1 character after trim
  • authors
    • optional string
  • year
    • optional
    • integer between 1900 and 2100
  • url
    • optional
    • must begin with http:// or https:// if provided
  • status
    • required
    • one of to_read, reading, read
  • tags
    • optional comma-separated string
  • summary
    • optional multiline string
  • notes
    • optional multiline string
  • date_read
    • optional
    • if status is not read, allow null
    • if status is read, may be provided

You can keep this simple without pretending it is perfect.


9. Concrete error policy for the program

Use these three categories:

Validation error

User entered bad data.

Example:

  • missing title
  • bad year
  • invalid status

Return 400.

Not found error

User tried to edit or delete a record that does not exist.

Return 404.

Server error

Something broke in the backend or database.

Return 500.

This makes the system behavior easier to reason about.


11. Best prompts for the whole workflow

Here is a compact sequence you can reuse.

Prompt A — inspect first

I am going to extend an existing React + Vite + Express scaffold. Here are the current files: [paste files]. Explain the current architecture and propose the smallest sequence of changes needed to build a CRUD app for the papers table in schema.sql.

Prompt B — add DB connection

Using this existing Express scaffold, add a mysql2/promise connection pool in db.js and show the minimal edits needed to use environment variables DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, and DB_NAME.

Prompt C — add first read route

Add only GET /api/papers to this server. Use the connection pool, order by date_added desc, and return { ok: true, data: rows } or a structured error object.

Prompt D — add Bootstrap UI

Replace the starter React page with a Bootstrap-based page that fetches /api/papers and shows them in a clean table with loading and error states.

Prompt E — add create

Add POST /api/papers with backend validation for title, year, and status. Then add a Bootstrap form in React that submits to it and displays validation errors clearly.

Prompt F — add edit

Refactor the papers form so it supports both create and edit. Add PUT /api/papers/:id and keep the code beginner-friendly.

Prompt G — add delete

Add DELETE /api/papers/:id and a Delete button with confirmation in the React table. Refresh the list after deletion.

Prompt H — improve validation and error flow

Review this CRUD app and improve validation, error handling, and user feedback while keeping the code simple enough for an introductory software development course.

Prompt I — tiny role-based login

Add a tiny classroom demo login with admin and student roles. Keep it intentionally simple and do not use sessions or a database users table yet. Students should be read-only; admins can perform CRUD.

Scroll to Top