A general store with honest stock counts, search that returns real matches and a one-page checkout.
CommerceTypeScript · PythonGitHub @GroovierHenOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
A general store built in a day for a hiring assessment. The brief was to rebuild amazon.com using it as a reference, not a blueprint. Stockroom keeps Amazon's flow (browse, search, product, cart, checkout, orders) and changes what gets in a shopper's way. One Next.js app and one Postgres database. No accounts, no payment, no ads. • Live site: https://stockroom-store.vercel.app • Repository: https://github.com/GroovierHen/stockroom • How it was built: every prompt and final response is in .agent-logs/, and CAPTURE-TEST.md shows the capture working. [README 설치·사용 부분 발췌] SetupRead the full README ↗
A general store built in a day for a hiring assessment. The brief was to rebuild amazon.com using it as a reference, not a blueprint. Stockroom keeps Amazon's flow (browse, search, product, cart, checkout, orders) and changes what gets in a shopper's way.
One Next.js app and one Postgres database. No accounts, no payment, no ads.
.agent-logs/, and
CAPTURE-TEST.md shows the capture working.| What | Why |
|---|---|
| The flow: browse, search, product page, cart, checkout, order history | Shoppers already know it, so there is nothing to learn. |
| A search box at the top of every page | Search is how most people start. |
| Category navigation under the header | It answers "what do you sell" without a click. |
| Star ratings with a count on every product | They are the fastest signal of quality. |
| Order history with a page per order | People check what they bought and where it is going. |
| What | Why |
|---|---|
| Sponsored results and ads | They put products the shopper did not ask for above the ones they did. |
| The sign-in wall | A visitor can browse, add to cart, order and see past orders without an account. A cookie identifies the browser. |
| Payment | Out of scope for the assessment. Checkout stops at "Place your order" and says nothing is charged. |
| Third-party sellers | One seller means one price and one stock count per product. |
| Prime upsells | They interrupt the purchase to sell something else. |
| Recommendation carousels | They push the product's own details down the page. |
| Wish lists | They need accounts, and the cart already holds things for later. |
| Writing reviews | Ratings are shown read only. Collecting reviews needs accounts and moderation. |
| Numbered result pages | Next and Previous are enough, and they stay correct while the catalog changes. |
| What | Why it is better to use |
|---|---|
| Search results contain only real matches | Nothing is padded with loosely related products. A product is listed because its name or description matches. |
| Sort and aisle filter sit above the results, always visible | No sidebar of 40 filters, and nothing hidden behind a menu on a phone. |
| Search tolerates typos | "iphne" finds iPhones. The page says when it is showing close matches instead of exact ones. |
| Price, stock and "Add to cart" are one box at the top of the product page | Those three answer "can I buy this and for how much". Nothing sits between them. |
| Stock is the real count | The product page shows the number on the shelf, and "Only N left" at five or fewer. |
| Running out of stock is explained, not just refused | If stock runs out while ordering, checkout names the item, says how many are left and offers "Change to N" as one click. |
| Cart changes show at once | The header count and the cart lines update on click, before the server answers. |
| Checkout is one page | A shipping form, the order, and a single "Place your order" button. |
| Pages load from cache | Only the cart count, cart, checkout and orders are rendered per visitor. Everything else is prerendered. |
| Its own name, colours and type | Stockroom is green and white, set in one typeface (Archivo) at three widths. It is not a copy of Amazon's look. |
You need Bun 1.x, Node 20 or newer (Playwright's test runner needs Node), and a Postgres database. The project is set up for Supabase through the Vercel Marketplace.
bun install
vercel link # once, to connect the folder to the Vercel project
vercel env pull # writes the database variables to .env.local
bun run db:migrate # creates the tables
bun run db:seed # loads 208 products in 8 categories
bun run dev # http://localhost:3000
Without Vercel, copy .env.example to .env.local and fill in the two connection strings.
| Command | What it does |
|---|---|
bun run dev | Starts the app |
bun run build | Builds for production |
bun run typecheck | tsc --noEmit |
bun run lint | ESLint |
bun test | Unit and integration tests, against a real Postgres in the test schema |
bun run test:e2e | Playwright: builds, starts the app and runs the whole purchase |
bun run db:migrate | Applies the SQL files in drizzle/ |
bun run db:seed | Loads the catalog. Safe to run again; it also resets stock |
bun test drops and rebuilds a schema named test on every run. It never touches the schema
the app reads. bun run test:e2e places a real order in the app's database, for two units of a
product seeded with 150. Set E2E_BASE_URL to run it against a deployed site.
Run bunx playwright install chromium once before the first end-to-end run.
The tests talk to the real database, so bun test takes a few minutes when Postgres is on
another continent and a few seconds when it is local.
Vercel builds and deploys every push to main. The Supabase database is connected through the
Vercel Marketplace with the prefix SUPABASE_, which supplies SUPABASE_POSTGRES_URL and
SUPABASE_POSTGRES_URL_NON_POOLING to the build and to the running app. Run bun run db:migrate
and bun run db:seed against the database before the first deploy: the build prerenders pages
from it.
The app uses Supabase as plain Postgres, through node-postgres. It does not use the Supabase Data API, so every table has row level security turned on with no policies, which closes that API to the tables. The app connects as the table owner and is not affected.
src/app/ pages and Server Actions (App Router)
src/components/ UI, server components unless they need the browser
src/lib/ queries and rules: products, cart, orders, cached reads
src/db/ Postgres pool, Drizzle schema, migrate and seed
drizzle/ SQL migrations, the source of truth for the schema
seed/ the catalog: a public sample dataset plus 14 products written here
tests/ bun tests against Postgres
e2e/ the Playwright purchase test
.agent-logs/ every prompt and final response from the build, captured by a hook
use cache)
are prerendered into it. Anything per visitor reads the cookie inside <Suspense> and streams in.products and the tag of every product on the page.
Product content (title, description, images) is cached for days under product:{id}. Price
and stock use the same tag with a lifetime of minutes. Placing an order invalidates the tag of
every product in it. The cart, cart count, checkout and orders are never cached.after loads the next page and before the previous one. OFFSET is
never used, so pages stay correct while rows are added, and cost the same at any depth.websearch_to_tsquery over a stored tsvector (title weighted above description),
ranked with ts_rank. A name that contains the query text also matches. If nothing matches,
the query falls back to trigram word similarity on the title.SELECT ... FOR UPDATE in ascending id order, check every quantity against stock, decrement,
insert the order with title and price copied from the product, delete the cart items, commit.
The fixed lock order means two carts that share products cannot deadlock. If anything is
short, the transaction rolls back and returns the short items. This is the only code that
changes stock.visitor_id cookie is created on the first add to cart. The cart
and orders belong to that id.next/image. 14 more were written for
this project to reach 200, and use local placeholder images.bun --bun). The Next.js docs say Cache
Components is only guaranteed on Node. Under Bun the build output is identical to Node's, but
next start logs "unhandledRejection: AbortError" when a browser cancels a request. The app
keeps serving.Payment of any kind. Login and accounts. Seller pages, admin pages, writing reviews, recommendations, wish lists and emails. Redis, Elasticsearch, message queues and microservices.
bun run typecheck, bun run lint, bun run build and bun test pass at every slice commit.
The tests cover: