|
1 | | -# PowerSync Next.js example |
| 1 | +# PowerSync Next.js Example |
2 | 2 |
|
3 | | -This example is built using [Next.js](https://nextjs.org/) and the [PowerSync JS web SDK](https://docs.powersync.com/client-sdk-references/js-web). |
| 3 | +PowerSync demo using [Next.js](https://nextjs.org/) and the [PowerSync JS web SDK](https://docs.powersync.com/client-sdk-references/js-web). |
4 | 4 |
|
5 | | -To see it in action: |
| 5 | +Syncs data from a local Postgres through a self-hosted PowerSync service. No login required; the Next.js server hands out anonymous JWTs signed with a local key pair. |
6 | 6 |
|
7 | | -1. `cd` into this directory and run `pnpm install`. |
8 | | -2. Copy `.env.local.template` to `.env.local`, and complete the environment variables. You can generate a [temporary development token](https://docs.powersync.com/usage/installation/authentication-setup/development-tokens), or leave blank to test with local-only data. |
9 | | -3. Run `pnpm start`. |
10 | | -4. Open the localhost URL displayed in the terminal output in your browser. |
| 7 | +## Architecture |
| 8 | + |
| 9 | +``` |
| 10 | +Browser (WASQLite) |
| 11 | + ↕ sync (WebSocket) |
| 12 | +PowerSync service <-> Postgres (source DB) |
| 13 | + ↕ bucket storage |
| 14 | +Postgres (storage DB) |
| 15 | +
|
| 16 | +Browser -> POST /api/data -> Next.js API route -> Postgres (writes) |
| 17 | +Browser -> GET /api/auth/token -> Next.js API route -> signed JWT |
| 18 | +PowerSync -> GET /api/auth/keys -> Next.js API route -> JWKS (public key) |
| 19 | +``` |
| 20 | + |
| 21 | +## Prerequisites |
| 22 | + |
| 23 | +- [Docker](https://www.docker.com/) (running) |
| 24 | +- [PowerSync CLI](https://docs.powersync.com/self-hosting/installation) (`npm i -g @powersync/cli`) |
| 25 | +- Node.js >= 18 and [pnpm](https://pnpm.io/) |
| 26 | + |
| 27 | +## Setup |
| 28 | + |
| 29 | +```bash |
| 30 | +# 1. Install deps |
| 31 | +pnpm install |
| 32 | + |
| 33 | +# 2. Create env file |
| 34 | +cp .env.local.template .env.local |
| 35 | + |
| 36 | +# 3. Generate a JWT key pair and paste the output into .env.local |
| 37 | +pnpm generate-keys |
| 38 | + |
| 39 | +# 4. Start local Postgres + PowerSync |
| 40 | +pnpm local:up |
| 41 | + |
| 42 | +# 5. Start Next.js |
| 43 | +pnpm dev |
| 44 | +``` |
| 45 | + |
| 46 | +Open [http://localhost:3000](http://localhost:3000). |
| 47 | + |
| 48 | +### About the key pair |
| 49 | + |
| 50 | +PowerSync validates JWTs the Next.js app issues by fetching a JWKS at [/api/auth/keys](src/app/api/auth/keys/route.ts). The private key signs tokens; the public key is what PowerSync fetches. Both must be set in `.env.local` — the app will refuse to start token issuance without them. |
| 51 | + |
| 52 | +`pnpm generate-keys` prints base64-encoded JWKs to stdout. Copy the two lines into `.env.local`: |
| 53 | + |
| 54 | +``` |
| 55 | +POWERSYNC_PRIVATE_KEY=<base64> |
| 56 | +POWERSYNC_PUBLIC_KEY=<base64> |
| 57 | +``` |
| 58 | + |
| 59 | +Restart `pnpm dev` after changing these values. |
| 60 | + |
| 61 | +## Project structure |
| 62 | + |
| 63 | +``` |
| 64 | +src/ |
| 65 | +├── app/ |
| 66 | +│ ├── api/ |
| 67 | +│ │ ├── auth/ |
| 68 | +│ │ │ ├── keys/route.ts JWKS endpoint for PowerSync |
| 69 | +│ │ │ └── token/route.ts Anonymous JWT endpoint |
| 70 | +│ │ └── data/route.ts CRUD writes to Postgres |
| 71 | +│ ├── globals.css |
| 72 | +│ ├── layout.tsx |
| 73 | +│ └── page.tsx |
| 74 | +├── components/ |
| 75 | +│ ├── CustomerList.tsx |
| 76 | +│ ├── StatusPanel.tsx |
| 77 | +│ └── SyncedContent.tsx |
| 78 | +└── library/ |
| 79 | + ├── auth-keys.ts Loads RSA key pair from env (server only) |
| 80 | + ├── db.ts Postgres pool (server only) |
| 81 | + └── powersync/ |
| 82 | + ├── connector.ts Fetch token + upload mutations |
| 83 | + ├── powersync-provider.tsx PowerSync context provider |
| 84 | + └── schema.ts Client-side table schema |
| 85 | +``` |
| 86 | + |
| 87 | +## Environment variables |
| 88 | + |
| 89 | +All config lives in `.env.local`. Docker Compose also reads from this file (via a symlink at `powersync/docker/.env`). |
| 90 | + |
| 91 | +| Variable | Required | What it does | |
| 92 | +|---|---|---| |
| 93 | +| `POWERSYNC_URL` | yes | PowerSync service URL, also used as the JWT audience | |
| 94 | +| `DATABASE_URL` | yes | Postgres connection for Next.js API routes (uses `localhost`) | |
| 95 | +| `POWERSYNC_PRIVATE_KEY` | yes | Base64-encoded JWK private key — generate with `pnpm generate-keys` | |
| 96 | +| `POWERSYNC_PUBLIC_KEY` | yes | Base64-encoded JWK public key — generate with `pnpm generate-keys` | |
| 97 | +| `PS_DATABASE_*` | yes | Postgres credentials used by Docker | |
| 98 | +| `PS_STORAGE_*` | yes | Separate Postgres for PowerSync internal storage | |
| 99 | +| `PS_DATA_SOURCE_URI` | yes | Postgres URI inside Docker (uses `pg-db` hostname) | |
| 100 | +| `PS_STORAGE_SOURCE_URI` | yes | Storage Postgres URI inside Docker (uses `pg-storage` hostname) | |
| 101 | + |
| 102 | +## Scripts |
| 103 | + |
| 104 | +| Command | What it does | |
| 105 | +|---|---| |
| 106 | +| `pnpm dev` | Start Next.js dev server | |
| 107 | +| `pnpm build` | Production build | |
| 108 | +| `pnpm generate-keys` | Print a fresh JWT key pair for `.env.local` | |
| 109 | +| `pnpm local:up` | Start PowerSync + Postgres via Docker | |
| 110 | +| `pnpm local:down` | Stop Docker stack | |
| 111 | + |
| 112 | +## Resetting the database |
| 113 | + |
| 114 | +If you change the schema, wipe the Docker volumes so the init SQL runs again: |
| 115 | + |
| 116 | +```bash |
| 117 | +powersync docker stop --directory powersync --remove --remove-volumes |
| 118 | +powersync docker reset --directory powersync |
| 119 | +``` |
0 commit comments