Typestate
Sign in

Page and price watch

You name the pages to watch. Each morning they are read, and you get an email when one moves.

For a shop owner or marketer who watches rival prices or pages.

Firecrawl logo FirecrawlResend logo Resend
Start it with your agentStarting from a blueprint does not count against the action changes of your plan.

Start the page and price watch blueprint on Typestate

Asked you for the address your emails come from.

Started Page and price watch: 2 record types, 4 web endpoints.

5 actions are compiling.

Deployed to Sandbox. Try it at your Sandbox address.

What your agent does when you start this blueprint

What runs

Each step has 3 parts: who starts it, how it reaches your backend, and the action that answers.

  1. Youname a page to watch, and the part that holds the price
    Web endpointPOST /pages
    Watch a PageSaves the page.saves a Page
  2. Your backendreads each page every morning
    TimerEvery day at 07:00, Berlin time
    Read Every PageRuns Check a Page for each page you watch.runs an action for each page
  3. Your backendkeeps what moved and emails you
    Web endpointPOST /pages/check
    Check a PageReads the page and compares it with the last reading.changes a Pagesaves a Changesends 1 email
  4. Youread what moved, newest first
    Web endpointGET /changes
    List ChangesAnswers each change with the text before and after.reads only
  5. Youstop watching a page
    Web endpointPOST /pages/stop
    Stop WatchingStops the daily reading of the page.changes a Page
  • Web endpoint: your website or app calls it
  • Timer: it runs at a set time

The rule you will want to change first

A page counts as changed when its text differs from the last reading. Name a part, such as .price, to watch only the price.

It lives in the action Check a Page. Tell your agent how you want it instead: one sentence changes, and you read the change before it goes Live.

What it is made of

The map shows the records it keeps, the actions it runs and the services it calls.

What it keeps

Pageperson, email, name, url, part, last text, last read at, active
Changeperson, page, page name, before, after

What it does

Watch a Pageweb endpoint
Check a Pageweb endpointThe rule to change first
Read Every PageEvery day at 07:00, Berlin time
List Changesweb endpoint
Stop Watchingweb endpoint

What it reaches

FirecrawlLet an action read any web page as clean text.
ResendSend email from your own address: sign-in links, receipts, reminders.
Your website4 web endpoints

What it keeps

Page

8 fields

One page you watch, with its last reading.

person
required
email
required, an email address
name
required, at most 120 characters
url
required, at most 2000 characters
part
optional, at most 200 characters
last text
optional, at most 200000 characters
last read at
optional, a date and time
active
required, yes or no

Each person sees and changes only the pages they watch.

Change

5 fields

Each time a page moved, with the text before and after.

person
required
page
required
page name
required, at most 120 characters
before
optional, at most 200000 characters
after
required, at most 200000 characters

Each person sees only the changes of their own pages.

What it does

Open an action to read its steps: each sentence, with the calls that do it under it.

Watch a PageYou name a page to watch, and the part of it that holds the price.

Who starts it

From the webPOST /pages

What it is given

Nametext, needed

URLtext, needed

Parttext, optional

What it does

  • input.urlwhat the caller gives
  • pagesa value it works out
  • Pagea record type
  • Pagean attribute of a record or an answer
  • "https://"a fixed text or number
  • caller.idwhat it knows without being told
  • Refusewhere it says no

When the given address does not start with https://, refuse with "The address must start with https://".

When not (input.url starts with "https://")

Refuse "The address must start with https://"

Count the Pages of the signed-in person.When there are 50 or more, refuse with "You watch 50 pages already".

Each page is one Firecrawl call a day, so the count keeps the bill small.

pages is

Count Pages where

person_id is caller.id

When pages is at least 50

Refuse "You watch 50 pages already"

Create a Page with person_id set to the signed-in person, email set to the address they signed in with, the given name, address and part, and active set to yes.

Add a Page

set active to true

set email to caller.email

set name to input.name

set part to input.part

set person_id to caller.id

set url to input.url

Answer with that Page's id.

Answer

id is page.id

Check a PageThe page is read now. When its text moved since the last reading, a Change is kept and you get an email.

Who starts it

From the webPOST /pages/check

What it is given

Page IDtext, needed

What it does

  • input.page_idwhat the caller gives
  • pagea value it works out
  • Pagea record type
  • Pagean attribute of a record or an answer
  • "markdown"a fixed text or number
  • nowwhat it knows without being told
  • formatsa part of an email or a payment
  • refusewhere it says no

Find the Page whose id is the given page id.When none matches, refuse with "No such page".

page is

Find the first Page where

id is input.page_id

when none refuse "No such page"

Ask Firecrawl to read that Page's address now as Markdown, never from a saved copy, only its main content, and only the part the Page names when it names one.If that fails, refuse with "The page could not be read".

read is

Ask Firecrawl to Scrape Page

formats is a list of 1:

"markdown"

includeTags is

when

page.part holds a value

then the list of the page's part

otherwise an empty list

maxAge is 0

onlyMainContent is true

url is page.url

when it fails

Refuse "The page could not be read"

new_text is

take read.data.markdown

or, when that gives nothing, take ""

then cut the spaces at its ends

The page changed when that Page has a last text and the new text is not the same.

changed is

page.last_text holds a value

and page.last_text is not new_text

When the page changed, create a Change with person_id set to that Page's person, page_id and page_name set to that Page's id and name, before set to its last text, and after set to the new text.

When changed

Add a Change

set after to new_text

set before to page.last_text

set page_id to page.id

set page_name to page.name

set person_id to page.person_id

When the page changed, email that Page's address with the subject "A page you watch changed", naming the page and its address.

When changed

Send an email

to page.email

template "Check a Page Email"

name page.name

url page.url

Change that Page's last text to the new text and its last reading to now.

Change the Page where

id is page.id

set last_read_at to now

set last_text to new_text

Answer whether the page changed.

Answer

changed is changed

Read Every PageEach morning, each page you watch is read in the background.

Who starts it

A timer, every day at 07:00, Berlin time

What it is given

Nothing. It needs no input.

What it does

  • pagesa value it works out
  • Pagea record type
  • Pagean attribute of a record or an answer
  • truea fixed text or number
  • caller.idwhat it knows without being told
  • page_ida part of an email or a payment

Find up to 50 Pages of the signed-in person whose active is yes.

pages is

Find Pages where

active is true

person_id is caller.id

For each of them, run Check a Page in the background with its id, as the person who made this request.

For each page in pages, at most 50

Run Check a Page in the background

page_id is page.id

as the person who asked

List ChangesYou read what moved on the pages you watch, newest first.

Who starts it

From the webGET /changes

What it is given

Nothing. It needs no input.

What it does

  • founda value it works out
  • Changea record type
  • Changean attribute of a record or an answer
  • caller.idwhat it knows without being told

Find up to 50 Changes of the signed-in person, newest first.

found is

Find Changes where

person_id is caller.id

sorted by created_at, highest first

Answer with each Change's page id, page name, text before, text after and the time it was seen.

Answer

changes is

each change of found as

after is change.after

before is change.before

page_id is change.page_id

page_name is change.page_name

seen_at is change.created_at

Stop WatchingYou stop watching a page. Its changes stay.

Who starts it

From the webPOST /pages/stop

What it is given

Page IDtext, needed

What it does

  • input.page_idwhat the caller gives
  • pagea value it works out
  • Pagea record type
  • Pagean attribute of a record or an answer
  • falsea fixed text or number
  • refusewhere it says no

Find the Page whose id is the given page id.When none matches, refuse with "No such page".

page is

Find the first Page where

id is input.page_id

when none refuse "No such page"

Change that Page's active to no.

Change the Page where

id is page.id

set active to false

Answer with that Page's id.

Answer

id is page.id

What it does by itself

  • Every day at 07:00, Berlin time, each page is read.

Who signs in and what they may read

People sign up and sign in with an email address and a password, or with a provider you add, such as Google.

  • Page: Each person sees and changes only the pages they watch.
  • Change: Each person sees only the changes of their own pages.

Web endpoints

What it doesWho may callAddress
You name a page to watch.a signed-in personPOST /pages
You read a page now, without waiting for the morning.a signed-in personPOST /pages/check
You read what moved.a signed-in personGET /changes
You stop watching a page.a signed-in personPOST /pages/stop

What it cannot do yet

  • It reads each page once a day. A change that comes and goes within the day is not seen.
  • Any change in the text counts, also a date or a counter on the page. Name a part to watch less.
  • Each reading is one Firecrawl call, on your own Firecrawl key.

Build the pages with your tool

Typestate is the backend. Paste this brief into Lovable, v0, Claude Code or the tool that builds your pages.

Show the brief
Build the pages for "Page and price watch". The backend runs on Typestate and answers these web endpoints: POST /pages: You name a page to watch. Who may call: a signed-in person. POST /pages/check: You read a page now, without waiting for the morning. Who may call: a signed-in person. GET /changes: You read what moved. Who may call: a signed-in person. POST /pages/stop: You stop watching a page. Who may call: a signed-in person. People sign up at POST /auth/signup and sign in at POST /auth/login, which answers a token. Send it as Authorization: Bearer <token>. A refused call answers a sentence that can be shown to the person as it is.

Start it

  1. Tell your agent the sentence on the right.
  2. It asks you for the address emails come from, on a domain you verified at Resend, such as "Riverside Physio <hello@riverside.example>".
  3. It tells you what only you can do, such as pasting your Resend key in the cockpit. A key never goes through the agent.
  4. Open your Sandbox address and try it yourself.

Starting from this blueprint does not count against the action changes of your plan. The Free plan runs it on Sandbox. Live needs a paid plan.

Start the page and price watch blueprint on TypestateChoose a plan

Related blueprints