A modern web application for designing and printing custom playing cards with rich text descriptions, image support, and professional PDF export.
π Launch Application
- Rich Text Editor: Format card descriptions with bold, italic, strikethrough, and lists using TipTap
- Image Upload: Add custom images to card centers
- Title & Description: Fully customizable card content
- Live Preview: See your changes in real-time
- Multi-Card Decks: Create and manage collections of cards
- Quantity Control: Set print quantities for each card individually
- Grid View: Visual overview of your entire deck
- Hybrid Storage: Decks are saved using
localStorage, while large assets (images) are efficiently managed in IndexedDB for high performance and scalability.
- Google Drive Integration: Sync your entire library across devices using your private Google Drive storage.
- Bidirectional Sync: Automatically detects changes in the cloud and keeps your local library up to date.
- Atomic Image Storage: Images are stored as separate binary assets (blobs) rather than embedded in JSON, optimizing sync speed and memory usage.
- Conflict Resolution: Smart SHA-256 hash-based comparison avoids unnecessary prompts, while genuine conflicts are handled through a clean visual interface.
- Background Migration: Seamlessly upgrades legacy decks with embedded Base64 images to the new optimized storage format.
- Toast Notifications: Non-intrusive, real-time feedback for sync status, uploads, and system events.
- Responsive Animations: Fluid transitions and micro-interactions powered by
framer-motion. - Dark Mode: Fully supports modern dark mode with curated color palettes.
- Multi-Page Layout: Automatically generates 3x3 grid layouts (9 cards per A4 page)
- Cut Lines: Dashed guides for easy physical cutting
- High Quality: SVG-based rendering using
html-to-imagefor accurate layouts - Batch Export: Export entire decks with custom quantities in one click
- PDF Export: Multi-page, print-ready PDFs with cut lines
- SVG Export: Individual cards as scalable vector graphics
- Template Synchronization: Load standard SVG files as card templates. The application automatically detects and maps elements.
- Visual Sync: Position, rotation, scale, opacity, fonts, and colors of SVG elements are faithfully rendered in the Card Editor.
- Bi-directional Editing: Changes made in the Style Editor (e.g., moving a title or changing a font) are written back to the SVG upon export.
- Reference Mapping: Use
data-refattributes in your SVGs (e.g.,data-ref="title") to explicitly link graphical elements to card properties. These references are displayed in the editor for easy debugging.
- Node.js 18+
- npm or yarn
# Clone the repository
git clone <repository-url>
cd cardcraftstudio
# Install dependencies for all apps
npm install
# Start development server
# For Frontend only
npm run dev:web
# For Full Stack (Front + Back)
npm run devThe application will be available at http://localhost:5173/
To enable cloud synchronization, you must configure a Google OAuth Client ID:
- Go to the Google Cloud Console.
- Create a Project (e.g., "CardCraftStudio").
- Go to APIs & Services > Library and search for "Google Drive API". Click Enable.
- Go to APIs & Services > OAuth consent screen:
- Select External.
- Fill in the required App Information (App name, support email, developer email).
- Add the scope:
.../auth/drive.file(View and manage Google Drive files and folders that you have opened or created with this app).
- Go to APIs & Services > Credentials:
- Click Create Credentials > OAuth client ID.
- Select Web application as the type.
- Under Authorized JavaScript origins, add:
https://gnuton.github.iohttp://localhost:5173(for local development)
- Click Create and copy your Client ID.
For local use with full synchronization features, you need to configure both the frontend and backend environment variables.
Create a .env file in apps/backend/ (see .env.example):
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=http://localhost:5173/CardCraftStudio/oauth-callback.html
TOKEN_ENCRYPTION_KEY=a-random-32-char-stringCreate a .env file in apps/web/ (see .env.example):
VITE_GOOGLE_CLIENT_ID=your-client-id
VITE_API_BASE_URL=http://localhost:3001To inject credentials into your production environment, add the following secrets in GitHub (Settings > Secrets and variables > Actions):
| Secret Name | Description |
|---|---|
GCP_PROJECT_ID |
Your Google Cloud Project ID |
WIF_PROVIDER |
Workload Identity Federation Provider ID |
WIF_SERVICE_ACCOUNT |
Service Account email for Workload Identity |
GOOGLE_API_KEY |
Google API Key for Custom Search |
GOOGLE_CUSTOM_SEARCH_CX |
Google Custom Search Engine ID |
GOOGLE_CLIENT_ID |
Google OAuth Client ID |
GOOGLE_CLIENT_SECRET |
Google OAuth Client Secret |
TOKEN_ENCRYPTION_KEY |
A random 32-character string (for encrypting refresh tokens) |
JWT_SECRET |
A random string (for signing authentication tokens) |
STRIPE_SECRET_KEY |
Stripe Secret Key (for premium features) |
STRIPE_WEBHOOK_SECRET |
Stripe Webhook Signing Secret |
The CI/CD pipeline will automatically use these to provision infrastructure via Terraform and configure the Cloud Run backend.
- Start the App: Run
npm run devand openhttp://localhost:5173/ - Add a Card: Click "Add New Card" in the Deck Studio
- Design Your Card:
- Enter a title
- Add a description using the rich text editor
- Upload an image (optional)
- Save: Click "Save to Deck" to add it to your collection
- Set Quantities: In the Deck Studio, use the "Qty" input to set how many copies of each card to print
- Download: Click "Download PDF" to generate a multi-page PDF with all cards
- Print: The PDF includes cut lines for easy physical card creation
- Edit a Card: Click the edit icon on any card in the Deck Studio
- Export SVG: Click "Export SVG" to download the card as a scalable vector graphic
/
βββ apps/
β βββ web/ # Frontend Application (@cardcraft/web)
β β βββ src/
β β β βββ components/ # React components
β β β βββ services/ # Drive & Image services
β β β βββ App.tsx
β β βββ public/
β β βββ package.json
β β
β βββ backend/ # Backend Application (@cardcraft/backend)
β βββ src/
β βββ package.json
β
βββ package.json # Root workspace config
βββ .github/workflows/ # CI/CD pipelines
- React 18 - UI framework
- TypeScript - Type safety
- Vite - Build tool and dev server
- TailwindCSS - Styling
- Dexie.js - IndexedDB wrapper for local image storage
- Framer Motion - Smooth UI animations
- TipTap - Rich text editing
- html-to-image - SVG/Image generation
- jsPDF - PDF creation
- Lucide React - Icons
- Vitest - Unit testing
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage# Create production build
npm run build
# Preview production build
npm run preview- Dimensions: Poker-sized cards (2.5" Γ 3.5" / 63.5mm Γ 88.9mm)
- Layout: 3Γ3 grid per A4 page
- Border: 1px black border (standardized)
- Format: A4 (210mm Γ 297mm)
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
The project includes comprehensive unit tests for critical functionality:
- β Card rendering
- β Deck management
- β PDF generation with mocked dependencies
- β Google Drive Sync & Conflict Resolution (Bidirectional)
- β User interactions
Run npm test to execute the test suite.
Copyright (c) 2026 Antonio 'GNUton' Aloisio
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- Built with Vite
- Styled with TailwindCSS
- Icons by Lucide
- Rich text editing powered by TipTap