OfflineHQ / marketplace

https://offline.live/
GNU General Public License v3.0
0 stars 0 forks source link

Offline logo

Offline: Next-gen Consumer Brand Interaction Platform

[!IMPORTANT]
Offline development has been stopped on July 2024 and the project is no longer maintained.

License: GPL v3

OverviewArchitectureQuick InstallEnvironment ConfigurationProject StructureTech StackLibrariesTestsNX WorkspaceTroubleshootServicesLicense

✨ Features

Project Overview

Offline is an innovative platform designed to revolutionize brand-customer interactions through user-centric applications leveraging blockchain and NFT technologies. The project consists of three main applications:

  1. Marketplace (apps/web): The user-facing app where customers can browse and purchase tickets for events offered by organizers. This serves as the main entry point for consumers to interact with brands and access exclusive experiences.

  2. Back-office (apps/back-office): A comprehensive management interface for organizers to create and manage their events, smart contracts, and analyze performance metrics. This empowers brands to easily create and manage their offerings on the Offline platform.

  3. Unlock (apps/unlock): An iframe app that allows users to connect their Offline smart contract wallet across various platforms outside of Offline. This includes integration with Shopify stores for token-gating campaigns, expanding the utility of Offline's blockchain-based assets.

Architecture

The Offline Marketplace Monorepo employs a microservices architecture with the following key components:

Quick Install

  1. Install pnpm: npm install -g pnpm
  2. Install all dependencies: pnpm install
  3. Provide the required API keys in the .env.local file.

[!TIP] Refer to the Environment Configuration section to set up your .env.local with the required API keys.

  1. Run the project: pnpm start

Environment Configuration

[!NOTE]
In order to run the project, you need to configure the following environment variables in you .env.local file

Alchemy env

Our platform uses Alchemy as an RPC provider for the Polygon blockchain. You need to create an account and get an API key on the alchemy dashboard:

NEXT_PUBLIC_ALCHEMY_API_KEY=
ALCHEMY_API_KEY=
ALCHEMY_AUTH_TOKEN=
# Warning ! Those api keys are going to get leaked in the client side code so it's advised to set ALLOWLIST DOMAIN in the alchemy dashboard to your apex domain (in our case www.offline.live) in order to avoid someone hijacking your api keys.

JWT secret keys

In order to secure your JWT authentication provided by Next Auth you are going to need to generate your own RSA-256 keys.

Configure Hasura and Next Auth with same RSA key

You need to configure hasura and next auth to have the same asymmetric key. One is provided by default but you can generate your own RSA 256 key using those commands:

# Don't add passphrase

ssh-keygen -t rsa -P "" -b 4096 -m PEM -f jwtRS256.key

ssh-keygen -e -m PEM -f jwtRS256.key > jwtRS256.key.pub

https://hasura.io/blog/next-js-jwt-authentication-with-next-auth-and-integration-with-hasura/

awk -v ORS='\\n' '1' jwtRS256.key.pub | pbcopy
{ "type": "RS256", "key": "<insert-your-public-key-here>"}
cat jwtRS256.key | pbcopy

Don't forget to add double quotes "" arround so that \n are interpreted correctly

Project Structure

Access to the services and app URLs locally

The console is used as a backoffice to handle the graphQL server and to innerlink all the microservices.

This is the main web app where you can browse and purchase tickets for events. It also serve as an API provider for external integrations like our Shopify tokengating app.

This is the back-office app where organizers can manage their events, smart contracts and analyze the performance metrics.

This is the iframe app where the users connect their smart wallet to our platform seamlessly across domains. It is embedded in the Shopify stores for tokengating campaigns.

The Stack

Docker

This repo is configured to be built with Docker, and Docker compose.

To build all apps in this repo:

pnpm docker:build

To shutdown all running containers:

pnpm docker:stop

To launch all the services containers:

pnpm docker:services

The command to run all the services in this repo is

pnpm docker:services

The command to run all the containers for unit and integration test is

pnpm docker:test

Storybook

We have four separate Storybooks for different parts of our project:

  1. UI Components: Individual stories for each component (mostly based on shadcn/ui). View UI Storybook

  2. Web Platform: Exposes the Offline platform user-facing app. View Web Storybook

  3. Back-office: Exposes the Offline platform organizer app. View Back-office Storybook

  4. Unlock: Exposes the Offline iframe app. View Unlock Storybook

We use interaction testing with the Storybook version of Jest and Testing Library to provide dynamic demonstrations of individual components along with testing.

Additionally, we use Chromatic in our CI pipeline to spot and approve/decline UI changes across all our Storybooks.

Utilities

This repo has some additional tools already setup for you:

Libraries

Next Auth & Cometh Connect

This project uses Next-Auth in conjunction with Cometh Connect to provide secure authentication for users.

Our authentication method utilizes smart wallet signatures, offering a seamless and secure connection through the verification of a signature on a smart contract. This approach leverages blockchain technology to provide a robust and user-friendly authentication experience.

The authentication providers and configuration can be found in libs/next/next-auth/options.

We associate the smart account with a Hasura account by persisting the wallet address and a UUID in our database.

For more details on the signature verification process, refer to the Cometh Connect documentation.

GraphQL code generator

The command pnpm graphql-codegen will launch the graphql-codegen script. All the codegen definitions are written in the file codegen.ts. You should run this command each time you modify a graphql query or update something on the hasura console to have the updated generated sdk and utilities functions.

The generator is divided in three parts, corresponding to the role of anonymous, user and admin, targeting the graphql hasura server for those respective roles.

Each one have a graphql schema and an ast schema generated and specfic sdk.

Anonymous

The graphql queries definition are defined in libs/gql/anonymous/api/queries. We use a generic sdk with a simple fetch query in order to facilitate the querying the data for the anonymous role. Those queries doesn't need any authentication and thus are limited to read only access on some basic information about the events.

User

The graphql queries definition are defined in libs/gql/user/api/queries. We use the React-Query module in order to facilitate the querying the data for the user role in the fontend client. The hasura service will read the auth cookie in order to validate the request. We also generate a generic sdk in order to facilitate testing of user query with jest on libs/test-utils/gql/src/generated/test-account.tswhere we provide a Bearer JWT instead of a cookie because jest is not capable to provide one.

Admin

The graphql queries definition are defined in libs/gql/admin/api/queries. We use a generic sdk with a simple fetch query in order to facilitate the querying the data for the admin role. Those queries are made on the server side of the frontend. Hasura will allow the request through the providing of the X-Hasura-Admin-Secret.

shadcn/ui

We use shadcn/ui as our component library. It provides a set of re-usable components that you can copy and paste into your apps.

Key features of shadcn/ui in our project:

Our custom implementations and extensions of shadcn/ui components can be found in the libs/ui/components directory. We've adapted these components to fit our specific needs while maintaining the core benefits of the library.

For more information on how we use and customize shadcn/ui, refer to our UI Components Storybook.

Tests

Jest

Jest is the test runner used for unit and integration tests. To run all the Jest tests on affected code, you can use the command:

pnpm affected:test

The global settings for Jest are located in tools/test. This directory contains a docker-compose file and an env file to launch specific services used for the integration tests:

Coverage for all the libraries is created in the root of the workspace. In order to maintain code quality, you can uncomment this section with the minimum coverage before the test reports a failure on CI:Coverage for all the libs is created in the root of the workspace. In order to maintain code quality, you can uncommit this section with the minimum coverage before the test report a failure on CI:

{
  // global: {
  // branches: 80,
  // functions: 80,
  // lines: 80,
  // statements: 80,
  // },
}

Playwright

Playwright is the test runner used for e2e tests. The tests for the web app are located in apps/web/e2e and apps/back-office/e2e.

Before running the tests, be sure that all the service containers are running with:

pnpm docker:services

The test command will wait for all the necessary services to be reachable before launching Playwright.

To run all the Playwright tests on affected code, you can use the command:

pnpm affected:e2e

NX Workspace

This project was generated using Nx.

🔎 Smart, Fast and Extensible Build System

Categories of libraries

In a workspace, libraries are typically divided into four different types:

Feature

Libraries that implement "smart" UI (e.g. is effectful, is connected to data sources, handles routing, etc.) for specific business use cases.

UI

Libraries that contain only presentational components. That is, compo- nents that render purely from their props, and calls function handlers when interaction occurs.

Data-access

Libraries that contain the means for interacting with external data services; external services are typically backend services.

Utility

Libraries that contain common utilities that are shared by many projects.

Troubleshoot

In case you need your own image instead of sebpalluel/hasura_cli_with_socat_and_curl you can do the following command to publish it in docker hub.

Be sure to have activated the buildx module first by following this article

cd hasura && docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t <username>/<image>:latest --push .

Services

Our platform leverages a variety of cutting-edge services to deliver a robust and feature-rich experience. Here's an overview of our key technology partners:


Cometh Connect
Smart Wallet infrastructure

Blockchain RPC provider

NFT smart contract management

Web app and API hosting

Meta-transaction relayer

GraphQL API gateway

Serverless Postgres database provider

Bytescale
Secure file management

KYC and AML solutions

Payment processing

Analytics platform

Error tracking
hygraph-logo
Headless CMS for event content
Clone Project

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.