diff --git a/apps/dashboard/.env.example b/apps/dashboard/.env.example
index 3f719125270..c20ff8fe6e4 100644
--- a/apps/dashboard/.env.example
+++ b/apps/dashboard/.env.example
@@ -108,4 +108,10 @@ STRIPE_SECRET_KEY=""
# required for server wallet management
NEXT_PUBLIC_THIRDWEB_VAULT_URL=""
-NEXT_PUBLIC_ENGINE_CLOUD_URL=""
\ No newline at end of file
+NEXT_PUBLIC_ENGINE_CLOUD_URL=""
+
+# farcaster frame env variables
+NEXT_PUBLIC_APP_URL=
+NEXT_PUBLIC_FARCASTER_HEADER=
+NEXT_PUBLIC_FARCASTER_PAYLOAD=
+NEXT_PUBLIC_FARCASTER_SIGNATURE=
\ No newline at end of file
diff --git a/apps/dashboard/next.config.ts b/apps/dashboard/next.config.ts
index ef23f2ed4a7..f5b13c2bcdd 100644
--- a/apps/dashboard/next.config.ts
+++ b/apps/dashboard/next.config.ts
@@ -29,7 +29,8 @@ const securityHeaders = [
},
{
key: "X-Frame-Options",
- value: "SAMEORIGIN",
+ // allow farcaster.xyz as a frame ancestor for the browser mini app
+ value: "frame-ancestors 'self' https://farcaster.xyz; default 'self'",
},
{
key: "Referrer-Policy",
diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json
index 0b194ad1421..75cbe7c5880 100644
--- a/apps/dashboard/package.json
+++ b/apps/dashboard/package.json
@@ -27,6 +27,8 @@
"@chakra-ui/theme-tools": "^2.1.2",
"@emotion/react": "11.14.0",
"@emotion/styled": "11.14.0",
+ "@farcaster/frame-core": "^0.1.8",
+ "@farcaster/frame-sdk": "^0.0.60",
"@hookform/resolvers": "^3.9.1",
"@marsidev/react-turnstile": "^1.1.0",
"@radix-ui/react-accordion": "^1.2.11",
diff --git a/apps/dashboard/public/.well-known/apple-app-site-association b/apps/dashboard/public/.well-known/apple-app-site-association
deleted file mode 100644
index c9cac6e71c3..00000000000
--- a/apps/dashboard/public/.well-known/apple-app-site-association
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "applinks": {
- "apps": ["XYHGSFAMHX.com.thirdweb.demo"],
- "details": [
- {
- "appIDs": ["XYHGSFAMHX.com.thirdweb.demo"],
- "components": [
- {
- "#": "no_universal_links",
- "exclude": true,
- "comment": "Matches any URL with a fragment that equals no_universal_links and instructs the system not to open it as a universal link."
- },
- {
- "/": "/mobile-wallet-protocol",
- "comment": "Matches any URL with a path that starts with /mobile-wallet-protocol for coinbase wallet mobile redirects."
- },
- {
- "/": "/dashboard/*",
- "exclude": true,
- "comment": "no universal link for dashboard"
- }
- ]
- }
- ]
- },
- "webcredentials": {
- "apps": ["XYHGSFAMHX.com.thirdweb.demo"]
- },
- "appclips": {}
-}
diff --git a/apps/dashboard/public/.well-known/apple-developer-merchantid-domain-association b/apps/dashboard/public/.well-known/apple-developer-merchantid-domain-association
deleted file mode 100644
index 2ff95c96281..00000000000
--- a/apps/dashboard/public/.well-known/apple-developer-merchantid-domain-association
+++ /dev/null
@@ -1 +0,0 @@
-7B227073704964223A2239373943394538343346343131343044463144313834343232393232313734313034353044314339464446394437384337313531303944334643463542433731222C2276657273696F6E223A312C22637265617465644F6E223A313536363233343735303036312C227369676E6174757265223A22333038303036303932613836343838366637306430313037303261303830333038303032303130313331306633303064303630393630383634383031363530333034303230313035303033303830303630393261383634383836663730643031303730313030303061303830333038323033653333303832303338386130303330323031303230323038346333303431343935313964353433363330306130363038326138363438636533643034303330323330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333031653137306433313339333033353331333833303331333333323335333735613137306433323334333033353331333633303331333333323335333735613330356633313235333032333036303335353034303330633163363536333633326437333664373032643632373236663662363537323264373336393637366535663535343333343264353035323466343433313134333031323036303335353034306230633062363934663533323035333739373337343635366437333331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333035393330313330363037326138363438636533643032303130363038326138363438636533643033303130373033343230303034633231353737656465626436633762323231386636386464373039306131323138646337623062643666326332383364383436303935643934616634613534313162383334323065643831316633343037653833333331663163353463336637656233323230643662616435643465666634393238393839336537633066313361333832303231313330383230323064333030633036303335353164313330313031666630343032333030303330316630363033353531643233303431383330313638303134323366323439633434663933653465663237653663346636323836633366613262626664326534623330343530363038326230363031303530353037303130313034333933303337333033353036303832623036303130353035303733303031383632393638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635363136393633363133333330333233303832303131643036303335353164323030343832303131343330383230313130333038323031306330363039326138363438383666373633363430353031333038316665333038316333303630383262303630313035303530373032303233303831623630633831623335323635366336393631366536333635323036663665323037343638363937333230363336353732373436393636363936333631373436353230363237393230363136653739323037303631373237343739323036313733373337353664363537333230363136333633363537303734363136653633363532303666363632303734363836353230373436383635366532303631373037303663363936333631363236633635323037333734363136653634363137323634323037343635373236643733323036313665363432303633366636653634363937343639366636653733323036663636323037353733363532633230363336353732373436393636363936333631373436353230373036663663363936333739323036313665363432303633363537323734363936363639363336313734363936663665323037303732363136333734363936333635323037333734363137343635366436353665373437333265333033363036303832623036303130353035303730323031313632613638373437343730336132663266373737373737326536313730373036633635326536333666366432663633363537323734363936363639363336313734363536313735373436383666373236393734373932663330333430363033353531643166303432643330326233303239613032376130323538363233363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353631363936333631333332653633373236633330316430363033353531643065303431363034313439343537646236666435373438313836383938393736326637653537383530376537396235383234333030653036303335353164306630313031666630343034303330323037383033303066303630393261383634383836663736333634303631643034303230353030333030613036303832613836343863653364303430333032303334393030333034363032323130306265303935373166653731653165373335623535653561666163623463373266656234343566333031383532323263373235313030326236316562643666353530323231303064313862333530613564643664643665623137343630333562313165623263653837636661336536616636636264383338303839306463383263646461613633333038323032656533303832303237356130303330323031303230323038343936643266626633613938646139373330306130363038326138363438636533643034303330323330363733313162333031393036303335353034303330633132343137303730366336353230353236663666373432303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330316531373064333133343330333533303336333233333334333633333330356131373064333233393330333533303336333233333334333633333330356133303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330353933303133303630373261383634386365336430323031303630383261383634386365336430333031303730333432303030346630313731313834313964373634383564353161356532353831303737366538383061326566646537626165346465303864666334623933653133333536643536363562333561653232643039373736306432323465376262613038666437363137636538386362373662623636373062656338653832393834666635343435613338316637333038316634333034363036303832623036303130353035303730313031303433613330333833303336303630383262303630313035303530373330303138363261363837343734373033613266326636663633373337303265363137303730366336353265363336663664326636663633373337303330333432643631373037303663363537323666366637343633363136373333333031643036303335353164306530343136303431343233663234396334346639336534656632376536633466363238366333666132626266643265346233303066303630333535316431333031303166663034303533303033303130316666333031663036303335353164323330343138333031363830313462626230646561313538333338383961613438613939646562656264656261666461636232346162333033373036303335353164316630343330333032653330326361303261613032383836323636383734373437303361326632663633373236633265363137303730366336353265363336663664326636313730373036633635373236663666373436333631363733333265363337323663333030653036303335353164306630313031666630343034303330323031303633303130303630613261383634383836663736333634303630323065303430323035303033303061303630383261383634386365336430343033303230333637303033303634303233303361636637323833353131363939623138366662333563333536636136326266663431376564643930663735346461323865626566313963383135653432623738396638393866373962353939663938643534313064386639646539633266653032333033323264643534343231623061333035373736633564663333383362393036376664313737633263323136643936346663363732363938323132366635346638376137643162393963623962303938393231363130363939306630393932316430303030333138323031386233303832303138373032303130313330383138363330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533303230383463333034313439353139643534333633303064303630393630383634383031363530333034303230313035303061303831393533303138303630393261383634383836663730643031303930333331306230363039326138363438383666373064303130373031333031633036303932613836343838366637306430313039303533313066313730643331333933303338333133393331333733313332333333303561333032613036303932613836343838366637306430313039333433313164333031623330306430363039363038363438303136353033303430323031303530306131306130363038326138363438636533643034303330323330326630363039326138363438383666373064303130393034333132323034323062303731303365313430613462386231376262613230316130336163643036396234653431366232613263383066383661383338313435633239373566633131333030613036303832613836343863653364303430333032303434363330343430323230343639306264636637626461663833636466343934396534633035313039656463663334373665303564373261313264376335666538633033303033343464663032323032363764353863393365626233353031333836363062353730373938613064643731313734316262353864626436613138363633353038353431656565393035303030303030303030303030227D
\ No newline at end of file
diff --git a/apps/dashboard/public/.well-known/assetlinks.json b/apps/dashboard/public/.well-known/assetlinks.json
deleted file mode 100644
index 46c70f80a5b..00000000000
--- a/apps/dashboard/public/.well-known/assetlinks.json
+++ /dev/null
@@ -1,15 +0,0 @@
-[
- {
- "relation": [
- "delegate_permission/common.handle_all_urls",
- "delegate_permission/common.get_login_creds"
- ],
- "target": {
- "namespace": "android_app",
- "package_name": "com.thirdweb.demo",
- "sha256_cert_fingerprints": [
- "40:EB:0D:96:57:F3:D8:1F:BA:87:B8:E4:26:E0:3A:DB:C8:35:96:A8:A2:B2:55:F0:B1:64:F1:39:F8:6F:7E:EB"
- ]
- }
- }
-]
diff --git a/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.png b/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.png
new file mode 100644
index 00000000000..f8e5744a0b4
Binary files /dev/null and b/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.png differ
diff --git a/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.svg b/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.svg
new file mode 100644
index 00000000000..8bf89db8383
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/ask-nebula-pfp.svg
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/apps/dashboard/public/assets/nebula/frame/farcaster-logo.svg b/apps/dashboard/public/assets/nebula/frame/farcaster-logo.svg
new file mode 100644
index 00000000000..062943dd91c
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/farcaster-logo.svg
@@ -0,0 +1,7 @@
+
diff --git a/apps/dashboard/public/assets/nebula/frame/frame.png b/apps/dashboard/public/assets/nebula/frame/frame.png
new file mode 100644
index 00000000000..39ef1e6338a
Binary files /dev/null and b/apps/dashboard/public/assets/nebula/frame/frame.png differ
diff --git a/apps/dashboard/public/assets/nebula/frame/hero.svg b/apps/dashboard/public/assets/nebula/frame/hero.svg
new file mode 100644
index 00000000000..8873deaae87
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/hero.svg
@@ -0,0 +1,27 @@
+
\ No newline at end of file
diff --git a/apps/dashboard/public/assets/nebula/frame/icon.png b/apps/dashboard/public/assets/nebula/frame/icon.png
new file mode 100644
index 00000000000..f8e5744a0b4
Binary files /dev/null and b/apps/dashboard/public/assets/nebula/frame/icon.png differ
diff --git a/apps/dashboard/public/assets/nebula/frame/icon.svg b/apps/dashboard/public/assets/nebula/frame/icon.svg
new file mode 100644
index 00000000000..84228c6dd3f
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/icon.svg
@@ -0,0 +1,16 @@
+
\ No newline at end of file
diff --git a/apps/dashboard/public/assets/nebula/frame/og.svg b/apps/dashboard/public/assets/nebula/frame/og.svg
new file mode 100644
index 00000000000..cd00953b3ae
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/og.svg
@@ -0,0 +1,22 @@
+
+
\ No newline at end of file
diff --git a/apps/dashboard/public/assets/nebula/frame/screenshot.svg b/apps/dashboard/public/assets/nebula/frame/screenshot.svg
new file mode 100644
index 00000000000..9e6eb1de640
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/screenshot.svg
@@ -0,0 +1,69 @@
+
+
\ No newline at end of file
diff --git a/apps/dashboard/public/assets/nebula/frame/splash.png b/apps/dashboard/public/assets/nebula/frame/splash.png
new file mode 100644
index 00000000000..a1ea30a62c7
Binary files /dev/null and b/apps/dashboard/public/assets/nebula/frame/splash.png differ
diff --git a/apps/dashboard/public/assets/nebula/frame/splash.svg b/apps/dashboard/public/assets/nebula/frame/splash.svg
new file mode 100644
index 00000000000..8bb9456be77
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/splash.svg
@@ -0,0 +1,24 @@
+
\ No newline at end of file
diff --git a/apps/dashboard/public/assets/nebula/frame/thirdweb-logo.png b/apps/dashboard/public/assets/nebula/frame/thirdweb-logo.png
new file mode 100644
index 00000000000..ec919ab48eb
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/thirdweb-logo.png
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/dashboard/public/assets/nebula/frame/user-logo.svg b/apps/dashboard/public/assets/nebula/frame/user-logo.svg
new file mode 100644
index 00000000000..44dc35cbd08
--- /dev/null
+++ b/apps/dashboard/public/assets/nebula/frame/user-logo.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/apps/dashboard/src/app/.well-known/apple-app-site-association.json/route.ts b/apps/dashboard/src/app/.well-known/apple-app-site-association.json/route.ts
new file mode 100644
index 00000000000..ceefb7da147
--- /dev/null
+++ b/apps/dashboard/src/app/.well-known/apple-app-site-association.json/route.ts
@@ -0,0 +1,36 @@
+import { NextResponse } from "next/server";
+
+export async function GET() {
+ return NextResponse.json({
+ applinks: {
+ apps: ["XYHGSFAMHX.com.thirdweb.demo"],
+ details: [
+ {
+ appIDs: ["XYHGSFAMHX.com.thirdweb.demo"],
+ components: [
+ {
+ "#": "no_universal_links",
+ exclude: true,
+ comment:
+ "Matches any URL with a fragment that equals no_universal_links and instructs the system not to open it as a universal link.",
+ },
+ {
+ "/": "/mobile-wallet-protocol",
+ comment:
+ "Matches any URL with a path that starts with /mobile-wallet-protocol for coinbase wallet mobile redirects.",
+ },
+ {
+ "/": "/dashboard/*",
+ exclude: true,
+ comment: "no universal link for dashboard",
+ },
+ ],
+ },
+ ],
+ },
+ webcredentials: {
+ apps: ["XYHGSFAMHX.com.thirdweb.demo"],
+ },
+ appclips: {},
+ });
+}
diff --git a/apps/dashboard/src/app/.well-known/apple-developer-merchantid-domain-association/route.ts b/apps/dashboard/src/app/.well-known/apple-developer-merchantid-domain-association/route.ts
new file mode 100644
index 00000000000..7d84734a856
--- /dev/null
+++ b/apps/dashboard/src/app/.well-known/apple-developer-merchantid-domain-association/route.ts
@@ -0,0 +1,3 @@
+export async function GET() {
+ return "7B227073704964223A2239373943394538343346343131343044463144313834343232393232313734313034353044314339464446394437384337313531303944334643463542433731222C2276657273696F6E223A312C22637265617465644F6E223A313536363233343735303036312C227369676E6174757265223A22333038303036303932613836343838366637306430313037303261303830333038303032303130313331306633303064303630393630383634383031363530333034303230313035303033303830303630393261383634383836663730643031303730313030303061303830333038323033653333303832303338386130303330323031303230323038346333303431343935313964353433363330306130363038326138363438636533643034303330323330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333031653137306433313339333033353331333833303331333333323335333735613137306433323334333033353331333633303331333333323335333735613330356633313235333032333036303335353034303330633163363536333633326437333664373032643632373236663662363537323264373336393637366535663535343333343264353035323466343433313134333031323036303335353034306230633062363934663533323035333739373337343635366437333331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333035393330313330363037326138363438636533643032303130363038326138363438636533643033303130373033343230303034633231353737656465626436633762323231386636386464373039306131323138646337623062643666326332383364383436303935643934616634613534313162383334323065643831316633343037653833333331663163353463336637656233323230643662616435643465666634393238393839336537633066313361333832303231313330383230323064333030633036303335353164313330313031666630343032333030303330316630363033353531643233303431383330313638303134323366323439633434663933653465663237653663346636323836633366613262626664326534623330343530363038326230363031303530353037303130313034333933303337333033353036303832623036303130353035303733303031383632393638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635363136393633363133333330333233303832303131643036303335353164323030343832303131343330383230313130333038323031306330363039326138363438383666373633363430353031333038316665333038316333303630383262303630313035303530373032303233303831623630633831623335323635366336393631366536333635323036663665323037343638363937333230363336353732373436393636363936333631373436353230363237393230363136653739323037303631373237343739323036313733373337353664363537333230363136333633363537303734363136653633363532303666363632303734363836353230373436383635366532303631373037303663363936333631363236633635323037333734363136653634363137323634323037343635373236643733323036313665363432303633366636653634363937343639366636653733323036663636323037353733363532633230363336353732373436393636363936333631373436353230373036663663363936333739323036313665363432303633363537323734363936363639363336313734363936663665323037303732363136333734363936333635323037333734363137343635366436353665373437333265333033363036303832623036303130353035303730323031313632613638373437343730336132663266373737373737326536313730373036633635326536333666366432663633363537323734363936363639363336313734363536313735373436383666373236393734373932663330333430363033353531643166303432643330326233303239613032376130323538363233363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353631363936333631333332653633373236633330316430363033353531643065303431363034313439343537646236666435373438313836383938393736326637653537383530376537396235383234333030653036303335353164306630313031666630343034303330323037383033303066303630393261383634383836663736333634303631643034303230353030333030613036303832613836343863653364303430333032303334393030333034363032323130306265303935373166653731653165373335623535653561666163623463373266656234343566333031383532323263373235313030326236316562643666353530323231303064313862333530613564643664643665623137343630333562313165623263653837636661336536616636636264383338303839306463383263646461613633333038323032656533303832303237356130303330323031303230323038343936643266626633613938646139373330306130363038326138363438636533643034303330323330363733313162333031393036303335353034303330633132343137303730366336353230353236663666373432303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330316531373064333133343330333533303336333233333334333633333330356131373064333233393330333533303336333233333334333633333330356133303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330353933303133303630373261383634386365336430323031303630383261383634386365336430333031303730333432303030346630313731313834313964373634383564353161356532353831303737366538383061326566646537626165346465303864666334623933653133333536643536363562333561653232643039373736306432323465376262613038666437363137636538386362373662623636373062656338653832393834666635343435613338316637333038316634333034363036303832623036303130353035303730313031303433613330333833303336303630383262303630313035303530373330303138363261363837343734373033613266326636663633373337303265363137303730366336353265363336663664326636663633373337303330333432643631373037303663363537323666366637343633363136373333333031643036303335353164306530343136303431343233663234396334346639336534656632376536633466363238366333666132626266643265346233303066303630333535316431333031303166663034303533303033303130316666333031663036303335353164323330343138333031363830313462626230646561313538333338383961613438613939646562656264656261666461636232346162333033373036303335353164316630343330333032653330326361303261613032383836323636383734373437303361326632663633373236633265363137303730366336353265363336663664326636313730373036633635373236663666373436333631363733333265363337323663333030653036303335353164306630313031666630343034303330323031303633303130303630613261383634383836663736333634303630323065303430323035303033303061303630383261383634386365336430343033303230333637303033303634303233303361636637323833353131363939623138366662333563333536636136326266663431376564643930663735346461323865626566313963383135653432623738396638393866373962353939663938643534313064386639646539633266653032333033323264643534343231623061333035373736633564663333383362393036376664313737633263323136643936346663363732363938323132366635346638376137643162393963623962303938393231363130363939306630393932316430303030333138323031386233303832303138373032303130313330383138363330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533303230383463333034313439353139643534333633303064303630393630383634383031363530333034303230313035303061303831393533303138303630393261383634383836663730643031303930333331306230363039326138363438383666373064303130373031333031633036303932613836343838366637306430313039303533313066313730643331333933303338333133393331333733313332333333303561333032613036303932613836343838366637306430313039333433313164333031623330306430363039363038363438303136353033303430323031303530306131306130363038326138363438636533643034303330323330326630363039326138363438383666373064303130393034333132323034323062303731303365313430613462386231376262613230316130336163643036396234653431366232613263383066383661383338313435633239373566633131333030613036303832613836343863653364303430333032303434363330343430323230343639306264636637626461663833636466343934396534633035313039656463663334373665303564373261313264376335666538633033303033343464663032323032363764353863393365626233353031333836363062353730373938613064643731313734316262353864626436613138363633353038353431656565393035303030303030303030303030227D";
+}
diff --git a/apps/dashboard/src/app/.well-known/assetlinks.json/route.ts b/apps/dashboard/src/app/.well-known/assetlinks.json/route.ts
new file mode 100644
index 00000000000..47374d23c2a
--- /dev/null
+++ b/apps/dashboard/src/app/.well-known/assetlinks.json/route.ts
@@ -0,0 +1,19 @@
+import { NextResponse } from "next/server";
+
+export async function GET() {
+ return NextResponse.json([
+ {
+ relation: [
+ "delegate_permission/common.handle_all_urls",
+ "delegate_permission/common.get_login_creds",
+ ],
+ target: {
+ namespace: "android_app",
+ package_name: "com.thirdweb.demo",
+ sha256_cert_fingerprints: [
+ "40:EB:0D:96:57:F3:D8:1F:BA:87:B8:E4:26:E0:3A:DB:C8:35:96:A8:A2:B2:55:F0:B1:64:F1:39:F8:6F:7E:EB",
+ ],
+ },
+ },
+ ]);
+}
diff --git a/apps/dashboard/src/app/.well-known/farcaster.json/route.ts b/apps/dashboard/src/app/.well-known/farcaster.json/route.ts
new file mode 100644
index 00000000000..92a218023b4
--- /dev/null
+++ b/apps/dashboard/src/app/.well-known/farcaster.json/route.ts
@@ -0,0 +1,47 @@
+import { NextResponse } from "next/server";
+
+export async function GET() {
+ try {
+ const appUrl =
+ process.env.NEXT_PUBLIC_APP_URL || "http://nebula---localhost:3000";
+ const manifest = {
+ accountAssociation: {
+ header: process.env.NEXT_PUBLIC_FARCASTER_HEADER,
+ payload: process.env.NEXT_PUBLIC_FARCASTER_PAYLOAD,
+ signature: process.env.NEXT_PUBLIC_FARCASTER_SIGNATURE,
+ },
+ frame: {
+ version: "1",
+ name: "Nebula",
+ iconUrl: `${appUrl}/assets/nebula/frame/ask-nebula-pfp.png`,
+ imageUrl: `${appUrl}/assets/nebula/frame/frame.png`,
+ homeUrl: appUrl,
+ splashImageUrl: `${appUrl}/assets/nebula/frame/ask-nebula-pfp.png`,
+ splashBackgroundColor: "#171B20",
+ subtitle: "Web3 AI Assistant",
+ description:
+ "Ask questions about your web3 activity, get AI-powered insights about your wallet, and explore blockchain data through natural language",
+ primaryCategory: "utility",
+ tags: ["ai", "web3", "blockchain", "insights", "wallet"],
+ tagline: "Your AI guide to web3",
+ ogTitle: "Nebula - Web3 AI Assistant",
+ ogDescription:
+ "Interact with your wallet data through natural language queries powered by Thirdweb Nebula AI",
+ heroImageUrl: `${appUrl}/assets/nebula/frame/screenshot.svg`,
+ ogImageUrl: `${appUrl}/assets/nebula/frame/og.svg`,
+ screenshotUrls: [
+ `${appUrl}/assets/nebula/frame/screenshot.svg`,
+ `${appUrl}/assets/nebula/frame/frame.png`,
+ `${appUrl}/assets/nebula/frame/og.svg`,
+ ],
+ },
+ };
+ return NextResponse.json(manifest);
+ } catch (error) {
+ console.error("Error generating manifest:", error);
+ return NextResponse.json(
+ { error: (error as Error).message },
+ { status: 500 },
+ );
+ }
+}
diff --git a/apps/dashboard/src/app/nebula-app/(app)/_farcaster/miniapp-provider.tsx b/apps/dashboard/src/app/nebula-app/(app)/_farcaster/miniapp-provider.tsx
new file mode 100644
index 00000000000..00424ee3ba2
--- /dev/null
+++ b/apps/dashboard/src/app/nebula-app/(app)/_farcaster/miniapp-provider.tsx
@@ -0,0 +1,125 @@
+"use client";
+
+import type { AddMiniAppResult } from "@farcaster/frame-core/dist/actions/AddMiniApp";
+import type { FrameContext } from "@farcaster/frame-core/dist/context";
+import { sdk } from "@farcaster/frame-sdk";
+import { useQuery } from "@tanstack/react-query";
+import { type ReactNode, createContext, useCallback, useState } from "react";
+import { base } from "thirdweb/chains";
+import { useConnect } from "thirdweb/react";
+import { EIP1193 } from "thirdweb/wallets";
+import { nebulaAppThirdwebClient } from "../utils/nebulaThirdwebClient";
+
+interface MiniAppContextType {
+ isMiniAppReady: boolean;
+ isInMiniApp: boolean;
+ context: FrameContext | null;
+ setMiniAppReady: () => void;
+ addMiniApp: () => Promise;
+}
+
+// eslint-disable-next-line no-restricted-syntax
+const MiniAppContext = createContext(undefined);
+
+export function MiniAppProvider({
+ addMiniAppOnLoad,
+ children,
+}: {
+ addMiniAppOnLoad?: boolean;
+ children: ReactNode;
+}) {
+ const [context, setContext] = useState(null);
+ const [isMiniAppReady, setIsMiniAppReady] = useState(false);
+ const [isInMiniApp, setisInMiniApp] = useState(false);
+ const [, setError] = useState(null);
+ const { connect } = useConnect();
+
+ const connectWallet = useCallback(async () => {
+ connect(async () => {
+ const wallet = EIP1193.fromProvider({ provider: sdk.wallet.ethProvider });
+ await wallet.connect({ client: nebulaAppThirdwebClient, chain: base });
+ return wallet;
+ });
+ }, [connect]);
+
+ const setMiniAppReady = useCallback(async () => {
+ try {
+ const isInMiniApp = await sdk.isInMiniApp();
+ setisInMiniApp(isInMiniApp);
+ if (!isInMiniApp) return;
+ const context = await sdk.context;
+ if (context) {
+ setContext(context as FrameContext);
+ } else {
+ setError("Failed to load Farcaster context");
+ }
+ await sdk.actions.ready();
+ if (sdk.wallet) {
+ await connectWallet();
+ }
+ } catch (err) {
+ setError(err instanceof Error ? err.message : "Failed to initialize SDK");
+ console.error("SDK initialization error:", err);
+ } finally {
+ setIsMiniAppReady(true);
+ }
+ }, [connectWallet]);
+
+ useQuery({
+ queryKey: ["miniapp-ready"],
+ queryFn: async () => {
+ try {
+ await setMiniAppReady();
+ return true;
+ } catch (err) {
+ setError(
+ err instanceof Error ? err.message : "Failed to initialize SDK",
+ );
+ console.error("SDK initialization error:", err);
+ return false;
+ }
+ },
+ });
+
+ const handleAddMiniApp = useCallback(async () => {
+ try {
+ if (!isInMiniApp) return null;
+ const result = await sdk.actions.addFrame();
+ if (result) {
+ return result;
+ }
+ return null;
+ } catch (error) {
+ console.error("[error] adding frame", error);
+ return null;
+ }
+ }, [isInMiniApp]);
+
+ useQuery({
+ queryKey: ["miniapp-add"],
+ queryFn: async () => {
+ try {
+ await handleAddMiniApp();
+ return true;
+ } catch (error) {
+ console.error("[error] adding frame", error);
+ return false;
+ }
+ },
+ enabled: isMiniAppReady && !context?.client?.added && addMiniAppOnLoad,
+ });
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/apps/dashboard/src/app/nebula-app/layout.tsx b/apps/dashboard/src/app/nebula-app/layout.tsx
index 927bbc8a5eb..437ae41950a 100644
--- a/apps/dashboard/src/app/nebula-app/layout.tsx
+++ b/apps/dashboard/src/app/nebula-app/layout.tsx
@@ -1,4 +1,4 @@
-import type { Metadata } from "next";
+// import type { Metadata } from "next";
import "../../global.css";
import "./nebula-global.css";
import { DashboardRouterTopProgressBar } from "@/lib/DashboardRouter";
@@ -15,14 +15,34 @@ const title =
const description =
"The most powerful AI for interacting with the blockchain, with real-time access to EVM chains and their data";
-export const metadata: Metadata = {
- title,
- description,
- openGraph: {
+export async function generateMetadata() {
+ const appUrl =
+ process.env.NEXT_PUBLIC_APP_URL || "http://nebula---localhost:3000";
+ return {
title,
description,
- },
-};
+ openGraph: {
+ title,
+ description,
+ },
+ other: {
+ "fc:frame": JSON.stringify({
+ version: "next",
+ imageUrl: `${appUrl}/assets/nebula/frame/frame.png`,
+ button: {
+ title: "Start Chatting",
+ action: {
+ type: "launch_frame",
+ name: "Nebula",
+ url: appUrl,
+ splashImageUrl: `${appUrl}/assets/nebula/frame/ask-nebula-pfp.png`,
+ splashBackgroundColor: "#0f172a",
+ },
+ },
+ }),
+ },
+ };
+}
const fontSans = Inter({
subsets: ["latin"],
diff --git a/apps/dashboard/src/app/nebula-app/providers.tsx b/apps/dashboard/src/app/nebula-app/providers.tsx
index 532bb20ab06..9577c5912ab 100644
--- a/apps/dashboard/src/app/nebula-app/providers.tsx
+++ b/apps/dashboard/src/app/nebula-app/providers.tsx
@@ -6,6 +6,7 @@ import { ThemeProvider, useTheme } from "next-themes";
import { useMemo } from "react";
import { Toaster } from "sonner";
import { ThirdwebProvider, useActiveAccount } from "thirdweb/react";
+import { MiniAppProvider } from "./(app)/_farcaster/miniapp-provider";
import { NebulaConnectWallet } from "./(app)/components/NebulaConnectButton";
const queryClient = new QueryClient();
@@ -14,17 +15,19 @@ export function NebulaProviders(props: { children: React.ReactNode }) {
return (
-
-
-
- {props.children}
-
-
+
+
+
+
+ {props.children}
+
+
+
);
diff --git a/apps/dashboard/src/middleware.ts b/apps/dashboard/src/middleware.ts
index c512b0f10ec..0a134e4a7d5 100644
--- a/apps/dashboard/src/middleware.ts
+++ b/apps/dashboard/src/middleware.ts
@@ -48,9 +48,14 @@ export async function middleware(request: NextRequest) {
// nebula.thirdweb.com -> render page at app/nebula-app
// on vercel preview, the format is nebula---thirdweb-www-git-.thirdweb-preview.com
if (
- subdomain &&
- (subdomain === "nebula" || subdomain.startsWith("nebula---"))
+ (subdomain &&
+ (subdomain === "nebula" || subdomain.startsWith("nebula---"))) ||
+ host?.includes("ngrok")
) {
+ // ignore well-known paths when served under nebula
+ if (paths[0] === ".well-known") {
+ return NextResponse.next();
+ }
// preserve search params when redirecting to /login page
if (
!nebulaAuthCookie &&
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9aaff733e53..ad8827faa6c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -76,6 +76,12 @@ importers:
'@emotion/styled':
specifier: 11.14.0
version: 11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
+ '@farcaster/frame-core':
+ specifier: ^0.1.8
+ version: 0.1.10(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)
+ '@farcaster/frame-sdk':
+ specifier: ^0.0.60
+ version: 0.0.60(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.62)
'@hookform/resolvers':
specifier: ^3.9.1
version: 3.10.0(react-hook-form@7.55.0(react@19.1.0))
@@ -3256,6 +3262,20 @@ packages:
resolution: {integrity: sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw==}
hasBin: true
+ '@farcaster/frame-core@0.1.10':
+ resolution: {integrity: sha512-4PG0mHrk5VmDtt/HH+vs3xDaWY/KVdZLUxlFetkD/szn1NNtHUxM43vCUE/qgulmlV53x8GPBbkwHzcA7Dmpuw==}
+
+ '@farcaster/frame-core@0.1.8':
+ resolution: {integrity: sha512-Y0JATQXa/iaqH3pCp8Dby4iCQbwqw7JJaGtfzUazdr7R+zs3EDP8DYQCkqJu6iGjE9gqgecB+b+DOZpnqMTDNw==}
+
+ '@farcaster/frame-sdk@0.0.60':
+ resolution: {integrity: sha512-MHQwdFT1VPe3kS0NvnORBPb/DQXr8qpdSDgIgfrdVCB8byQ5uFELlr3gQMuFYFyLFQVXgbMl75z8O6+hvorqow==}
+
+ '@farcaster/quick-auth@0.0.5':
+ resolution: {integrity: sha512-Z8hWz/7c33zlmII2AJHja/Wz0C03mm2o+CEBtBylmiun1wC4FMgx1Fal699VQvBUG1lpcJ662WxuRNxKogktDw==}
+ peerDependencies:
+ typescript: 5.8.3
+
'@floating-ui/core@1.7.1':
resolution: {integrity: sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==}
@@ -7426,6 +7446,7 @@ packages:
'@walletconnect/modal@2.7.0':
resolution: {integrity: sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==}
+ deprecated: Please follow the migration guide on https://docs.reown.com/appkit/upgrade/wcm
'@walletconnect/react-native-compat@2.17.3':
resolution: {integrity: sha512-lHKwXKoB0rdDH1ukxUx7o86xosWbttWIHYMZ8tgAQC1k9VH3CZZCoBcHOAAX8iBzyb0n0UP3/9zRrOcJE5nz7Q==}
@@ -8572,6 +8593,9 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
+ comlink@4.4.2:
+ resolution: {integrity: sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==}
+
comma-separated-tokens@1.0.8:
resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==}
@@ -11110,6 +11134,9 @@ packages:
jose@4.15.9:
resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==}
+ jose@5.10.0:
+ resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==}
+
jose@6.0.11:
resolution: {integrity: sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==}
@@ -12619,6 +12646,14 @@ packages:
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
engines: {node: '>= 0.4'}
+ ox@0.4.4:
+ resolution: {integrity: sha512-oJPEeCDs9iNiPs6J0rTx+Y0KGeCGyCAA3zo94yZhm8G5WpOxrwUtn2Ie/Y8IyARSqqY/j9JTKA3Fc1xs1DvFnw==}
+ peerDependencies:
+ typescript: '>=5.4.0'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
ox@0.6.7:
resolution: {integrity: sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA==}
peerDependencies:
@@ -19229,6 +19264,48 @@ snapshots:
find-up: 5.0.0
js-yaml: 4.1.0
+ '@farcaster/frame-core@0.1.10(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)':
+ dependencies:
+ '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)
+ ox: 0.4.4(typescript@5.8.3)(zod@3.25.62)
+ zod: 3.25.62
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - typescript
+ - utf-8-validate
+
+ '@farcaster/frame-core@0.1.8(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)':
+ dependencies:
+ '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)
+ ox: 0.4.4(typescript@5.8.3)(zod@3.25.62)
+ zod: 3.25.62
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - typescript
+ - utf-8-validate
+
+ '@farcaster/frame-sdk@0.0.60(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.62)':
+ dependencies:
+ '@farcaster/frame-core': 0.1.8(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)
+ '@farcaster/quick-auth': 0.0.5(typescript@5.8.3)
+ comlink: 4.4.2
+ eventemitter3: 5.0.1
+ ox: 0.4.4(typescript@5.8.3)(zod@3.25.62)
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - typescript
+ - utf-8-validate
+ - zod
+
+ '@farcaster/quick-auth@0.0.5(typescript@5.8.3)':
+ dependencies:
+ jose: 5.10.0
+ typescript: 5.8.3
+ zod: 3.25.62
+
'@floating-ui/core@1.7.1':
dependencies:
'@floating-ui/utils': 0.2.9
@@ -28012,6 +28089,8 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
+ comlink@4.4.2: {}
+
comma-separated-tokens@1.0.8: {}
comma-separated-tokens@2.0.3: {}
@@ -31203,6 +31282,8 @@ snapshots:
jose@4.15.9: {}
+ jose@5.10.0: {}
+
jose@6.0.11: {}
joycon@3.1.1: {}
@@ -33039,6 +33120,20 @@ snapshots:
object-keys: 1.1.1
safe-push-apply: 1.0.0
+ ox@0.4.4(typescript@5.8.3)(zod@3.25.62):
+ dependencies:
+ '@adraffy/ens-normalize': 1.11.0
+ '@noble/curves': 1.8.2
+ '@noble/hashes': 1.7.2
+ '@scure/bip32': 1.7.0
+ '@scure/bip39': 1.6.0
+ abitype: 1.0.8(typescript@5.8.3)(zod@3.25.62)
+ eventemitter3: 5.0.1
+ optionalDependencies:
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - zod
+
ox@0.6.7(typescript@5.8.3)(zod@3.25.62):
dependencies:
'@adraffy/ens-normalize': 1.11.0