Skip to main content

Overview

VCVerifier provides a customizable login page at /api/v1/loginQR that displays a QR code for wallet-based authentication. You can customize the appearance and behavior by providing custom HTML templates and static assets.

Template Directory Structure

Templates and static files are organized as follows:
views/
├── verifier_present_qr.html    # Main login template (required)
└── static/                      # Static assets directory
    ├── css/
    │   └── styles.css
    ├── js/
    │   └── app.js
    └── images/
        └── logo.png

Configuration

Configure the template and static directories in your server.yaml:
server:
  templateDir: "views/"        # Directory containing templates
  staticDir: "views/static/"   # Directory for static assets
The templateDir must contain a file named verifier_present_qr.html which will be rendered when users access the login page.

Required Template File

verifier_present_qr.html

This template is rendered at /api/v1/loginQR and must include the QR code image. Minimum Required Template:
<!DOCTYPE html>
<html>
<head>
    <title>Login with Wallet</title>
</head>
<body>
    <h1>Scan QR Code to Login</h1>
    
    <!-- Required: QR code image -->
    <img src="data:{{.qrcode}}" alt="Login QR Code" />
    
</body>
</html>
{{.qrcode}}
string
required
Data URI containing the QR code image. This must be included in the template using the exact syntax shown above.

Template Variables

The following variables are available in the template context:
{{.qrcode}}
string
Base64-encoded data URI of the QR code image. Use as: <img src="data:{{.qrcode}}" />
VCVerifier uses the goview framework for template rendering, which supports Go’s standard html/template syntax.

Static Assets

Static files in the staticDir are served at the /static path.

Example Directory Structure

views/static/
├── css/
│   └── login.css
├── js/
│   └── qr-refresh.js
└── images/
    ├── logo.png
    └── background.svg

Accessing Static Files

Reference static files in your templates using the /static prefix:
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="/static/css/login.css">
    <script src="/static/js/qr-refresh.js"></script>
</head>
<body>
    <img src="/static/images/logo.png" alt="Logo" class="logo" />
    <img src="data:{{.qrcode}}" alt="QR Code" />
</body>
</html>

Complete Example

Here’s a complete example with styling and branding:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Secure Login</title>
    <link rel="stylesheet" href="/static/css/login.css">
</head>
<body>
    <div class="container">
        <header>
            <img src="/static/images/logo.png" alt="Company Logo" class="logo" />
            <h1>Secure Wallet Login</h1>
        </header>
        
        <main>
            <div class="qr-container">
                <img src="data:{{.qrcode}}" alt="Login QR Code" class="qr-code" />
            </div>
            
            <div class="instructions">
                <h2>How to Login</h2>
                <ol>
                    <li>Open your wallet app</li>
                    <li>Scan the QR code above</li>
                    <li>Approve the authentication request</li>
                </ol>
            </div>
        </main>
        
        <footer>
            <p>Powered by VCVerifier</p>
        </footer>
    </div>
    
    <script src="/static/js/login.js"></script>
</body>
</html>

Advanced Templating

VCVerifier uses Go’s html/template engine, which supports:
{{if .someVariable}}
    <p>Variable is present</p>
{{else}}
    <p>Variable is missing</p>
{{end}}
Standard Go template functions are available:
  • {{printf}} - Formatted printing
  • {{html}} - HTML escaping
  • {{js}} - JavaScript escaping
  • {{urlquery}} - URL query escaping
<p>{{printf "Welcome to %s" "VCVerifier"}}</p>
You can include other templates (if they exist in templateDir):
{{template "header.html" .}}

<img src="data:{{.qrcode}}" />

{{template "footer.html" .}}

Mobile Responsive Design

Ensure your template works well on mobile devices:
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        @media (max-width: 768px) {
            .container {
                padding: 20px;
            }
            
            .qr-code {
                max-width: 250px;
            }
        }
    </style>
</head>

Testing Your Templates

1

Create Template Directory

mkdir -p views/static/css
mkdir -p views/static/js
mkdir -p views/static/images
2

Add Template File

Create views/verifier_present_qr.html with your custom HTML
3

Add Static Assets

Place CSS, JavaScript, and images in the static/ subdirectories
4

Update Configuration

server:
  templateDir: "views/"
  staticDir: "views/static/"
5

Restart VCVerifier

Restart the service to load the new templates
6

Test Login Page

Navigate to /api/v1/loginQR?state=test&client_callback=http://example.com

Common Use Cases

<header>
  <img src="/static/images/company-logo.png" alt="Company" />
  <h1>{{.companyName}} Secure Login</h1>
</header>
@media (prefers-color-scheme: dark) {
  body {
    background: #1a1a1a;
    color: #fff;
  }
  
  .container {
    background: #2d2d2d;
  }
}
Create different template files and switch based on user preference:
server:
  templateDir: "views/en/"  # or views/es/, views/de/, etc.
<div class="qr-container">
  <div class="loading" id="loading">
    <div class="spinner"></div>
    <p>Generating QR Code...</p>
  </div>
  <img src="data:{{.qrcode}}" 
       alt="QR Code" 
       onload="document.getElementById('loading').style.display='none'" />
</div>

Troubleshooting

Common Issues:
  1. Template not found: Ensure verifier_present_qr.html exists in the templateDir
  2. Static files 404: Verify staticDir path is correct and files are in the right location
  3. QR code not displaying: Check that you’re using <img src="data:{{.qrcode}}" /> exactly as shown
  4. Template syntax errors: Validate your Go template syntax

Security Considerations

  • Always escape user input in templates
  • Use HTTPS in production to protect QR code content
  • Don’t include sensitive information in static files
  • Implement Content Security Policy headers

Next Steps

API Reference

Learn about the loginQR endpoint parameters

Frontend Integration

Integrate the login page into your application

Build docs developers (and LLMs) love