sxsphinxstack

Skills / Database basics

Database basics

Give their app real persistence with a hosted database. A free-tier Postgres or SQLite, a schema for their actual data, and full CRUD from their app. Use when localStorage stops being enough, when data must survive across devices or users, or when they ask "how do I store this properly".

Use this skill. Nothing to install.

Open in ChatGPT Open in Claude prefilled and ready; just hit send
for Gemini, Copilot, or Cursor: paste it, then say "use the database basics skill"

Don't have an agent?  ·  Raw file: skills/database-basics.md

Watch the first two minutes

This is how a session goes, including the part everyone is afraid of. Click through it.

(pastes the skill) my workout tracker loses everything when i clear my browser. how do i store this properly?
localStorage lives in one browser on one device; a database lives on a host and outlasts your laptop. First: what does one entry in your tracker look like?
date, exercise, sets, reps, and a note. but SQL looks terrifying, do i actually have to learn it
You'll type a little of it by hand, on purpose: the CREATE TABLE and a few SELECTs in the provider's console, so the layer under any client library isn't magic. It reads closer to English than you'd guess from the reputation.
does a hosted database cost money?
Free tiers cover this: hosted Postgres or SQLite. I'll say the limits before you commit to one, like storage caps and databases that pause after inactivity. No card details anywhere.
ok so what's step one
Paper before console. One entry becomes one row, every field gets a type, and we both say why. Then you write the CREATE TABLE yourself, run it, and INSERT three real workouts by hand before any app code touches the database.

Scripted example of a real session.

Do I really have to learn SQL?

A little, by hand, and it's the part that pays off longest. The skill has you design the schema on paper around your actual data (two tables maximum, and the second only when a real one-to-many shows up), then type the CREATE TABLE and a few queries yourself in the database console. Client libraries come after, once the layer they wrap is real to you. The finish line is being able to write a SELECT with a WHERE clause unaided. These projects each stand on a schema someone designed this way:

Speedrun game with a real leaderboard Club dues tracker Team stats board

What you end up with

A hosted database with a schema you can explain, and your app doing full CRUD against it. Here is what the workout tracker's database looks like when it's done.

Example
THE SCHEMA, TYPED BY HAND IN THE CONSOLE
CREATE TABLE workouts (
  id       serial PRIMARY KEY,
  day      date NOT NULL,
  exercise text NOT NULL,
  sets     int,
  reps     int,
  note     text
);
A QUERY YOU CAN WRITE UNAIDED AT THE END
SELECT day, exercise, sets, reps
FROM workouts
WHERE day >= '2026-07-01'
ORDER BY day;
THE DATABASE DEFENDING ITSELF (TRIGGERED ON PURPOSE)
INSERT INTO workouts (exercise) VALUES ('squats');
ERROR: null value in column "day" violates
       not-null constraint
  1. Every field has a type and a reason. One entry became one row; you said why day is a date and why it can't be null. That modeling habit is the durable lesson.
  2. You break it once on purpose. Seeing the NOT NULL error fire teaches what the database refuses on your behalf, before bad data ever gets in.
  3. Persistence is proven, then localStorage is deleted. Redeploy the app, open it on your phone, the workouts are still there. Then the old storage code goes.

Questions people actually ask

Is SQL hard to learn?

The slice you need here is small: CREATE TABLE, INSERT, SELECT with a WHERE, UPDATE, DELETE. You type each one by hand in the console before app code hides them. Most people are surprised how readable it is.

Is a hosted database free?

Free tiers of hosted Postgres and SQLite cover a personal app comfortably. The skill names the limits before you commit: storage caps, and some free databases pause after inactivity. No card details anywhere.

Where does the connection string go?

It's a secret, so: env vars on the server side, a gitignored .env locally, never in frontend code, and proven absent from git. If you connect from the browser via a service like Supabase, the skill explains which key is publishable and turns on row-level security before any write works.

How many tables should I make?

Two at most, and the second only when a real one-to-many appears in your data (a workout with many sets, an order with many items). Starting with one well-typed table teaches more than a diagram of eight empty ones.

What happens to the data already in localStorage?

You migrate it: read the entries out, INSERT them as rows, check the count matches. Then the localStorage code is deleted from the app so there's exactly one source of truth.

Where to go from here

Shared data raises the next question: whose rows are whose?

Auth basics: rows owned by users First SQL: go deeper on queries Backend basics: an API in front

Or build something that needs real persistence:

Tool lending library Turn-based game two browsers can play Alumni directory

Ideas to use it on

Curious? Read the full skill — the exact instructions your agent gets
---
name: database-basics
category: code
description: Give their app real persistence with a hosted database. A free-tier Postgres or SQLite, a schema for their actual data, and full CRUD from their app. Use when localStorage stops being enough, when data must survive across devices or users, or when they ask "how do I store this properly".
---

# database-basics

Move someone's app from localStorage to a real database: a
hosted free-tier database with a schema designed around their actual
data, and their app reading and writing it. The durable lesson is
modeling. Tables, rows, and types that match the thing they are
tracking.

## Ground rules

- Use their real data. The best schema exercise is the app they
  already built (build-web-app leaves exactly this). If they have no
  app, pick one small enough that the whole loop still fits in a
  session.
- Compare the current official plans for a hosted Postgres or SQLite service,
  or use SQLite on a server they already control. Record storage, inactivity,
  export, and backup limits before committing. No card details anywhere.
- Their account, their connection string. Database URLs and service
  keys are secrets: env vars on the server side, gitignored `.env`
  locally, never in frontend code. If they use Supabase from the
  browser, explain which key is publishable and which must never
  ship, and turn on row-level security before any write works.
- Design the schema on paper first. One entry becomes one row; every
  field gets a type; you both say why. Two tables maximum, and only
  add the second when a real one-to-many appears in their data.
- SQL is not optional. Even behind a client library, they type at
  least the CREATE TABLE and a few SELECTs by hand in the database
  console, so they can inspect the layer underneath the client library.

## The path

1. Model out loud: what is one entry, what are its fields, what type
   is each, what makes a row unique. Write the CREATE TABLE together
   and run it in the provider's SQL console.
2. Seed and query by hand: INSERT three rows, SELECT them back,
   UPDATE one, DELETE one, all in the console. Now the database is
   real before any app code touches it.
3. Connect from their code with the connection string in an env var.
   First read: the app lists rows from the database instead of
   localStorage.
4. Complete the loop: create, update, delete from the app. Bad input
   rejected before it reaches the database, and a NOT NULL or type
   error triggered once on purpose so they see the database defend
   itself.
5. Prove persistence: redeploy the app, open it on their phone, data
   still there. Delete localStorage use from the code.
6. README note in their words: what the schema is and where the
   connection string lives for anyone cloning.
7. Export a small backup or schema dump and document how it would be restored.

## Done

- A hosted database with a schema they designed and can explain
- Their app doing full CRUD against it; localStorage retired
- Data survives redeploys and shows up across devices
- Connection string and keys in env vars only, proven absent from git
- A tested export path and restore note, so the provider is not the only copy
- They can write a SELECT with a WHERE clause unaided

Then: auth-basics, since data shared by everyone raises the question
of who is allowed to see and change which rows.