Assignments > Tutorial 11: Create Your Own Backend
Due Wed, 04/22 at 11:59pm
This tutorial walks through the API Generator that you will be using for your final project. The generator is designed so that you:
- Describe resources in
api.config.yaml, - Run
npm run generate, and - Get a SQLite-backed REST API with docs and a small data grid UI.
Please consult the API Generator cheatsheet for more information.
1. Setup
-
Create a folder named
tutorial11inside yourcsci344/tutorialsfolder (adjust if your course uses a different layout). -
Download the API generator starter here: https://github.com/csci344/api-generator/archive/refs/heads/main.zip
-
Unzip the archive and move the unzipped project folder inside
tutorial11. You might see a name likeapi-generator-main— that is your project root (feel free to rename it). -
Open your
csci344folder in VS Code -
Open your
api-generator-mainfolder integrated terminal and run (one at a time):npm install npm run validate npm run generate npm run seed npm run devWhen the CLI asks to confirm destructive steps, type
yesor add--yesto the command. -
In the terminal, note the URL (often
http://localhost:3100). Keep the server running for the tasks below.
What just happened?
npm run validate
- checks that your
api.config.yamlis validnpm run generate
- builds / rebuilds the backend code from
api.config.yaml- creates / recreates the SQLite database schema
- writes the database file to
data/app.db- generates sample CSV files in
data/sample-data/- (Optional) Run
npm run seed
- reads the CSV files in
data/sample-data/- inserts sample data into the SQLite database
npm run dev
- starts the Express server
- serves your REST API (JSON endpoints)
- provides interactive API docs at
/api/docs- connects everything to your local database
2. Understanding the database
- In VS Code, install an extension that can open SQLite files. I recommend SQLite Viewer (search the Extensions marketplace for “SQLite”).
- Open the database file
data/app.db - Explore the tables. Compare what you see to the resources listed in
api.config.yamlat the project root.
Short Answer
Please create a file inside of your
tutorial11directory calledanswers.txt. Then, answer the following questions (and the subsequent questions latter in this tutorial):
- Name three tables that correspond to the Resource types that are defined in
api.config.yaml. Which table is not defined by your YAML but still exists? (Hint: accounts.)- Pick one resource table (e.g.
sneakers). Which columns look like they are referencing data in other tables (this is called a “foreign key”)?- What looks different between the required and optional fields in the database?
3. How seed works and editing the generated CSVs
When you run npm run generate, the script writes sample data as CSV files under data/sample-data/. Those rows are not in the database until you run npm run seed (this tutorial uses npm run seed -- --yes when the CLI asks for confirmation).
Install the Edit CSV extension in VS Code, open the CSVs in data/sample-data/, and change the sample values so the data fits a sneaker store (for example, rename brands or products to sneakers instead of the generic placeholders). Save your files, then run npm run seed -- --yes.
If you want to link to custom images, there are some located in
public/student/images/sneakers.
- A valid sample URL path that you could use is:
/student/images/sneakers/sneaker_0_0.png.- Feel free to copy other images to the
public/student/imagesfolder.
If you change api.config.yaml, run npm run generate again before npm run seed so the database and CSV templates match your resources.
3.1. Try it: “Edit CSV” in VS Code
-
In
data/sample-data/, pick a small CSV (for examplebrands.csv, or another resource from yourapi.config.yaml). Change at least one cell to something sneaker-themed and save the file. -
In the terminal, run:
npm run seed -- --yesIf you get SQL errors about duplicate keys or constraint failures, run
npm run generate -- --yesonce to reset the database and templates, put your sneaker-themed edits back into the new CSVs if they were archived, thennpm run seed -- --yesagain. -
Confirm the change in the database (SQLite Viewer on
data/app.db) or in/spreadsheetafter reloading data.
Short Answer
Answer in your
tutorial11/answers.txtfile:
- In one sentence: what is the difference between changing data with
npm run seedand changing data only through the REST API or data grid?- Why should you run
npm run generateagain beforenpm run seedif you just editedapi.config.yaml?
4. Edit data in the data grid
- With the server running, open a browser to http://localhost:3100/spreadsheet. The home page at
/also links to this UI (e.g./spreadsheet). - Log in using
admin/password - Choose a resource, load rows, and change at least one cell (or add a row, then save). Refresh the page or reload the list to confirm your change persisted.
- If the spreadsheet shows filters or search for that resource, try changing them a few times. Watch the address bar or your browser’s Network tab: notice how the URL for the list request changes (for example, the path may stay the same while query parameters after
?appear, change, or disappear).
Short Answer
Answer in your
tutorial11/answers.txtfile:
- How did the list request URL change when you applied the filter(s)? (Mention the path, any new or removed query parameters, or if only the Network tab showed a change.)
- Suppose your Sneakers API endpoint is
/api/sneakersandnameis marked queryable inapi.config.yaml. What URL would you use for aGETrequest that asks the server for sneakers whosenameincludes the substringrunning?
5. Interactive API docs (Swagger)
- Open
/api/docson the same origin as your server. - Use
POST /auth/loginwithadmin/password, copy thetokenfrom the response. - Click Authorize, paste
Bearer <token>(include the wordBearerand a space before the token if the UI expects the full scheme — follow what your docs UI shows). - Try at least two generated routes: for example list a public collection and create a row on a route that requires a logged-in user.
Short Answer
Answer in your
tutorial11/answers.txtfile:
- What is one difference between experimenting in
/api/docsand experimenting in the data grid?
6. Swap in the “campus trees” API
You will replace the stock api.config.yaml with a pre-written config about plants (each with latitude, longitude, and optional notes) and comments on campus fruit trees.
First, Backup your current config (optional but good practice):
cp api.config.yaml api.config.backup.yaml
Next, replace your current api.config.yaml with the following structure:
# Sample API: campus fruit trees and bushes
# Copy this file to the project root as api.config.yaml (backup the default first if you want).
resources:
- type: Plant
path: /api/plants
operations: [list, retrieve, create, update, delete]
fields:
- name: name
type: string
required: true
query: true
- name: image_url
type: image_url
required: true
query: true
- name: species
type: string
required: true
query: true
- name: planted_year
type: integer
- name: latitude
type: number
required: true
- name: longitude
type: number
required: true
- name: notes
type: text
permissions:
list: public
retrieve: public
create: user
update: owner
delete: owner
- type: Comment
path: /api/comments
operations: [list, retrieve, create, update, delete]
fields:
- name: body
type: text
required: true
- name: plant
type: Plant
required: true
query: true
permissions:
list: public
retrieve: public
create: user
update: owner
delete: owner
Rebuild your API and generate new fake data:
npm run validate
npm run generate -- --yes
npm run seed -- --yes
Restart npm run dev if the server was stopped. Feel free to edit your fake data spreadsheets (and then rerun npm run seed to insert it into your API).
When you’re done, open /api/docs again and confirm you see paths like /api/plants and /api/comments.
7. Add a PlantType relation (manual edit + regenerate)
Right now species is a free-text string. You will introduce a PlantType resource and link each Plant to a plant type so names stay consistent (e.g. “Apple”, “Pear”, “Fig”).
Do this by hand in api.config.yaml (do not copy the answer file until you have tried):
-
Add a new resource
PlantTypewith at least:type: PlantType,path: /api/plant-types, full CRUDoperations- Fields: e.g.
name(string,required,query: true) anddescription(text) permissionsblocks similar toPlant(public list/retrieve, user create, owner update/delete is fine)
-
Order matters: put
PlantTypein theresources:list beforePlantso it is easy to reason about dependencies (the generator will also order seed files correctly). -
On
Plant, remove thespeciesfield and add a relation field, for example:name: plant_typetype: PlantTyperequired: truequery: true(optional but useful)
-
Run
npm run validate. Fix YAML errors until it passes. -
Run
npm run generate -- --yesandnpm run seed -- --yes. -
In
/api/docs, create a few PlantType rows (POST requests), then create a Plant that references one of those ids asplant_type.
Short Answer
Answer in your
tutorial11/answers.txtfile:
- What is one advantage of introducing a separate
PlantTyperesource (with a relation fromPlant) instead of keepingspeciesas a plain string on every plant row?
8. Reflection and your project
Short Answer
Answer in your
tutorial11/answers.txtfile:
- Final project: List at least three REST paths you expect to need for your final project (they can be placeholders like
/api/...). For each, name:
- The resource
- the data fields you’ll need
- Which fields will be queryable
- One relationship you might add (e.g., Sneakers are linked a Brand resource in another table)
Completion Checklist and Submission
To submit this tutorial, commit and push all of your edits to GitHub and, paste a link to your GitHub Repository in the Moodle submission for Tutorial 11. Please ensure that you have completed all of the required tasks:
answers.txt (all of the green boxes)