zabdoc is a full-stack application for SZABIST students to generate assignment cover sheets, lab tasks, and scrape ZabDesk course data. Built with Go (backend) and SvelteKit (frontend), deployed on Heroku and Cloudflare respectively.
zabdoc/
├── cmd/ # CLI entry points
├── internal/
│ ├── application/ # Application initialization & DI container
│ ├── api/
│ │ ├── http/ # HTTP handlers for all endpoints
│ │ └── dto/ # Request/response DTOs
│ ├── services/ # Business logic layer
│ ├── templates/ # PDF templates (HTML partials)
│ ├── middleware/ # HTTP middleware (CORS, logging, etc.)
│ └── router/ # Route definitions
├── worker/ # SvelteKit frontend (Cloudflare Workers)
│ ├── src/
│ │ ├── routes/ # SvelteKit file-based routing
│ │ ├── lib/
│ │ │ ├── components/ # Reusable Svelte components (shadcn-svelte)
│ │ │ ├── stores/ # Svelte reactive state (wizard, form stores)
│ │ │ └── utils/ # Helper functions
│ │ └── app.html # Root HTML template
│ ├── wrangler.toml # Cloudflare Workers config
│ └── package.json
├── go.mod / go.sum # Go dependencies
└── README.md- Runtime: Go 1.24.6+
- HTTP Router: chi - lightweight, composable router with middleware support
- PDF Generation: chromedp - headless Chrome automation for rendering HTML to PDF
- Deployment: Heroku Container Stack (Docker-based)
- Key Flow: HTTP POST → Form DTO validation → PDF generation via headless browser → Binary response
Core Files:
internal/app/app.go- Application setup, dependency injection containerinternal/api/http/handler.go- HTTP handler implementations (health check, PDF generation)internal/router/router.go- Route registration, middleware setup, CORS configurationinternal/api/dto/dto.go- Form data structures (request validation)internal/middleware/- Cross-cutting concerns (CORS, request logging)internal/templates/- HTML template partials used for PDF rendering
- Framework: SvelteKit v2+ with TypeScript, Svelte 5 runes
- Deployment: Cloudflare Workers with
@sveltejs/adapter-cloudflare - UI Library: shadcn-svelte - unstyled, accessible component primitives
- State Management: Svelte stores (reactive
$state()runes) inlib/stores/ - Styling: Tailwind CSS with custom neo-brutalism design tokens
Key Features:
- Multi-step form wizard for document generation (assignment/lab task/lab project)
- ZabDesk data scraper - authentication & fetching attendance/marks
- Local storage persistence for user preferences
- Responsive design with neo-brutalism aesthetic
- Go 1.24.6 or later
- Node.js 20+ (for pnpm compatibility)
- pnpm 9+ (installation guide)
- Docker (recommended for local headless Chrome testing)
- Heroku CLI (for backend deployment)
- Wrangler CLI (for Cloudflare Workers deployment)
# Clone and navigate to project
git clone https://github.com/hammadmajid/zabdoc.git
cd zabdoc
# Install Go dependencies
go mod tidy
# Set port (defaults to 8080)
export PORT=8080
# Run development server
go run .Backend will be available at http://localhost:8080
Available endpoints:
GET /health- Health check endpointPOST /generate- Generate PDF from form data (expects multipart/form-data)POST /scrap- Scrape data from ZabDesk (expects username and password)
# Navigate to frontend directory
cd worker
# Install dependencies using pnpm
pnpm install
# Start development server
pnpm devFrontend will be available at http://zabdoc.localhost:5173
Key pnpm scripts:
pnpm dev- Development server with HMRpnpm build- Build for production (Cloudflare Workers)
# Build Go binary (outputs: zabdoc or zabdoc.exe)
go build -o zabdoc .
# Or use Docker for consistent environment
docker build -t zabdoc:latest .Environment variables for production:
PORT- HTTP port (default: 8080)API_URL- Frontend API endpoint (for CORS)
cd worker
pnpm buildOutput is ready for Cloudflare Workers deployment. Configuration in wrangler.toml.
Uses Heroku Container Stack with Docker. See Heroku Container Registry docs.
heroku login
heroku create zabdoc-api
heroku container:push web
heroku container:release webUses @sveltejs/adapter-cloudflare with wrangler.
cd worker
pnpm build
wrangler deploy-
Go: Follow Effective Go guidelines
- Use staticcheck for linting:
staticcheck ./... - Prefer explicit error handling over panic
- Use dependency injection pattern (see
internal/app/app.go)
- Use staticcheck for linting:
-
TypeScript/Svelte: Use strict TypeScript mode
- Run
pnpm lintbefore committing - Follow Svelte best practices
- Run
-
Start with an issue: Check GitHub Issues
- Pick an existing issue or open a discussion
- Comment on the issue before starting work to avoid duplicates
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Make changes following the code style above
-
Test locally:
- Backend:
go run .+ manual testing - Frontend:
pnpm dev+ browser testing - Both: Verify integration works
- Backend:
-
Commit with clear messages:
git commit -m "add feature X" -
Push and open PR:
git push origin feature/your-feature-name
- Reference the issue: "Closes #123"
- Provide context on changes
- Run
go fmt ./...andpnpm formatbefore submitting
- Backend: Add handler in
internal/api/http/handler.go, register ininternal/router/router.go - Frontend: Use file-based routing in
worker/src/routes/, add components inworker/src/lib/components/ - State: Use Svelte stores in
worker/src/lib/stores/for shared state
- Port already in use: Change PORT env var:
export PORT=3000 && go run . - Chromedp issues: Ensure Chrome/Chromium is available or use Docker
- CORS errors: Check
internal/middleware/cors.goand API_URL env var
- Module not found: Run
pnpm installinworker/directory - Build fails: Clear
.svelte-kitand rebuild:rm -rf .svelte-kit && pnpm build - HMR not working: Check
vite.config.tsconfiguration
Licensed under GNU General Public License v3.0. See LICENSE file for details.
Questions? Open an issue or start a discussion.