FluentReads is a high-performance, 100% static e-commerce platform designed for digital books, study packs, and international English exam preparation materials in Peru. Built for low-volume, high-speed catalog navigation, it uses the Peruvian Sol (PEN) currency and features a fully localized Spanish user interface.
Important
This platform is entirely static and serverless. It operates without dynamic database engines, user authentication, or online payment gateways (like Stripe or PayPal). Checkout is processed via WhatsApp, and payments are managed through direct bank transfers.
- Dynamic Static Catalog: Products are defined as JSON content collections and baked directly into HTML at build time, yielding near-instant page loads.
- Client-Side Cart: Managed entirely via
CartManager.ts, synchronizing state inlocalStorageand dispatching custom reactive events. - WhatsApp Checkout: Generates checkout summaries and transfers order details directly to the seller via WhatsApp.
- Decap CMS Support: Administrators can manage and edit the catalog using a web UI at
/admin. Changes are saved back to GitHub, triggering an automatic Vercel build. - Service Worker Integration: Integrates a custom service worker (
public/sw.js) supporting stale-while-revalidate and offline-first cache strategies for resources.
The codebase is organized as follows:
/
├── public/ # Static assets (favicons, manifests, decals)
│ └── admin/ # Decap CMS configuration (index.html, config.yml)
├── src/
│ ├── assets/ # Processed assets (optimized images)
│ ├── components/ # Astro and React UI components
│ ├── config/ # Centralized site configurations
│ ├── data/ # Content collection data files (JSON)
│ ├── content/ # Glob-based collections (Markdown legal files)
│ ├── layouts/ # Page layouts and global SEO metadata
│ ├── pages/ # File-based routing pages
│ ├── scripts/ # Client-side scripts and interaction logic
│ ├── styles/ # Global styling (Tailwind CSS v4)
│ ├── types/ # Strict TypeScript type declarations
│ └── utils/ # Helper utilities (CartManager, filtering)
├── docs/ # Roadmaps, technical audits, and sprint documentation
└── package.json # Scripts, dependencies, and configuration
The application leverages the following modern frontend technologies:
| Dependency | Version | Role / Context |
|---|---|---|
| Astro | 7.0.6 | Core static site generator framework |
| React | 19.2.7 | Interactive UI islands (filters, cart actions) |
| Tailwind CSS | 4.3.2 | Modern utility-first styling with @tailwindcss/vite |
| Bun | 1.3.14 | JavaScript runtime, package manager, and test runner |
| TypeScript | 6.0.3 | Strict type validation |
Note
This repository requires Bun 1.3.14 or later. Standard npm, yarn, or pnpm commands should not be used.
Make sure you have installed:
- Node.js >= 22.0.0
- Bun >= 1.3.14
Clone the repository and install the development dependencies:
bun installStart the local server at http://localhost:4321:
bun run devValidate files and build the production bundle to the dist/ directory:
bun run buildTo bypass linting and TypeScript checks (for emergencies only), run:
bun run build:forceLaunch a local server to preview the built static output:
bun run previewThe following helper scripts are configured in package.json:
| Script | Command | Purpose |
|---|---|---|
dev |
astro dev |
Run the local dev server |
build |
bun run check && astro build |
Verify and bundle static files |
build:force |
astro build |
Build without verification checks |
preview |
astro preview |
Serve the production build locally |
check |
astro check |
Run Astro validation and TypeScript verification |
typecheck |
bun run check |
Run type checking across the project |
lint |
eslint . |
Verify codebase styles with ESLint |
lint:fix |
eslint . --fix |
Automatically fix linting violations |
format |
prettier --write . |
Format files according to Prettier settings |
format:check |
prettier --check . |
Check files formatting without writing |
This project leverages Astro Content Collections validated with strict Zod schemas inside src/content.config.ts. The catalog comprises 12 distinct collections:
- books: Single-file JSON representing individual digital books.
- packs: Single-file JSON combining multiple books into discounted study bundles.
- exams: Single-file JSON detailing international English exam types.
- editorial: Single-file JSON containing publisher descriptions.
- testimonies: Single-file JSON representing customer reviews.
- offers: Single-file JSON listing active banner promotions.
- categories: Single-file JSON defining product categories and navigation icons.
- generalFaqs: Single-file JSON for general FAQs.
- catalogFaqs: Single-file JSON for catalog FAQs.
- paymentFaqs: Single-file JSON for billing FAQs.
- offerHeroBanner: Single-file JSON for countdown banner configurations.
- legal: Markdown-based collection representing legal guidelines.
Decap CMS is embedded at /admin (configured via public/admin/index.html and public/admin/config.yml).
Because Astro single-file collections are structured as JSON arrays and Decap CMS defaults to object files, we register a custom json-array serialization format inside the CMS:
window.CMS.registerFormat('json-array', 'json', {
fromFile: (content) => ({ items: JSON.parse(content) }),
toFile: (data) => JSON.stringify(data.items, null, 2),
});Modifying content in the /admin portal commits files directly to GitHub, triggering a rebuild on Vercel automatically.
Configure the following variables in a local .env file for development:
| Name | Scope | Description |
|---|---|---|
PUBLIC_PAGECLIP_KEY |
Public | Key for serverless form processing via Pageclip |
PUBLIC_SITE_URL |
Public | Canonical URL of the site, used for absolute routing |
We enforce conventional commit messages. All pull requests and commits must follow standard prefixes:
type(scope): description in imperative
- Branching Policy: Merges to the
developbranch generate Vercel preview environments. Merges tomainupdate the production site and triggerrelease-pleaseto auto-bump version numbers and generate changelogs. - Git Hooks: Pre-commit hooks run ESLint and Prettier check formatting before code is allowed to commit.