I Built a Free PDF Toolkit in Go + Astro — Here’s What I Learned

Every few months I find myself needing to merge two PDFs or pull a few pages out of a big document. I open a search, find a tool, and immediately get hit with “sign up to continue” or “buy premium to process files over 5MB.” For a 30-second task.

So I built PDFCrush — a free online PDF toolkit that does merge, split, and compress without accounts or upsells. Here is what the process looked like and what I learned along the way.

The Stack

  • Backend: Go with the chi router
  • Frontend: Astro with Tailwind CSS
  • Database: SQLite via modernc.org/sqlite
  • PDF processing: pdfcpu (pure Go)
  • Hosting: Hetzner ARM64 VPS, Caddy reverse proxy, Cloudflare

No frameworks on the backend. No ORM. No Redis. The entire thing is a single Go binary serving both the API and the static frontend.

Why Go?

I wanted a single binary I could scp to a cheap ARM64 VPS and run. No runtime, no dependency hell, no node_modules on the server. Go gives me that plus genuinely good concurrency for handling file uploads.

The server setup is minimal — chi for routing, slog for structured JSON logging, and standard library for everything else:

r := chi.NewRouter()

r.Use(chimw.RequestID)
r.Use(chimw.RealIP)
r.Use(chimw.Logger)
r.Use(chimw.Recoverer)
r.Use(middleware.SecurityHeaders)
r.Use(middleware.CORS("*"))

r.Route("/api/v1", func(r chi.Router) {
    r.Get("/health", handlers.HealthCheck(store))

    // PDF operations — rate limited for free users.
    r.With(rateLimiter.Limit).Post("/pdf/merge", pdfHandlers.Merge)
    r.With(rateLimiter.Limit).Post("/pdf/split", pdfHandlers.Split)
    r.With(rateLimiter.Limit).Post("/pdf/compress", pdfHandlers.Compress)
})

Chi’s middleware chaining with .With() is one of those things that looks obvious but makes route-level concerns (rate limiting, auth) really clean.

Pure Go PDF Processing (No CGO)

This was the decision that shaped the whole project. Most PDF libraries in Go lean on C bindings (poppler, MuPDF, etc.), which means CGO, which means cross-compilation headaches and no static binaries on ARM64 without pain.

Instead I used pdfcpu, which is pure Go. The processing layer is thin:

func (p *Processor) Merge(files []string) (string, error) {
    if len(files) < 2 {
        return "", fmt.Errorf("pdf: merge requires at least 2 files, got %d", len(files))
    }

    outFile := filepath.Join(p.uploadDir, uuid.New().String()+".pdf")

    conf := model.NewDefaultConfiguration()
    if err := api.MergeCreateFile(files, outFile, false, conf); err != nil {
        return "", fmt.Errorf("pdf: merge failed: %w", err)
    }

    slog.Info("pdf merge completed", "input_count", len(files), "output", outFile)
    return outFile, nil
}

Split and compress follow the same pattern — validate inputs, call pdfcpu, return a path. The Processor struct owns the upload directory and max file size, and every handler cleans up temp files with defer:

defer h.processor.Cleanup(savedPaths...)

The trade-off: pdfcpu does not do image resampling for compression, so “compress” is really “optimize the PDF structure” (remove duplicate objects, linearize streams). For most office-generated PDFs this still cuts 20-40% off the size. For image-heavy PDFs, less so. Honest about it, and it still beats “please sign up first.”

SQLite for Everything

I use modernc.org/sqlite — a pure Go translation of SQLite’s C source. No CGO needed. It works on ARM64, M-series Macs, and Linux AMD64 without any build flags.

db, err := sql.Open("sqlite", dbPath)

pragmas := []string{
    "PRAGMA journal_mode=WAL",
    "PRAGMA foreign_keys=ON",
    "PRAGMA busy_timeout=5000",
    "PRAGMA synchronous=NORMAL",
}

SQLite handles rate-limit counters, operation logs, subscriptions, and email signups. For a tool that processes maybe a few hundred requests a day, it is absurd overkill to reach for Postgres. WAL mode gives me concurrent reads while writes are happening, and the entire database is a single file I can back up with cp.

Rate Limiting Without Redis

The rate limiter is SQLite-backed. It counts operations per IP within a sliding window:

type RateLimiter struct {
    store     *storage.Store
    maxOps    int
    window    time.Duration
    proSecret string
}

func (rl *RateLimiter) Limit(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := extractIP(r)

        // Pro users bypass rate limiting.
        proEmail := proauth.ReadProEmail(r, rl.proSecret)
        if proEmail != "" {
            isPro, _ := rl.store.IsProUser(r.Context(), proEmail)
            if isPro {
                next.ServeHTTP(w, r)
                return
            }
        }

        since := time.Now().Add(-rl.window)
        count, _ := rl.store.GetOperationCount(r.Context(), ip, since)

        if count >= rl.maxOps {
            w.Header().Set("Retry-After", fmt.Sprintf("%d", int(rl.window.Seconds())))
            writeJSONError(w, http.StatusTooManyRequests,
                fmt.Sprintf("rate limit exceeded: %d operations per %s", rl.maxOps, rl.window))
            return
        }

        rl.store.RecordOperation(r.Context(), ip)
        next.ServeHTTP(w, r)
    })
}

Free users get 5 operations per 24 hours. Pro users (identified by an HMAC-signed HTTP-only cookie) bypass the limit entirely. No Redis, no in-memory maps that reset on deploy — the counts survive restarts because they live in SQLite.

Security Without Overthinking It

A middleware function sets the standard hardening headers:

func SecurityHeaders(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("X-Content-Type-Options", "nosniff")
        w.Header().Set("X-Frame-Options", "DENY")
        w.Header().Set("X-XSS-Protection", "1; mode=block")
        w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
        w.Header().Set("Content-Security-Policy",
            "default-src 'self'; script-src 'self' 'unsafe-inline'; ...")
        next.ServeHTTP(w, r)
    })
}

Uploaded files get validated with magic bytes (%PDF- header check) and saved with UUID filenames to prevent path traversal. Files are deleted immediately after the response is sent. There is also a background cleanup job that sweeps stale uploads every hour, just in case.

Why Astro for the Frontend

Astro ships zero JavaScript by default. For a tool where the landing page is static marketing content and the actual app is one interactive page, that is perfect. The landing page loads fast (just HTML + CSS), and the interactive PDF uploader is a React island hydrated only on the app page.

The entire frontend builds to static files that the Go server serves directly — no separate Node process in production.

What I Would Do Differently

Start with better compression. pdfcpu’s optimize is solid for structural cleanup but does not resample images. If I were starting over, I would evaluate whether Ghostscript via a subprocess (ugly but effective) is worth it for the compress feature specifically.

Skip the dual payment provider setup. I wired up both Stripe and LemonSqueezy. In practice, Stripe handles everything. The abstraction cost was not worth the optionality.

Add WebSocket progress for large files. Right now, large merges just hang with a spinner until the response comes back. A progress stream would make the UX feel faster even if the processing time is the same.

The Numbers

The whole thing runs on a single Hetzner CAX21 (ARM64, 4 vCPUs, 8GB RAM) that costs about 7 EUR/month — and that VPS also hosts two other products. Memory usage hovers around 30MB for the Go process. Deploys are rsync + docker build on the VPS, done in under a minute.

Try It

If you need to merge, split, or compress PDFs, give it a try at pdfcrush.dev — it is free, no signup required, and your files are deleted immediately after processing.

The source is part of a larger monorepo where I am experimenting with AI agents that build and manage products autonomously, but that is a story for another post.

How to Verify US Business Entities Across States Without Paying $500/mo for an API

If you work in compliance, sales, or risk, you’ve probably needed to verify whether a business is actually registered, who its officers are, or when it was formed.

The commercial APIs that do this — Cobalt Intelligence, OpenCorporates, Dun & Bradstreet — charge $300-500/month minimum. Some charge per lookup. For startups, small compliance teams, or anyone doing occasional due diligence, that’s hard to justify.

Here’s the thing: all of this data is public. Every US state maintains a Secretary of State (or equivalent) database where business registrations are filed. The information is free to access. The problem is that each state has its own portal, its own search interface, its own data format, and its own quirks.

I built free-to-use actors on Apify that let you search the four largest state business registries through a single, consistent interface. No API keys. No subscriptions. Pay only for the results you use.

What you get

Each actor returns structured data including:

  • Entity name and entity number
  • Entity type (LLC, Corporation, LP, etc.)
  • Formation/registration date
  • Status (Active, Dissolved, Suspended, etc.)
  • Registered agent name and address
  • Officers/directors (where available)
  • Principal address
  • Jurisdiction of formation
  • Filing history (where available)

All returned as clean JSON. Export to CSV, Excel, Google Sheets, or consume via API.

The four states

These cover roughly 40% of all US business entities:

California Secretary of State

Search by entity name or entity number. Returns formation date, status, agent for service of process, and entity type. California has 4+ million active business entities.

Try it on Apify

Texas Comptroller of Public Accounts

Search by entity name, taxpayer number, or SOS file number. Returns officers, registered agent, EIN, addresses, franchise tax status. Texas has 3+ million active entities.

Try it on Apify

New York Division of Corporations

Search by entity name or DOS ID. Returns service of process info, CEO, registered agent, stock details, filing dates, jurisdiction. New York has 2+ million active entities.

Try it on Apify

Florida Division of Corporations

Access bulk filing data from the public Sunbiz SFTP server. Parse daily or quarterly data dumps with officers, registered agent, addresses, annual reports. Florida has 5+ million entities on record.

Try it on Apify

Use cases

KYC/AML compliance: Verify that a business counterparty is actually registered and in good standing before onboarding. Cross-check officer names against what the business self-reported.

Sales prospecting: Build targeted lists of newly formed LLCs or corporations in specific states. Filter by formation date to find businesses less than 90 days old — they’re actively buying services.

Due diligence: Before an investment, acquisition, or partnership, verify the target company’s registration status, officers, and agent for service of process across every state where they claim to operate.

Legal research: Find registered agent information for service of process. Identify all entities associated with a particular officer or address.

Competitive intelligence: Track when competitors form new entities, change officers, or register in new states.

How it compares to paid APIs

Feature Commercial APIs ($300-500/mo) These Apify actors
States covered 50 states CA, TX, NY, FL (40% of entities)
Pricing Monthly subscription Pay per result ($0.005/result)
Minimum commitment Monthly or annual None
Bulk export Usually extra Included
API access Yes Yes (Apify API)
Freshness Varies Real-time from state portals
Integrations Custom Zapier, Make, Google Sheets, Slack, Airtable

For teams that only need the four largest states, the cost difference is significant. A 1,000-entity verification batch costs about $5 instead of $300+/month.

Getting started

  1. Go to any of the actor pages linked above
  2. Enter a business name or entity number
  3. Click “Start” — results appear in seconds
  4. Export as JSON, CSV, or Excel

For programmatic access, use the Apify API to trigger runs and retrieve results. Works with any language that can make HTTP requests.

What’s next

I’m expanding to more states. Illinois, New Jersey, Ohio, Pennsylvania, and Georgia are in the pipeline. The goal is all 50 states through a single, consistent interface.

If there’s a specific state you need, let me know in the comments — I’ll prioritize based on demand.

All actors: apify.com/pink_comic

Idempotency Situation

The problem is
Same transaction may be executed multiple times
This can happen due to network retry or duplicate request
This may lead to wrong balances

Initial Data
Alice has 1000
Bob has 500

Normal Transfer
Transfer 200 from Alice to Bob

After transaction
Alice becomes 800
Bob becomes 700

Duplicate Execution
Same transfer runs again

After second execution
Alice becomes 600
Bob becomes 900

Transaction is applied again

Database allows repeated execution
It does not know whether request is duplicate
Each execution is treated as a new operation

Because database only ensures consistency per transaction
It does not track duplicate requests
There is no built in mechanism to stop same transfer again

Database ensures No partial updates and Valid data state

Use unique transaction id for each request
Check if transaction already exists before processing
Reject duplicate requests

Database ensures correctness of each transaction
Application ensures transaction is not repeated

I built a simple IP checker tool

I’ve been working on a simple IP checker that shows your IP address, location, ISP, and browser info.

The idea was to keep it clean and easy to understand, especially for beginners who want to know what their IP actually reveals.

While building it, I also realized how confusing the basics of the internet can be for most people — things like DNS, servers, and how a page actually loads.

So I wrote a simple breakdown explaining how websites actually work, step by step.

If you’re curious, you can check it here:
https://examineip.com/how-websites-actually-work-simple-explanation-for-beginners/

And here’s the tool itself:
https://tools.examineip.com/

Would love feedback or suggestions on what to improve.

11 Free Government Data APIs You Didn’t Know Existed (And How to Use Them)

The US government publishes enormous amounts of data through public APIs — SEC filings, vehicle recalls, consumer complaints, federal contracts, healthcare provider registries, drug safety reports, and more.

The problem: these APIs are scattered across dozens of agencies, each with its own authentication scheme, rate limits, pagination quirks, and data format. Finding the right endpoint, figuring out the request format, and parsing the response takes hours of documentation reading before you get a single useful result.

I built ready-to-use actors on Apify for 11 of the most valuable government data sources. Each one handles the API quirks, pagination, and data formatting so you get clean, structured JSON output you can export to CSV, connect to Google Sheets, or pipe into your app via API.

All of these use free public APIs. No API keys required.

1. SEC EDGAR — Company Filings Search

Search SEC filings by company name, stock ticker, or CIK number. Filter by form type (10-K, 10-Q, 8-K, Form 4) and date range.

Who uses this: investors doing due diligence, compliance teams tracking competitor filings, financial analysts monitoring insider transactions.

Example: Search “TSLA” to get all Tesla SEC filings with direct links to the actual documents.

Try it on Apify

2. USAspending — Federal Contracts & Grants

Search $7+ trillion in federal spending data. Find government contracts, grants, and loans by keyword, agency, recipient, state, NAICS code, or date range.

Who uses this: government contractors tracking competitors, BD teams finding opportunities, journalists investigating federal spending, researchers studying procurement patterns.

Example: Search for “cybersecurity” contracts from the Department of Defense to see who’s winning federal cyber work.

Try it on Apify

3. CFPB — Consumer Financial Complaints

Search 2+ million consumer complaints against banks, credit card companies, mortgage lenders, and debt collectors. Filter by company, product, issue, state, and date.

Who uses this: compliance teams monitoring complaint trends, fintech companies identifying pain points, investors assessing reputation risk, attorneys researching patterns of consumer harm.

Example: Search “WELLS FARGO” to see all complaints, filtered by product type and time period.

Try it on Apify

4. NHTSA — Vehicle Safety Recalls

Look up vehicle recalls by make, model, and year. Get full recall details: affected component, safety consequence, remedy, and whether it’s a “Park It” (do not drive) advisory.

Who uses this: used car buyers, auto dealers verifying inventory, fleet managers, insurance companies, automotive journalists.

Example: Search “Tesla Model 3 2024” to find all active recalls.

Try it on Apify

5. Federal Register — Rules, Regulations & Executive Orders

Search the daily journal of the US government. Find proposed rules, final rules, notices, and presidential documents by keyword, agency, date, or CFR reference.

Who uses this: regulatory affairs teams tracking new rules, lobbyists monitoring proposed regulations, compliance officers, policy researchers.

Example: Search EPA proposed rules from the last 90 days to see what environmental regulations are coming.

Try it on Apify

6. NPPES NPI Registry — Healthcare Provider Lookup

Search 8+ million healthcare providers in the National Plan and Provider Enumeration System. Find doctors, hospitals, and clinics by name, specialty, location, or NPI number.

Who uses this: health tech companies building provider directories, insurance companies verifying credentials, healthcare recruiters, patients looking up provider details.

Example: Search for cardiologists in California to get NPI numbers, addresses, phone numbers, and taxonomy codes.

Try it on Apify

7. openFDA — Drug Safety Data

Search FDA drug adverse events, recalls, and drug labels. Three search modes cover different aspects of pharmaceutical safety data.

Who uses this: pharma companies monitoring adverse events, regulatory teams tracking recalls, researchers studying drug safety profiles, health journalists.

Example: Search adverse events for “Ozempic” to see reported side effects and outcomes.

Try it on Apify

State Business Entity Registrations

Business entity data is one of the most in-demand public records categories. KYC/compliance teams, sales prospecting, due diligence, and competitive intelligence all need it. I built actors for the four largest states:

8. California Secretary of State

Search CA business entities by name or entity number. Get formation date, status, agent for service of process, and entity type.

Try it on Apify

9. Texas Comptroller

Search TX business entities by name, taxpayer number, or SOS file number. Full details: officers, registered agent, EIN, addresses, franchise tax status.

Try it on Apify

10. New York Division of Corporations

Search NY business entities by name or DOS ID. Full details: service of process, CEO, registered agent, stock info, filing dates, jurisdiction.

Try it on Apify

11. Florida Division of Corporations

Access FL bulk filing data from the public Sunbiz SFTP server. Parse daily or quarterly data dumps with officers, registered agent, addresses, annual reports.

Try it on Apify

Why Apify?

Each of these actors runs in the cloud — no infrastructure to manage, no dependencies to install, no rate limit headaches. You get:

  • Structured output — clean JSON with consistent field names
  • Multiple export formats — JSON, CSV, Excel, or direct API access
  • Integrations — connect to Google Sheets, Slack, Airtable, Zapier, Make, and more
  • Scheduling — run daily/weekly to keep your data fresh
  • Pay per result — no monthly subscriptions, just pay for the data you use

What’s next

Since writing this, I’ve shipped 19 more actors — CPSC product safety recalls, CMS Nursing Home Compare, USDA FoodData Central, FDIC BankFind (27,800+ bank institutions), U.S. Census ACS (demographics by any geography), IRS 990 nonprofit financials, Medicare Part D drug spending, FEC campaign finance, EPA toxic releases, ClinicalTrials.gov, BLS Economic Data (CPI, unemployment, wages), NIH RePORTER research grants, FEMA Disaster Declarations, USGS Earthquake Search, World Bank Indicators, and PubChem Compound Search. 30 actors total, all free to try. If there’s a government data source you need access to, let me know in the comments.

All actors are available at apify.com/pink_comic.

Syncfusion announces Visual Studio subscriber benefits, Essential Studio access

RESEARCH TRIANGLE PARK, N.C. —  Syncfusion Inc. today announced new benefits for Microsoft Visual Studio subscribers, expanding access to Syncfusion’s development tools for building modern applications and workflows. Eligible Visual Studio Enterprise subscribers now have access to Essential Studio Enterprise Edition (ESEE), BoldSign, and Bold BI. Eligible Visual Studio Professional subscribers now have access to … continue reading

The post Syncfusion announces Visual Studio subscriber benefits, Essential Studio access appeared first on SD Times.

Live demonstration highlights modular charging pad delivering efficient energy to different robot platforms, achieving 100% uptime
Fresh from winning the LogiMAT Best Product Award, Sonair showcases the first commercial deployment of its 3D ultrasonic technology at MODEX 2026, moving robot safety from 2D sensing to full 3D spatial awareness.