FeaturesTemplatesShowcaseTownie
AI
BlogDocsPricing
Log inSign up
charmaine
charmainepersonalShopper
Remix of bgschiller/personalShopper
Public
Like
personalShopper
Home
Code
6
backend
3
docs
5
frontend
1
shared
1
.cursorrules
README.md
Branches
1
Pull requests
Remixes
History
Environment variables
4
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in miliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
…
README.md

Personal Shopper

Description

This is an AI-powered Grocery Shopping assistant that turns an imprecise list of items like "milk, bread, eggs" into a Kroger cart full of groceries. It relies on the Kroger API to search each item, then uses an LLM to decide which specific UPC to add to the cart (again, using the Kroger API). Once an item is selected, we store the UPC in the database so we can avoid consulting the LLM for that item again.

Households have preferences for which items to buy, and what priorities they have for each item. For example, we prefer to buy free range eggs and poultry, but don't particularly care whether they are organic or not. These details are stored in a database, which should also be consulted to add context to the LLM's decisions.

Kroger OAuth Implementation

The application now includes a complete OAuth2 flow for Kroger authentication:

Environment Variables Required

Set these in your Val Town environment:

  • KROGER_CLIENT_ID - Your Kroger API client ID
  • KROGER_CLIENT_SECRET - Your Kroger API client secret
  • KROGER_REDIRECT_URI - Your registered redirect URI (e.g., https://your-val.web.val.run/auth/callback)

OAuth Flow

  1. Login: User clicks "Connect with Kroger" → redirected to /auth/login
  2. Authorization: App redirects to Kroger's OAuth endpoint with proper parameters
  3. Callback: Kroger redirects back to /auth/callback with authorization code
  4. Token Exchange: App exchanges code for access/refresh tokens
  5. Profile Fetch: App gets user's Kroger profile ID
  6. Session: User is logged in with session cookie

Authentication Features

  • Secure Sessions: HTTP-only cookies with proper security settings
  • Token Refresh: Automatic refresh of expired access tokens
  • State Validation: CSRF protection using state parameter
  • User Management: Create/update users based on Kroger profile ID

Database Schema

The database consists of the following tables:

kroger_users_1

  • id - Unique user ID (primary key)
  • krogerProfileId - Kroger's unique user identifier
  • accessToken - Current OAuth access token
  • refreshToken - OAuth refresh token
  • tokenExpiresAt - Token expiration timestamp
  • preferredLocationId - User's preferred Kroger store location
  • createdAt / updatedAt - Timestamps

guidance_1

  • id - Unique guidance ID (primary key)
  • userId - Foreign key to kroger_users_1
  • itemName - Name of the item (e.g., "milk", "bread")
  • guidance - Textual preferences (e.g., "prefer free range eggs")
  • createdAt / updatedAt - Timestamps

selections_1

  • id - Unique selection ID (primary key)
  • userId - Foreign key to kroger_users_1
  • itemName - User's free text item name
  • upc - Selected product UPC code
  • productName - Full product name from Kroger
  • createdAt / updatedAt - Timestamps
  • Unique constraint on (userId, itemName)

API Endpoints

Authentication

  • GET /auth/login - Start OAuth flow
  • GET /auth/callback - OAuth callback handler
  • POST /auth/logout - Logout user
  • GET /api/user - Get current user info
  • PUT /api/user/location - Update preferred store location

Guidance Management

  • GET /api/guidance - Get all guidance for current user
  • GET /api/guidance/search?q=item - Search guidance by item name
  • POST /api/guidance - Create new guidance
  • PUT /api/guidance/:id - Update guidance
  • DELETE /api/guidance/:id - Delete guidance

Selection Management

  • GET /api/selections - Get all selections for current user
  • GET /api/selections/item/:itemName - Get selection for specific item
  • POST /api/selections - Create/update selection
  • PUT /api/selections/:id - Update selection
  • DELETE /api/selections/:id - Delete selection

Shopping Process

  1. The user supplies a list of items they want to buy.
  2. We search the Kroger API, getting a list of products that match the free text name.
  3. For each item, we:
    1. Try to find it in selections. If we can't find it there,
    2. Use full-text search to find the most relevant guidance. Then ask the LLM to decide which specific UPC to add to the cart. Store this in the selections table for next time.
  4. We use the Kroger API to add the item to the cart.
  5. Repeat for each item.

There is no need to check out the cart, as the user will review the cart in the app and make any necessary changes.

Secondary flows

  • The user can add new items to the guidance table.
  • The user can CRUD their selections.
  • The user can change their Kroger location ID.
  • The user can log out.

Tech Stack

  • TypeScript
  • Val.Town with SQLite integration
  • Hono for the API
  • TailwindCSS for styling
  • Kroger API for product data and cart management

File Structure

├── backend/
│   ├── index.ts              # Main HTTP handler with OAuth routes
│   ├── database/
│   │   ├── migrations.ts     # Database schema setup
│   │   └── krogerQueries.ts  # Database query functions
│   └── services/
│       └── krogerAuth.ts     # Kroger OAuth service
├── frontend/
│   └── index.html           # Single-page application
├── shared/
│   └── types.ts             # Shared TypeScript interfaces
└── docs/                    # Kroger API documentation

See .cursorrules for more details.

Go to top
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Product
FeaturesPricing
Developers
DocsStatusAPI ExamplesNPM Package Examples
Explore
ShowcaseTemplatesNewest ValsTrending ValsNewsletter
Company
AboutBlogCareersBrandhi@val.town
Terms of usePrivacy policyAbuse contact
© 2025 Val Town, Inc.