The main frontend MVP for the GuildPass ecosystem. Built with Next.js 14 App Router, TypeScript, Tailwind CSS, wagmi/viem, and React Query, this app provides the member and admin dashboards for the GuildPass token-gated community platform.
Part of the Adamantine-Guild project — a Web3 membership and token-gated community platform built for the open-source ecosystem.
- Member dashboard — wallet connect, membership state, community & tier, expiration, badges placeholder, gated resources, profile summary
- Admin dashboard — overview, member list, role assignment, resource access policies, community settings
- Access-gated experiences — gated pages, gated content sections, event access, denied states, upgrade/renew placeholders
- Wallet-aware UX — connect flow, SIWE-authenticated admin experience, role-aware UI states, admin-only sections
- SIWE authentication — Sign-In with Ethereum (EIP-4361) for admin sessions; gasless off-chain signature; short-lived token attached to all mutations
- Local development — mock/demo mode with seeded fake data; typed API layer switches between mock and live; SIWE fully simulated in mock mode
- Node.js 18+
- npm 9+
# Clone and enter
git clone https://github.com/Adamantine-Guild/guildpass-integrations.git
cd guildpass-integrations
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env.local
# Edit .env.local as needed (mock mode requires no changes)NEXT_PUBLIC_MOCK_MODE=true npm run devOpen http://localhost:3000.
# Set NEXT_PUBLIC_CORE_API_URL in .env.local first
npm run devAdmin actions are protected by Sign-In with Ethereum (EIP-4361). After connecting a wallet, admins must sign a one-time, gasless message. The backend verifies the signature and returns a short-lived session token attached as Authorization: Bearer on all privileged mutations.
1. User connects wallet
2. UI shows "Sign In" with explanation — no gas required
3. Frontend requests a nonce: POST /v1/auth/siwe/nonce
4. EIP-4361 message built client-side (domain, statement, nonce, chainId, issuedAt)
5. wagmi signMessage → user approves in wallet
6. POST /v1/auth/siwe/verify → { token, expiresAt }
7. Token stored in sessionStorage; auto-attached to admin mutations
8. 401 from backend shows inline re-auth banner without page redirect
| Method | Path | Body | Response |
|---|---|---|---|
POST |
/v1/auth/siwe/nonce |
{ address } |
{ nonce: string } |
POST |
/v1/auth/siwe/verify |
{ message, signature } |
{ token, address, expiresAt } |
POST |
/v1/auth/siwe/logout |
— (Bearer token in header) | 204 No Content |
In mock mode all three endpoints are simulated in-memory — no backend required.
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_MOCK_MODE |
No | Set true for in-memory mock API; SIWE fully simulated |
NEXT_PUBLIC_DEMO_MODE |
No | Alias for NEXT_PUBLIC_MOCK_MODE |
NEXT_PUBLIC_CORE_API_URL |
Live mode only | Base URL of the guildpass-core access-api |
NEXT_PUBLIC_SIWE_DOMAIN |
No | Domain field in the EIP-4361 message (defaults to window.location.host) |
NEXT_PUBLIC_SIWE_STATEMENT |
No | Human-readable statement shown in the signed message |
See .env.example for a ready-to-copy template.
Modules that are experimental or not yet production-ready are controlled by environment variables. Setting a flag to "false" hides the corresponding navigation item and shows a clear "unavailable" state when the route is visited directly.
| Variable | Default (mock mode) | Default (prod) | Module |
|---|---|---|---|
NEXT_PUBLIC_FEATURE_ADMIN_POLICIES |
true |
true |
Access policy editor in /admin/policies |
NEXT_PUBLIC_FEATURE_EVENTS |
true |
false |
Event access page at /events/* |
NEXT_PUBLIC_FEATURE_RESOURCES |
true |
true |
Gated resources at /resources/* |
NEXT_PUBLIC_FEATURE_ANALYTICS |
false |
false |
Analytics module (not yet built) |
NEXT_PUBLIC_FEATURE_GOVERNANCE |
false |
false |
Governance module (not yet built) |
How flags work:
- All flags are read at build time from
NEXT_PUBLIC_*environment variables. No remote flag service is involved. - An omitted variable falls back to the default shown above.
- In mock/demo mode (
NEXT_PUBLIC_MOCK_MODE=true), flags foradminPolicies,events, andresourcesdefault totrueso the full demo works locally without any extra configuration. - Flags for deferred modules (
analytics,governance) default tofalsein every environment and must be explicitly set to"true"to enable them. - Navigation links for disabled modules are automatically hidden.
- Visiting a disabled route directly renders a clear "Feature unavailable" message instead of broken content.
Adding a new flag:
- Add the typed field to
FeatureFlagsinlib/features.tsand wire up theflag()call. - Document the variable in
.env.examplewith its recommended production default. - Wrap the relevant page with
<FeatureGate enabled={features.yourFlag} name="Module Name">. - Filter the corresponding nav item using
features.yourFlag.
npm run dev # Start Next.js dev server (http://localhost:3000)
npm run build # Production build
npm run start # Start production server (after build)
npm run lint # Lint via Next.js ESLint config
npm run typecheck # TypeScript type checking
npm run sync-types # Compile test/fixtures/openapi.json into lib/api/types.ts
npm run check-types # Validate that types in lib/api/types.ts match the schema| Path | Purpose |
|---|---|
app/* |
Next.js App Router pages |
lib/wallet/providers.tsx |
wagmi, React Query, and SiweAuthContext providers; useSiweAuth() hook |
lib/api/* |
API layer (getApi(address?, token?) switches mock ↔ live) |
lib/api/live.ts |
Live integration with guildpass-core; AuthError for 401 handling |
lib/api/mock.ts |
In-memory mock; simulates SIWE endpoints without real signatures |
lib/api/types.ts |
Shared TypeScript types (auto-generated from openapi.json) |
lib/session.ts |
sessionStorage helpers for SIWE token persistence |
components/ui/* |
Minimal shadcn-style UI primitives |
components/gated.tsx |
Access-gate component |
components/admin-guard.tsx |
3-layer admin guard (wallet → SIWE → role) with SiwePrompt |
components/wallet/connect-button.tsx |
3-state button (disconnected / connected / authenticated) |
components/nav.tsx |
Navigation bar |
test/fixtures/openapi.json |
OpenAPI schema contract fixture representing core API models |
scripts/sync-api-types.js |
Zero-dependency compiler converting openapi.json to typescript types |
- Access API:
lib/api/live.tsintegrates withguildpass-core/v1/*endpoints - Contract clients/ABIs: Add viem/wagmi hooks in feature modules as needed
- Shared types:
lib/api/types.ts— align withguildpass-coreshared types package
All live requests are sent to NEXT_PUBLIC_CORE_API_URL (default http://localhost:4000).
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/v1/session?address=<addr> |
— | Current session for address |
GET |
/v1/community |
— | Community info |
GET |
/v1/members |
— | All member rows |
GET |
/v1/members/:address/membership |
— | Membership for address |
GET |
/v1/members/:address/profile |
— | Profile for address |
GET |
/v1/resources |
— | Available gated resources |
GET |
/v1/policies |
— | Access policies |
POST |
/v1/members/:address/roles |
Bearer | Assign role to member |
PUT |
/v1/policies/:resourceId |
Bearer | Update access policy |
POST |
/v1/auth/siwe/nonce |
— | Request SIWE nonce |
POST |
/v1/auth/siwe/verify |
— | Verify SIWE signature → token |
POST |
/v1/auth/siwe/logout |
Bearer | Invalidate session |
Path and query parameters are URL-encoded. Backend responses are mapped into frontend types via the response-mapping layer in
lib/api/live.ts.
Implemented:
- Core member and admin surfaces listed above
- Basic role assignment and policy editing
- Gated pages and states
Deferred (intentionally):
- Advanced analytics and governance
- Rich profile customization and contribution history
- Social graph and advanced moderation
- Complex admin workflows, rewards visualization, full event management
- Complete billing/subscription management UX
We welcome contributions! See CONTRIBUTING.md for the full guide.
- Browse open issues tagged
good first issueorhelp wanted. - Comment directly on the GitHub issue you'd like to work on.
- Fork the repo, create a feature branch, implement your change, open a PR.
- Contact: cerealboxx123@gmail.com
MIT — see LICENSE.