diff --git a/README.md b/README.md
index 226d2ed..2c00a23 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,10 @@ You'll find this `dashboard` token already created for you on the Tinybird UI, u
## Advanced
+### Local development and mock data
+
+See the [tinybird](./tinybird/README.md) and [dashboard](./dashboard/README.md) READMEs.
+
### CLI installation of the Tinybird project
1. Create a [Tinybird account](https://ui.tinybird.co/signup).
diff --git a/TEMPLATE.md b/TEMPLATE.md
index 5253d41..38d71f9 100644
--- a/TEMPLATE.md
+++ b/TEMPLATE.md
@@ -21,3 +21,7 @@ Copy the snippet and paste it within your site `
` section:
```
Use the `data-host` attribute to set your Tinybird host URL. Defaults to `https://api.tinybird.co/`.
+
+## Local development and mock data
+
+See the [Tinybird](https://github.com/tinybirdco/web-analytics-starter-kit/blob/main/tinybird/README.md) and [dashboard](https://github.com/tinybirdco/web-analytics-starter-kit/blob/main/dashboard/README.md) READMEs.
diff --git a/dashboard/README.md b/dashboard/README.md
index db8ffad..e4be8f3 100644
--- a/dashboard/README.md
+++ b/dashboard/README.md
@@ -41,6 +41,17 @@ npm run dev
You will find the app running at http://localhost:3000
+Copy the .env.example file and rename it to .env.
+
+```
+NEXT_PUBLIC_TINYBIRD_DASHBOARD_URL=http://localhost:3000
+NEXT_PUBLIC_TINYBIRD_TRACKER_TOKEN=
+NEXT_PUBLIC_TINYBIRD_AUTH_TOKEN=
+NEXT_PUBLIC_TINYBIRD_HOST=
+```
+
+To develop locally, start [Tinybird Local](https://www.tinybird.co/docs/cli/local-container) and use `http://localhost` as NEXT_PUBLIC_TINYBIRD_HOST.
+
### Build for Production
```bash
diff --git a/dashboard/lib/api.ts b/dashboard/lib/api.ts
index 00dc7e3..10ede53 100644
--- a/dashboard/lib/api.ts
+++ b/dashboard/lib/api.ts
@@ -9,9 +9,15 @@ import {
import config from './config'
export function getConfig(search?: string) {
- const params = new URLSearchParams(search || window.location.search)
- const token = config.authToken ?? params.get('token')
- const host = config.host ?? params.get('host')
+ // Check if we're in the browser
+ const isBrowser = typeof window !== 'undefined'
+
+ // Use provided search param, or window.location.search if in browser, or empty string if on server
+ const searchParams = new URLSearchParams(search || (isBrowser ? window.location.search : ''))
+
+ const token = config.authToken ?? searchParams.get('token')
+ const host = config.host ?? searchParams.get('host')
+
return {
token,
host,
diff --git a/tinybird/README.md b/tinybird/README.md
index 8b87234..7a3a203 100644
--- a/tinybird/README.md
+++ b/tinybird/README.md
@@ -40,3 +40,29 @@ Note:
Typically, in big projects, we split the .pipe files across two folders: /pipes and /endpoints
- `/pipes` where we store the pipes ending in a datasource, that is, [materialized views](https://guides.tinybird.co/guide/materialized-views)
- `/endpoints` for the pipes that end in API endpoints.
+
+## Local development
+
+Start [Tinybird Local](https://www.tinybird.co/docs/cli/local-container), push the project with `tb push -f` and use `http://localhost` as NEXT_PUBLIC_TINYBIRD_HOST and the admin token in the [dashboard](../dashboard/README.md).
+
+## Mock data
+
+Install [mockingbird](https://github.com/tinybirdco/mockingbird):
+
+```
+npm install @tinybirdco/mockingbird-cli
+```
+
+Run:
+
+```
+TB_ENDPOINT=http://localhost mockingbird-cli tinybird \
+--schema "schema.json" \
+--datasource "analytics_events" \
+--token $TB_LOCAL_TOKEN \
+--endpoint "custom" \
+--eps 1000 \
+--limit 200000000
+```
+
+Where TB_LOCAL_TOKEN is the admin token in the [dashboard](../dashboard/README.md).
diff --git a/tinybird/mock/schema.json b/tinybird/mock/schema.json
new file mode 100644
index 0000000..5499951
--- /dev/null
+++ b/tinybird/mock/schema.json
@@ -0,0 +1,49 @@
+{
+ "timestamp": {
+ "type": "mockingbird.timestampNow"
+ },
+ "session_id": {
+ "type": "string.uuid"
+ },
+ "action": {
+ "type": "mockingbird.pick",
+ "params": [
+ {
+ "values": [
+ "page_hit"
+ ]
+ }
+ ]
+ },
+ "version": {
+ "type": "mockingbird.pick",
+ "params": [
+ {
+ "values": [
+ "1"
+ ]
+ }
+ ]
+ },
+ "payload": {
+ "type": "mockingbird.pick",
+ "params": [
+ {
+ "values": [
+ "{ \"user-agent\":\"Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.79 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\", \"locale\":\"en-US\", \"referrer\":\"https://www.kike.io\", \"pathname\":\"/blog-posts/data-market-whitebox-replaces-4-data-stack-tools-with-tinybird\", \"href\":\"https://www.tinybird.co/blog-posts/data-market-whitebox-replaces-4-data-stack-tools-with-tinybird\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +http://www.google.com/bot.html) Chrome/104.0.5112.79 Safari/537.36\", \"locale\":\"en-US\", \"location\":\"IT\", \"referrer\":\"https://www.hn.com\", \"pathname\":\"/guide/fine-tuning-csvs-for-fast-ingestion\", \"href\":\"https://www.tinybird.co/guide/fine-tuning-csvs-for-fast-ingestion\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0\", \"locale\":\"en-GB\", \"location\":\"ES\", \"referrer\":\"\", \"pathname\":\"/\", \"href\":\"https://www.tinybird.co\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0\", \"locale\":\"en-US\", \"location\":\"US\", \"referrer\":\"https://www.google.com\", \"pathname\":\"/\", \"href\":\"https://www.tinybird.co\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36\", \"locale\":\"en-US\", \"location\":\"US\", \"referrer\":\"https://www.tinybird.co/why-tinybird\", \"pathname\":\"/pricing\", \"href\":\"https://www.tinybird.co/pricing\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36\", \"locale\":\"en-US\", \"location\":\"US\", \"referrer\":\"https://www.google.com\", \"pathname\":\"/product\", \"href\":\"https://www.tinybird.co/product\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36\", \"locale\":\"en-US\", \"location\":\"IL\", \"referrer\":\"https://www.google.com\", \"pathname\":\"/blog-posts/tips-5-adding-and-subtracting-intervals\", \"href\":\"https://www.tinybird.co/blog-posts/tips-5-adding-and-subtracting-intervals\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1\", \"locale\":\"es-ES\", \"location\":\"ES\", \"referrer\":\"https://www.twitter.com\", \"pathname\":\"/\", \"href\":\"https://www.tinybird.co\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36\", \"locale\":\"en-US\", \"location\":\"GB\", \"referrer\":\"https://www.facebook.com\", \"pathname\":\"/\", \"href\":\"https://www.tinybird.co\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36\", \"locale\":\"en-US\", \"location\":\"CH\", \"referrer\":\"https://www.qq.ch\", \"pathname\":\"guides\", \"href\":\"https://www.tinybird.co/guides\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.118 Mobile Safari/537.36\", \"locale\":\"en-US\", \"location\":\"US\", \"referrer\":\"https://www.yandex.com\", \"pathname\":\"/product\", \"href\":\"https://www.tinybird.co/product\"}",
+ "{ \"user-agent\":\"Mozilla/5.0 (Linux; Android 13; SM-A102U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.118 Mobile Safari/537.36\", \"locale\":\"en-US\", \"location\":\"FR\", \"referrer\":\"https://www.github.com\", \"pathname\":\"/pricing\", \"href\":\"https://www.tinybird.co/pricing\"}"
+ ]
+ }
+ ]
+ }
+}