Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The Parallel Cookbook is a curated set of recipes that show how to build with Pa
- [Recipes by Category](#recipes-by-category)
- [Templates & Starters](#templates--starters)
- [Agents & Search](#agents--search)
- [Discovery & Recommendations](#discovery--recommendations)
- [Data Enrichment](#data-enrichment)
- [Realtime Streaming (SSE)](#realtime-streaming-sse)
- [Scheduled Research & Webhooks](#scheduled-research--webhooks)
Expand Down Expand Up @@ -91,6 +92,14 @@ LLM agents that use Parallel's Search API as a tool with the Vercel AI SDK.
| [**Search Agent (Cerebras)**](typescript-recipes/parallel-search-agent-cerebras) | Multi-turn web research agent backed by Cerebras (GPT-OSS / Qwen). Iterative multi-angle searches, full-stack with vanilla JS frontend. | `Search` | Cloudflare Workers · Cerebras · AI SDK | [Live](https://oss.parallel.ai/agent/) |
| [**Search Agent (Groq)**](typescript-recipes/parallel-search-agent-groq) | Same agent shape, Llama 4 Maverick on Groq with 128k context for long sessions. | `Search` | Cloudflare Workers · Groq · AI SDK | [Live](https://oss.parallel.ai/agent/) |

### Discovery & Recommendations

Find and rank real-world entities from natural-language criteria.

| Recipe | Description | APIs | Stack | Demo |
| --- | --- | --- | --- | --- |
| [**Apartment Finder**](typescript-recipes/parallel-apartment-finder) | Discovers real Bay Area apartment listings with FindAll, enriches each match, and uses Task to verify scam signals. | `FindAll` `Task` | Next.js · Vercel | [Live](https://apartment-finder-web.vercel.app) |

### Data Enrichment

Take a thin input (a name, a domain) and return structured, cited fields.
Expand Down
16 changes: 16 additions & 0 deletions typescript-recipes/parallel-apartment-finder/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Required: your Parallel API key (https://platform.parallel.ai).
# Copy this file to .env.local and fill it in. .env.local is gitignored —
# never commit a real key. The key is used server-side only and is never
# exposed to the browser.
PARALLEL_API_KEY=your-parallel-api-key-here

# Optional. Absolute base URL for the app's own /api calls. Leave empty for
# local dev and normal single-origin deployments (the app calls its own
# same-origin API routes).
NEXT_PUBLIC_API_BASE=

# Optional overrides (see src/lib/server/config.ts for the full set):
# CITY=San Francisco, CA
# SEARCH_BUDGET=6000
# FINDALL_GENERATOR=base
# FINDALL_ENRICH_PROCESSOR=base
5 changes: 5 additions & 0 deletions typescript-recipes/parallel-apartment-finder/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.vercel
.env
.env.local
.env*.local
!.env.example
6 changes: 6 additions & 0 deletions typescript-recipes/parallel-apartment-finder/.vercelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
.next
.env
.env.*
Dockerfile.dev
package-lock.json
7 changes: 7 additions & 0 deletions typescript-recipes/parallel-apartment-finder/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM node:20-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
12 changes: 12 additions & 0 deletions typescript-recipes/parallel-apartment-finder/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
MIT License

Copyright (c) 2026 Parallel Web Systems

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
19 changes: 19 additions & 0 deletions typescript-recipes/parallel-apartment-finder/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Apartment Finder Web
Copyright 2026 Parallel Web Systems, Inc.

This project is licensed under the MIT License (see LICENSE).

Trademarks
----------
"Parallel" and the Parallel logo, wordmark, and symbol (the SVG brand marks in
frontend/public/) are trademarks of Parallel Web Systems, Inc. The MIT license
covers the source code only. It does not grant any right to use the Parallel
name or marks, whether to imply endorsement, in a derivative product's branding,
or otherwise. If you fork or redeploy this project, replace the Parallel brand
marks with your own.

Third-Party Notices
-------------------
This project depends on open-source software distributed under its own license,
including Next.js, React, Tailwind CSS, shadcn/ui, and Leaflet. Their licenses
apply to those components.
84 changes: 84 additions & 0 deletions typescript-recipes/parallel-apartment-finder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Apartment Finder

Discover and verify real Bay Area apartment listings from a natural-language request with Parallel FindAll and Task. Live demo: [apartment-finder-web.vercel.app](https://apartment-finder-web.vercel.app)

## What it shows

- Discover individual listing pages with FindAll, then enrich each match into a structured 18-field record.
- Verify listings from untrusted sources with a separate Task run that checks fact-based scam signals.
- Drive a multi-step search from a Next.js client while keeping every serverless API request short and stateless.
- Geocode results, score them for price and location fit, and save a shortlist in browser storage.

## Architecture

```mermaid
graph LR
A[Browser] <-->|create · poll · enrich · finalize| B[Next.js API routes]
B <-->|FindAll + Task APIs| C[Parallel API]
B <-->|geocoding| D[OSM Nominatim]
A -.->|saved shortlist| E[(Browser localStorage)]
```

The browser advances each search through short serverless calls. The application has no database or long-running server process; only the user's saved shortlist persists, in `localStorage`.

## Quick Start

### Prerequisites

- Node.js 20 or newer
- A [Parallel API key](https://platform.parallel.ai)

```bash
git clone https://github.com/parallel-web/parallel-cookbook.git
cd parallel-cookbook/typescript-recipes/parallel-apartment-finder
npm install
cp .env.example .env.local
```

Set `PARALLEL_API_KEY` in `.env.local`, then start the app:

```bash
npm run dev
```

Open [http://localhost:3000](http://localhost:3000).

## Deploy

Deploy this directory as a Vercel project and add `PARALLEL_API_KEY` to the project's environment variables.

```bash
npx vercel deploy --prod
```

> [!IMPORTANT]
> The `/api/search` and `/api/verify` routes do not authenticate callers. Every request uses your Parallel quota. Before a public deployment, add authentication and rate limiting, and keep `PARALLEL_API_KEY` in a server-side environment variable—never a `NEXT_PUBLIC_` variable.

## How it works

1. `POST /api/search` turns the user's request into explicit FindAll match conditions.
2. The client polls the FindAll run and renders confirmed listings as they arrive.
3. When discovery finishes, the client starts structured enrichment and polls again for price, beds, address, and other listing fields.
4. The finalize route geocodes and scores matches. Listings from untrusted sources can then be checked by the Task-based fraud verifier.

Configuration is environment-driven. See [`src/lib/server/config.ts`](src/lib/server/config.ts) for supported city, budget, generator, processor, and result-limit overrides.

## Project Structure

```text
src/
├── app/ # Pages, layouts, and serverless API routes
├── components/ # Search, listings, map, and reasoning UI
├── hooks/ # Search state machine and saved targets
├── lib/server/ # Parallel client, parsing, scoring, and geocoding
├── providers/ # React context providers
└── types/ # TypeScript types
```

## Credits

Created by [Elijah Jacob](https://github.com/elijahgjacob) and contributed from [apartment-finder-web](https://github.com/elijahgjacob/apartment-finder-web).

## License

MIT. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
25 changes: 25 additions & 0 deletions typescript-recipes/parallel-apartment-finder/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "radix-nova",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": false,
"aliases": {
"components": "src/components",
"utils": "src/lib/utils",
"ui": "src/components/ui",
"lib": "src/lib",
"hooks": "src/hooks"
},
"menuColor": "default",
"menuAccent": "subtle",
"registries": {}
}
20 changes: 20 additions & 0 deletions typescript-recipes/parallel-apartment-finder/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import js from "@eslint/js"
import globals from "globals"
import reactHooks from "eslint-plugin-react-hooks"
import tseslint from "typescript-eslint"
import { defineConfig, globalIgnores } from "eslint/config"

export default defineConfig([
globalIgnores([".next"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
],
languageOptions: {
globals: globals.browser,
},
},
])
6 changes: 6 additions & 0 deletions typescript-recipes/parallel-apartment-finder/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference path="./.next/types/routes.d.ts" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
11 changes: 11 additions & 0 deletions typescript-recipes/parallel-apartment-finder/next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { NextConfig } from "next"

// All /api/* endpoints are native Next.js route handlers (src/app/api) that
// call the Parallel API directly — no separate backend, no proxy.
const nextConfig: NextConfig = {
// Keep build traces scoped to this recipe when it lives inside the cookbook
// monorepo (which contains several independent lockfiles).
outputFileTracingRoot: process.cwd(),
}

export default nextConfig
Loading