A year ago I was rebuilding the same <PhoneInput> for the third time across three different projects. Each time I reached for react-phone-number-input (45 KB), wired it to a form, gave up on its accessibility, then wrapped my own thing on top.
Same story for the photo cropper (react-image-crop), the i18n stack (i18next + react-intl), the date picker, the autocomplete, the captcha, the watermark — and then the truly painful one: rendering the same React tree to both the browser and a downloaded PDF, which usually means spinning up a Puppeteer worker on a separate Lambda because Chromium is 200 MB.
So I stopped. Today there are 11 npm packages under the tekivex-* family that try to make every one of those decisions for you, with one consistent design system, one accessibility floor (WCAG 2.1 AAA), and zero runtime dependencies in the core.
npm install tekivex-ui
This article is the "should I actually use this?" version — what's in it, the trade-offs, and what it does that nothing else does.
The product shipment
| Thing you'd normally install | What ships in tekivex-ui |
|---|---|
@mui/material |
tekivex-ui (99 components) |
@react-pdf/renderer + Puppeteer |
tekivex-pdf (one package, no Chromium) |
react-phone-number-input |
TkxPhoneInput (built-in, E.164, 50 countries) |
react-image-crop |
TkxImageEditor |
react-i18next + locale files |
I18nProvider + 35 locales |
react-hot-toast |
TkxToast + ToastProvider
|
react-confetti |
TkxConfetti (RAF, prefers-reduced-motion) |
react-signature-canvas |
TkxSignaturePad |
react-dropzone |
TkxFileUpload (magic-byte MIME check) |
dompurify + custom sanitisers |
tekivex-security-core |
| Cloudflare Turnstile / hCaptcha wrapper | TkxCaptcha |
eslint-plugin-jsx-a11y extras |
tekivex-audit (CLI) |
11 packages, all unscoped, all MIT, all under tekivex-*:
tekivex-ui v3.0.3 main library — 99 components, 1034 tests
tekivex-pdf v0.1.1 React → PDF without a headless browser
tekivex-templates v0.1.1 7 ready-made PDF layouts
tekivex-form v0.1.0 slim form-only re-export (24 inputs)
tekivex-india v0.1.1 Aadhaar, PAN, KYC, Tithi, INR lakh/crore
tekivex-finance v0.1.1 payments, OTP, statements
tekivex-content v0.1.1 signature, markdown, watermark, SEO
tekivex-security-core v0.1.1 framework-agnostic security kernel
tekivex-audit v0.1.1 static-analysis CLI
create-tekivex-app v0.1.1 project scaffolder
tekivex-add v0.1.0 shadcn-style component copier
Now the parts that are actually different.
1. React → PDF without Puppeteer
This is the v3.0 headline. Most "render React to PDF" stories end the same way: spin up a worker on Lambda or Railway, install puppeteer-core, fight a 200 MB Chromium binary, eat 2–4 second cold starts, watch your bill creep up.
tekivex-pdf is a thin opinionated layer over @react-pdf/renderer (1 MB, pure JS) that gives you the same component philosophy as tekivex-ui:
import {
TkxPDFDocument,
TkxPDFPage,
TkxPDFRow,
TkxPDFColumn,
TkxPDFText,
TkxPDFImage,
TkxPDFWatermark,
renderToPDF,
} from 'tekivex-pdf';
const Biodata = ({ data, sessionId }) => (
<TkxPDFDocument>
<TkxPDFPage size="A4" margin={36}>
<TkxPDFWatermark
text={`PREVIEW · ${sessionId}`}
pattern="tiled"
opacity={0.07}
/>
<TkxPDFRow gap={16}>
<TkxPDFColumn flex={2}>
<TkxPDFText size={22} weight="bold">{data.name}</TkxPDFText>
<TkxPDFText size={10} color="muted">{data.subtitle}</TkxPDFText>
</TkxPDFColumn>
<TkxPDFColumn>
<TkxPDFImage src={data.photo} width={120} height={150} />
</TkxPDFColumn>
</TkxPDFRow>
</TkxPDFPage>
</TkxPDFDocument>
);
// Server-side
const buffer = await renderToPDF(<Biodata data={...} sessionId="abc123" />);
// → 1.6–3 KB Node Buffer with `%PDF-` magic bytes, ready to write or stream
| Metric | Puppeteer | tekivex-pdf |
|---|---|---|
| Cold start | 2–4 s | ~50 ms |
| Bundle size | 200 MB | < 2 MB |
| RAM per render | 100–200 MB | ~10 MB |
| Vercel serverless? | ❌ exceeds limit | ✅ fits |
| Same React tree as browser? | Different <html> rendering |
Same component philosophy |
What it gives you for free:
- 7 templates that work out of the box: Biodata, Invoice, Certificate, Resume, Ticket, BoardingPass, Receipt
- Diagonal tiled watermarks
- Indic font registration helpers (Devanagari, Tamil, Telugu, etc.)
-
renderToPNG()for image output (via Sharp, optional peer dep)
And the tradeoff: @react-pdf/renderer supports a subset of CSS (flexbox-style layout, no position: absolute quirks, limited transforms). For structured documents (invoices, certificates, biodata, resumes), this is fine. For pixel-perfect screenshots of arbitrary web pages, keep Puppeteer.
I wrote a smoke test that proves the API actually works:
$ node packages/tekivex-pdf/smoke-test.mjs
Running: renderToPDF produces a buffer starting with %PDF- magic
✓ PDF buffer: 1623 bytes, magic="%PDF-"
Running: Row/Column/View/Text compose without error
✓ Composed Row/Column doc: 1833 bytes
Running: TkxPDFWatermark adds tiled overlay
✓ Watermarked PDF: 2444 bytes
Running: BiodataTemplate renders to a valid PDF
✓ BiodataTemplate: 2962 bytes
Running: InvoiceTemplate renders to a valid PDF
✓ InvoiceTemplate: 3149 bytes
✓ All 5 smoke tests passed.
5/5 pass. Real PDFs that Acrobat opens.
2. WCAG 2.1 AAA across all 99 components — not AA
Most React UI libraries aim for AA. AAA is genuinely rare:
- AA = 4.5:1 contrast for normal text, 3:1 for large
- AAA = 7:1 for normal text, 4.5:1 for large
That difference matters for vision-impaired users, older users on cheap LCD screens, and anyone reading on a phone outdoors. Most "accessible" libraries fail the contrast test on at least one variant (usually the secondary buttons, the muted text, or the disabled state).
What I had to do to get AAA:
- Computed contrast ratios programmatically for every text/background pair across every variant × every theme — flagged any pair < 7:1 with an automated test
-
44×44 minimum touch targets on
size="md"and above (older parents in Tier-2/3 India filling biodata forms — that's the user) -
:focus-visibleoutline at 2px on every interactive element, configurable per theme -
prefers-reduced-motionrespected — slides become fades, confetti renders nothing, autoplay carousels pause - Real screen-reader testing on NVDA + JAWS + VoiceOver iOS + TalkBack Android — published as a 470-cell matrix (88% pass rate documented honestly, the failures are listed)
Not a marketing claim — it's a CI gate. npm run a11y:audit runs axe-core against all 99 components on every PR. Drops below the threshold and the build fails.
3. Built-in security kernel — every prop sanitised
The xz/Bitwarden/Shai-Hulud npm worm wave of 2025 made supply-chain a board-level concern. Every dep you add is a CVE you'll triage one day at 2 AM.
tekivex-ui ships with zero runtime dependencies. Not "few" — zero. npm install tekivex-ui adds exactly one folder to your node_modules.
But more interesting: every prop that touches a DOM-dangerous surface is sanitised at the boundary. The same kernel ships as a standalone package:
npm install tekivex-security-core
import {
sanitizeHref, // blocks javascript:, data:, vbscript: schemes
sanitizeUnicode, // CVE-2021-42574 Trojan Source defense
scrubPII, // redact email/phone/SSN/credit-card from logs
buildTkxCSP, // construct a strict Content-Security-Policy
installTrustedTypes, // browser-side DOM-XSS guard
isFramed,
installFrameBuster, // clickjacking defense
createRateLimiter, // token-bucket, prevent brute-force on form submit
deepFreeze, // prototype-pollution defense
} from 'tekivex-security-core';
// One-line strict CSP for your <head>
const csp = buildTkxCSP({ nonce: 'r4nd0m', strict: true });
// → "default-src 'self'; frame-ancestors 'none'; ..."
// Sanitize untrusted URLs before <a href>
sanitizeHref('javascript:alert(1)'); // → null
sanitizeHref('https://example.com'); // → 'https://example.com'
// Strip Unicode bidi-override attacks (the GitHub/Rust 2021 CVE)
sanitizeUnicode('admin\u202E\u2066 evil'); // → 'admin evil'
// Redact PII before sending to your logger / analytics / LLM
scrubPII('call 415-555-0100 or email a@b.com');
// → 'call [PHONE] or email [EMAIL]'
Every export maps to a specific OWASP / CWE / CVE reference. The full threat model is published at docs/SECURITY-THREAT-MODEL.md — I think this is the only mainstream React UI library that publishes one.
4. Indian-market features — out of the box
Most UI libraries are built by US/EU teams and treat Indian-market needs as edge cases. Things tekivex-ui ships natively:
import {
TkxAadhaarInput, // 12-digit Aadhaar with Verhoeff checksum validation
TkxPanInput, // PAN regex + entity-character validation
TkxVoterIdInput,
TkxDrivingLicenceInput,
TkxAddressInput, // PIN-code → city/state lookup via India Post API
TkxCurrencyInput, // ₹1,23,456 (lakh/crore grouping, not 123,456)
TkxCalendarLunar, // Tithi/Nakshatra (Hindu), Hijri, Hebrew, Buddhist
TkxFontProvider, // lazy-load Devanagari/Tamil/Telugu/Bengali subsets
} from 'tekivex-ui';
The Aadhaar input does real Verhoeff checksum validation in 13 lines of pure TypeScript. The currency input formats 123456 as 1,23,456 for INR (en-IN locale), 123,456 for USD, no decimals for JPY/KRW — driven by Intl.NumberFormat, not a hardcoded table.
If you're building anything for the Indian market, this saves you 2–3 weeks of plumbing.
5. The 4 companion packages worth knowing about
Beyond the main library:
tekivex-form
Slimmer install for apps that only need form widgets:
npm install tekivex-form
24 components re-exported from tekivex-ui. Same React copy via peer dependency, no two-React-copies bug. Tree-shakeable.
tekivex-add
shadcn-style component copier — when you want to fork a single component:
npx tekivex-add button
# Copies TkxButton.tsx into your project's src/components/
# Edit it freely, no upstream coupling
tekivex-audit
Static-analysis CLI that catches what ESLint plugins miss — XSS via dangerouslySetInnerHTML, missing rel="noopener" on target="_blank", hardcoded API keys in source, eval(), target="_blank" without rel="noopener", missing CSP meta tags. 15 checks total, each mapped to OWASP/CWE/WCAG references:
npx tekivex-audit . --fail-on warn --format md --out audit.md
Run it as a CI gate. First time I ran it on my own demo site it found 9 errors and 67 warnings. Embarrassing, but that's the point.
create-tekivex-app
npm create tekivex-app@latest my-app
Two templates: basic (React + Vite + tekivex-ui) or secure (everything plus pre-wired CSP meta tag, Trusted Types installer, frame-buster, and live SecurityCore demos).
Honest comparison
This is the section every "I built a thing" post should have but most don't.
| Library | Best for | Compared to tekivex-ui |
|---|---|---|
| MUI | Teams already on Material Design; massive ecosystem | More mature; AAA contrast inconsistent; data grid is paid; bigger bundle |
| Chakra UI | Theming flexibility, fast prototyping | Excellent DX; AA not AAA; no PDF, no security kernel, no India pack |
| Mantine | Forms, hooks, fast iteration | Great form story; AA not AAA; no PDF |
| shadcn/ui | Copy-paste customisation, Tailwind-native | Brilliant for tinkerers; only ~30 components; you own all the code (also a downside if you don't want to) |
| Ant Design | Enterprise data-heavy apps | Huge component count; bundle size; AA not AAA |
| tekivex-ui | AAA accessibility hard requirement, India market, document/PDF-heavy apps, security-conscious teams | Younger; smaller community; opinionated stack |
If your stack is already on MUI/Chakra/Mantine and you're shipping a North American B2B SaaS, you probably don't need to switch — you'd lose ecosystem to gain features you don't need.
If you're starting fresh, building something India-shaped, AI-shaped, or PDF-shaped, or you have a hard accessibility ceiling — give it a shot.
Quick start
npm install tekivex-ui
import { ThemeProvider, TkxButton, TkxInput, TkxForm, TkxFormField } from 'tekivex-ui';
import 'tekivex-ui/styles';
export default function App() {
return (
<ThemeProvider mode="auto">
<TkxForm onSubmit={(values) => console.log(values)}>
<TkxFormField name="email" label="Email" required>
<TkxInput type="email" />
</TkxFormField>
<TkxButton type="submit" variant="primary">Sign up</TkxButton>
</TkxForm>
</ThemeProvider>
);
}
mode="auto" follows the OS prefers-color-scheme reactively — pin to "dark" or "light" if you prefer.
What's next
-
v3.1 — payments + commerce (
TkxCheckoutflow, Razorpay/Stripe/Square integration helpers) -
v3.2 — vertical packs filled out (
tekivex-india,tekivex-finance,tekivex-contentcurrently re-export; getting their own deep components) - Long-term — bigger AI-native surface (chat, confidence, streaming)
Honest gaps
I'd rather list these than pretend they don't exist:
- The docs site at
ui.tekivex.comis currently serving a fallback homepage because Astro 5 + Starlight 0.36 + Zod 4 hit a route-generation crash. Working on it. The component documentation is real and comprehensive in the GitHub source. -
Test coverage is at 64.84% lines / 51.10% functions / 56.77% branches — enforced via a CI ratchet. Path to 90/90/85 is documented in
docs/test-coverage-roadmap.md. - Community size: I'm one person + occasional contributors. If that's a deal-breaker for you, that's fair.
Try it & break it
If you build anything with this — especially something that breaks — please open an issue:
- 📦 npm: https://www.npmjs.com/package/tekivex-ui
- 🐛 Issues: https://github.com/novaai0401-ui/tekivex-issue-report/issues
- 🎮 Live playground: https://ui.tekivex.com/playground/
Especially interested in:
- People dropping
tekivex-pdfinto existing Puppeteer pipelines and reporting back - Indian-market apps using the KYC pack
- Anyone who notices an AAA contrast slip — that's a P0 bug to me
Thanks for reading. And if this saved you from rebuilding <PhoneInput> for the fourth time, drop a 🦄 below.
Top comments (0)