A web-based QR Code and vCard generator for Stand.earth, structured as a modern monorepo.
-
vCard QR Code Generation: Create "business card" QR codes that contain vCard contact information.
-
URL QR Code Generation: Create QR codes to visit a link.
-
WiFi QRCode Generation: Create QR codes to connect to a network.
- Customizable QR Codes: Adjust the appearance of the QR codes.
- Real-time Preview: See a live preview of the QR code as you type.
-
Apple Wallet Pass Generation: Generate Apple Wallet passes from vCard data.
- Automated Photo Lookup: Automatically include a person's photo from the Stand.earth staff page and adds it to the Apple Wallet pass.
- Monorepo Management:
pnpmWorkspaces
- Frontend:
- HTML5
- SCSS
- TypeScript
- Vite
- qr-code-styling
- Backend:
- Node.js
- Express.js
- TypeScript
- Deployment & Infrastructure:
- GitHub Actions (CI/CD)
- Terraform (Infrastructure as Code)
- Google Cloud Platform (GCP)
- Cloud Run
- Secret Manager
- GitHub Pages
This project uses environment variables for all organization-specific settings.
-
Fork the Repository: If you plan to deploy the frontend using your own GitHub account for GitHub Pages, you must first fork this repository. This ensures that the CI/CD pipeline has the necessary permissions to deploy to your account.
(The frontend compiles to a static page, so you can also build it locally and deploy it elsewhere manually very easily.)
-
Create an Environment File: Copy the template file to create your local configuration file. This file is ignored by Git and will not be committed.
cp .env.template .env
-
Edit
.env: Open the .env file and fill in the values for your organization. This includes your Apple Developer Team ID, Pass Type ID, default organization name, and production domains.
To deploy the application, you must configure these variables in your hosting environments.
The frontend is configured at build time. You must set the following as Repository secrets in your GitHub project under Settings > Secrets and variables > Actions:
VITE_ORG_NAMEVITE_ORG_WEBSITEVITE_OFFICE_PHONE_OPTIONSFRONTEND_DOMAINBACKEND_DOMAIN
Get the values for these secrets by running the following make command.
make show-github-secretsThe backend uses runtime environment variables. After your initial deployment, you can set them by running the following make command. It will use the values from your local .env file or prompt you for them.
make set-backend-env-varsThis project uses a Makefile to streamline one-time setup tasks and pnpm for all development commands.
- Node.js (v22+ recommended)
- pnpm (v9+ recommended)
- Google Cloud SDK (for deployment to GCP)
- Terraform (for infrastructure provisioning)
- OpenSSL (for generating local certificates)
-
Clone the repository:
Clone your forked repository (if deploying to GitHub Pages):
git clone https://github.com/YOUR_USERNAME/vcard-qr.git cd vcard-qrOr clone this repository (if deploying elsewhere):
git clone https://github.com/Standearth/vcard-qr.git cd vcard-qr -
Install dependencies: Run this single command from the project root.
pnpmwill install dependencies for all workspaces (frontend,server,shared-utils).pnpm install
-
Generate Local Certificates: You need two sets of local certificates: one for PassKit signing and one for local HTTPS.
# Generates placeholder certs for Apple Wallet signing make add-secrets-local # Generates self-signed certs for localhost (HTTPS) make add-local-https-certs
-
Start the development servers: Run the
devcommand from the project root to start both the frontend and backend servers concurrently.pnpm dev
- The servers will automatically use HTTPS if local certificates are found (see
make add-local-https-certs). - The frontend will run on
https://localhost:5173. - The backend will run on
https://localhost:3000.
When you first access
https://localhost:5173, your browser will show a privacy warning. Click "Advanced" and "Proceed to..." to accept the self-signed certificate. - The servers will automatically use HTTPS if local certificates are found (see
To generate a pass that can be installed on real devices, you must use an official certificate from Apple. The Makefile provides utilities to assist with this multi-step process. You can override the default filenames (signerKey.key, signerCert.pem) by passing them as arguments to the make command (e.g., make add-private-key SIGNER_KEY_FILE=MyNewKey.key).
-
Create a Private Key: This command generates a new private key in the
server/certs/directory. By default, it createssignerKey.key.make add-private-key
-
Create a Certificate Signing Request (CSR): This command uses your private key to generate a CSR. The output filename will be based on the
SIGNER_CERT_FILEvariable (e.g.,signerCert.csr). You can provide your Apple Developer email as a named or positional argument, or be prompted for it interactively.make create-certificate-signing-request your.email@example.com
Upload the resulting
.csrfile to the Apple Developer portal when creating a new Pass Type ID certificate. -
Convert Apple Certificates to PEM Format: After Apple processes your CSR, you will download a
.cerfile. You also need the Apple Worldwide Developer Relations (WWDR) intermediate certificate, which can be downloaded from the Apple Certificate Authority page (specifically the "Worldwide Developer Relations - G4" certificate). Both of these.cerfiles are in DER format and must be converted to PEM format.The
cer-to-pemcommand handles this conversion. Pass the path to your.cerfile as an argument.# Convert your new signer certificate make cer-to-pem path/to/your/signerCert.cer # Convert the WWDR certificate make cer-to-pem path/to/your/AppleWWDRCAG4.cer
This will create a new file with a
.pemextension in the same directory. -
Upload to Secret Manager: Once you have your official
signerKey.key,signerCert.pem(your converted signer cert), andAppleWWDRCAG4.pemfiles, upload them to Google Secret Manager for your production environment.make upload-signer-key path/to/signerKey.key make upload-signer-cert path/to/signerCert.pem make upload-wwdr-cert path/to/AppleWWDRCAG4.pem
Deployment is managed via Terraform and GitHub Actions.
The frontend is hosted on GitHub Pages. Frontend deployment is automated via the .github/workflows/deploy.yml GitHub Actions workflow, which builds the static site and creates a deployment artifact from the dist/ directory. This artifact is then deployed directly to GitHub Page. The frontend site is accessible at the provided GitHub Pages URL, or via a custom subdomain which is configured in the CNAME file and managed through GitHub Pages settings.
The backend is hosted on Google Cloud Run. Backend deployment is automated via the ./github/workflows/deploy-server.yml GitHub Actions workflow, which builds and packages the node microservice for generating and signing Apple Wallet PassKit files, and then deploys that to Google Cloud Run. The backend is accessible at the provided app.run URL, or using a custom subdomain configured below.
The GitHub Actions workflows automate the deployment of the frontend to GitHub Pages and the backend to Google Cloud Run whenever changes are pushed to the main branch.
Monitor the progress of the deployment in the "Actions" tab of your GitHub repository.
-
Initial GCP Configuration:
[!IMPORTANT] Before you begin, make sure you have the Google Cloud CLI installed and have authenticated as a user with sufficient permissions to create and manage Google Cloud projects.
It is highly recommended to use Google Cloud Shell, as it comes pre-configured with the necessary tools and authentications, simplifying the setup process.
Run the
setupMakefile target to create and configure your GCP project, authorization, service accounts, and workload identity federation. This is a one-time setup.make setup
Follow the prompts to enter a unique Google Cloud Project ID. This command will:
- Create a new GCP project (if it doesn't exist).
- Enable necessary Google Cloud APIs.
- Create a service account for GitHub Actions.
- Set up Workload Identity Federation for secure CI/CD.
- Create empty secrets in Google Secret Manager for your Apple Wallet signing certificates.
- Add placeholder certificates to Google Secret Manager if they are empty.
-
Configure GitHub Secrets: After running
make setup, display the required GitHub Actions secrets:make show-github-secrets
Add these secrets to your GitHub repository under
Settings > Secrets and variables > Actions. -
Upload Apple Wallet Signing Certificates: You will need your actual Apple Wallet signing key (
.key), certificate (.pem), and the Apple Worldwide Developer Relations Certification Authority (WWDR) certificate (.pem). You can upload these to Google Secret Manager by passing the file path directly on the command line, which allows you to use shell tab-completion.make upload-signer-key path/to/signerKey.key make upload-signer-cert path/to/signerCert.pem make upload-wwdr-cert path/to/AppleWWDRCAG4.pem
If you run these commands without providing a file path, you will be prompted to enter it interactively.
-
Deploy Infrastructure with Terraform: Apply the Terraform configuration to provision the Cloud Run service and other necessary GCP resources:
make terraform-apply
-
Map Custom Domain (Optional): If you have a custom domain, you can map it to your Cloud Run service. Ensure you have configured a CNAME record pointing to
ghs.googlehosted.comfirst.make map-custom-domain
You can check the status of your domain mapping:
make check-domain-status
Here's a quick reference for common make commands:
make help: Displays all available Makefile targets and their descriptions.make setup: Performs initial GCP project setup.make add-secrets-local: Generates local placeholder certificates for development.make add-local-https-certs: Generates self-signed certificates for local HTTPS.make add-private-key: Generates a new private key for signing.make create-certificate-signing-request [email=your@email.com]: Generates a CSR from the private key to submit to Apple.make cer-to-pem [path/to/file.cer]: Converts a .cer certificate from Apple to the required .pem format.make terraform-apply: Deploys infrastructure via Terraform.make terraform-destroy: Destroys all managed infrastructure.make cleanup-images-now: Immediately deletes all untagged Docker images from the repository.make show-github-secrets: Displays GitHub Actions secrets to be configured.make upload-signer-key [path/to/key]: Uploads your Apple Wallet signer key to Secret Manager.make upload-signer-cert [path/to/cert]: Uploads your Apple Wallet signer certificate to Secret Manager.make upload-wwdr-cert [path/to/wwdr]: Uploads your Apple WWDR certificate to Secret Manager.make map-custom-domain: Maps a custom domain to the Cloud Run service.make check-domain-status: Checks the status of the custom domain mapping.
The frontend is hosted at qr.stand.earth and the backend PassKit service is accessible at pkpass.stand.earth. Copies of key files are stored securely in Stand's 1Password admin vault and should be treated as sensitive data. The remaining .env parameters used locally or in deployment are below:
VITE_ORG_NAME="Stand.earth"
VITE_ORG_WEBSITE="https://stand.earth"
PASS_TEAM_ID="3WCH54M3A8"
PASS_TYPE_ID="pass.earth.stand.vcard"
PASS_DESCRIPTION="Stand.earth Business Card"
PASS_FOREGROUND="rgb(16, 16, 18)"
PASS_BACKGROUND="rgb(245, 244, 237)"
PASS_LABEL="rgb(0, 133, 125)"
CERT_SIGNER_KEY="Stand-PassKit.key"
CERT_SIGNER_CERT="Stand-PassKit.pem"
CERT_WWDR="AppleWWDRCAG4.pem"
FRONTEND_DOMAIN="qr.stand.earth"
BACKEND_DOMAIN="pkpass.stand.earth"
GITHUB_REPO="Standearth/vcard-qr"