personalShopperoauth-setup.md13 matches
53When a user clicks "Connect with Kroger", they're redirected to:
54```
55https://api.kroger.com/v1/connect/oauth2/authorize?
56client_id=YOUR_CLIENT_ID&
57redirect_uri=YOUR_REDIRECT_URI&
68### 3. Token Exchange
69Your app exchanges the authorization code for:
70- `access_token`: Used to make API calls on behalf of the user
71- `refresh_token`: Used to get new access tokens when they expire
72- `expires_in`: How long the access token is valid (in seconds)
75Your app uses the access token to get the user's Kroger profile ID from:
76```
77GET https://api.kroger.com/v1/identity/profile
78Authorization: Bearer ACCESS_TOKEN
79```
115- If refresh fails, users will need to re-authenticate
116117## API Endpoints
118119Once OAuth is configured, these endpoints become available:
125126### User Management
127- `GET /api/user` - Get current user info
128- `PUT /api/user/location` - Update preferred store location
129130### Data Management
131- `GET /api/guidance` - Get user's shopping preferences
132- `POST /api/guidance` - Add new preference
133- `GET /api/selections` - Get user's saved product selections
134- `POST /api/selections` - Save new product selection
135136## Next Steps
1391401. **Test the full flow** with a real Kroger account
1412. **Implement product search** using the Kroger Products API
1423. **Add cart management** using the Kroger Cart API
1434. **Integrate AI/LLM** for intelligent product selection
1445. **Build the shopping list interface**
146## Support
147148For Kroger API issues:
149- [Kroger Developer Documentation](https://developer.kroger.com/documentation)
150- [Kroger Developer Support](https://developer.kroger.com/support)
personalShopperkroger-products.md10 matches
1## Products API (1.2.4)
23The Products API allows you to search the Kroger product catalog.
45### Rate Limit
67The Public Products API has a 10,000 call per day rate limit.
89For all Public APIs, we enforce the rate limit by the number of calls the client makes to the endpoint, not individual API operations. This means you can distribute the 10,000 calls across all API operations using the /products endpoint as you see fit.
1011### Pagination
18Note: Since searching by a term acts as a fuzzy search, the order of the results can change with each new request.
1920### API Operations
2122The Products API supports the following operations:
2324| Name | Method | Description |
69```sh
70curl -X GET \
71'https://api.kroger.com/v1/products?filter.brand={{BRAND}}&filter.term={{TERM}}&filter.locationId={{LOCATION_ID}}' \
72-H 'Accept: application/json' \
73-H 'Authorization: Bearer {{TOKEN}}'
79{
80"productId": "0001111041700",
81"productPageURI": "/p/kroger-2-reduced-fat-milk/0001111041700?cid=dis.api.tpi_products-api_20240521_b:all_c:p_t:",
82"aisleLocations": [
83{
159```sh
160curl -X GET \
161'https://api.kroger.com/v1/products/{{ID}}?filter.locationId={{LOCATION_ID}}' \
162-H 'Accept: application/json' \
163-H 'Authorization: Bearer {{TOKEN}}'
168"data": {
169"productId": "0001111041700",
170"productPageURI": "/p/kroger-2-reduced-fat-milk/0001111041700?cid=dis.api.tpi_products-api_20240521_b:all_c:p_t:",
171"aisleLocations": [
172{
1# Kroger Cart API
23## PUT `/v1/cart/add`
personalShopperkrogerAuth.ts1 match
1import { KrogerTokenResponse, KrogerProfileResponse } from "../../shared/types.ts";
23const KROGER_BASE_URL = "https://api.kroger.com";
45export class KrogerAuthService {
personalShopperkroger-authorize.md2 matches
84There are 3 grant type flows that the token endpoint offers:
8586authorization_code - Uses the code returned from the /authorize endpoint to get a token, allowing your service or application to make API requests on an end user's behalf, including accessing personal data. The service is only able to perform the actions specified in the approved scopes.
87client_credentials - Uses the client credentials to provide a token that allows your service or application to call endpoints that do not require user approval.
88refresh_token - Allows the application to "refresh" an access token that has expired. Refresh tokens are only granted when using the Authorization Code grant type. Using the refresh token eliminates the need to re-authenticate the customer when the access token expires.
89The access_token received from this step is sent to the endpoint being called to prove that your service or application is authorized to call the API. The token_type field indicates what type of token it is so that you can correctly pass it to the API.
9091### Parameters
personalShopperindex.ts12 matches
165166// Get current user info
167app.get("/api/user", async (c) => {
168const user = await getCurrentUser(c);
169if (!user) {
181182// Update user location
183app.put("/api/user/location", async (c) => {
184const user = await getCurrentUser(c);
185if (!user) {
199200// Get all guidance for current user
201app.get("/api/guidance", async (c) => {
202const user = await getCurrentUser(c);
203if (!user) {
210211// Search guidance
212app.get("/api/guidance/search", async (c) => {
213const user = await getCurrentUser(c);
214if (!user) {
226227// Create guidance
228app.post("/api/guidance", async (c) => {
229const user = await getCurrentUser(c);
230if (!user) {
247248// Update guidance
249app.put("/api/guidance/:id", async (c) => {
250const user = await getCurrentUser(c);
251if (!user) {
261262// Delete guidance
263app.delete("/api/guidance/:id", async (c) => {
264const user = await getCurrentUser(c);
265if (!user) {
275276// Get all selections for current user
277app.get("/api/selections", async (c) => {
278const user = await getCurrentUser(c);
279if (!user) {
286287// Get selection by item name
288app.get("/api/selections/item/:itemName", async (c) => {
289const user = await getCurrentUser(c);
290if (!user) {
303304// Create or update selection
305app.post("/api/selections", async (c) => {
306const user = await getCurrentUser(c);
307if (!user) {
325326// Update selection
327app.put("/api/selections/:id", async (c) => {
328const user = await getCurrentUser(c);
329if (!user) {
339340// Delete selection
341app.delete("/api/selections/:id", async (c) => {
342const user = await getCurrentUser(c);
343if (!user) {
personalShopperindex.html3 matches
231
232try {
233const response = await fetch('/api/user/location', {
234method: 'PUT',
235headers: { 'Content-Type': 'application/json' },
250async function loadGuidanceCount() {
251try {
252const response = await fetch('/api/guidance');
253const guidance = await response.json();
254document.getElementById('guidance-count').textContent = guidance.length;
260async function loadSelectionsCount() {
261try {
262const response = await fetch('/api/selections');
263const selections = await response.json();
264document.getElementById('selections-count').textContent = selections.length;
personalShopper.cursorrules10 matches
20### 2. HTTP Vals
2122- Create web APIs and endpoints
23- Handle HTTP requests and responses
24- Example structure:
66- Generate code in TypeScript
67- Add appropriate TypeScript types and interfaces for all data structures
68- Prefer official SDKs or libraries than writing API calls directly
69- Ask the user to supply API or library documentation if you are at all unsure about it
70- **Never bake in secrets into the code** - always use environment variables
71- Include comments explaining complex logic (avoid commenting obvious operations)
190- For AI-generated images, use: `https://maxm-imggenurl.web.val.run/the-description-of-your-image`
191- **Storage:** DO NOT use the Deno KV module for storage
192- **Browser APIs:** DO NOT use the `alert()`, `prompt()`, or `confirm()` methods
193- **Weather Data:** Use open-meteo for weather data (doesn't require API keys) unless otherwise specified
194- **View Source:** Add a view source link with `import.meta.url.replace("esm.town", "val.town")` and include `target="_top"` attribute
195- **Error Debugging:** Add `<script src="https://esm.town/v/std/catch"></script>` to HTML to capture client-side errors
196- **Error Handling:** Only use try...catch when there's a clear local resolution; avoid catches that merely log or return 500s - let errors bubble up with full context
197- **Environment Variables:** Use `Deno.env.get('keyname')` and minimize their use - prefer APIs without keys
198- **Imports:** Use `https://esm.sh` for npm and Deno dependencies to ensure compatibility on server and browser
199- **Storage Strategy:** Only use backend storage if explicitly required; prefer simple static client-side sites
230231### Backend (Hono) Best Practices
232- Hono is the recommended API framework (similar to Express, Flask, or Sinatra)
233- Main entry point should be `backend/index.ts`
234- **Static asset serving:** Use the utility functions to read and serve project files:
251});
252```
253- Create RESTful API routes for CRUD operations
254- Be careful with error handling as Hono tends to swallow errors
255- Always include this snippet at the top-level Hono app to re-throwing errors to see full stack traces:
268- Use React 18.2.0 consistently in all imports and the `@jsxImportSource` pragma
269- Follow the React component pattern from the example project
270- Handle API calls properly with proper error catching
271272### Database Patterns
299- For files in the project, use `readFile` helpers
3003015. **API Design:**
302- `fetch` handler is the entry point for HTTP vals
303- Run the Hono app with `export default app.fetch // This is the entry point for HTTP vals`
untitled-73index.ts5 matches
13app.get("/shared/*", c => serveFile(c.req.path, import.meta.url));
1415// Weather API endpoint
16app.get("/api/weather", async (c) => {
17const lat = c.req.query("lat");
18const lon = c.req.query("lon");
24try {
25const response = await fetch(
26`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,relative_humidity_2m,wind_speed_10m,weather_code&timezone=auto`
27);
28
29if (!response.ok) {
30throw new Error(`Weather API error: ${response.status}`);
31}
32
34return c.json(data);
35} catch (error) {
36console.error("Weather API error:", error);
37return c.json({ error: "Failed to fetch weather data" }, 500);
38}
untitled-73WeatherCard.tsx2 matches
52{Math.round(weather.current.temperature_2m)}°{weather.current_units.temperature_2m}
53</div>
54<div className="text-gray-600 capitalize">
55{weatherInfo?.description || "Unknown conditions"}
56</div>
9192<div className="text-xs text-gray-500 text-center mt-4">
93Data from Open-Meteo API
94</div>
95</div>