{"id":29245798,"url":"https://github.com/arnobt78/paragraph-generator--react-fundamental-project-8","last_synced_at":"2026-05-04T17:32:32.220Z","repository":{"id":276595654,"uuid":"929730774","full_name":"arnobt78/Paragraph-Generator--React-Fundamental-Project-8","owner":"arnobt78","description":"A modern, interactive React application that generates a customizable number of random paragraphs (\"Lorem Ipsum\") for use in design, development, and content prototyping. This project demonstrates fundamental React concepts, state management, and functional component design with practical, real-world utility","archived":false,"fork":false,"pushed_at":"2026-03-11T14:05:18.000Z","size":121,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-11T19:55:01.477Z","etag":null,"topics":["controlled-input","educational-project","functional-components","javascript","list-rendering","lorem-ipsum","lorem-ipsum-generator","nanoid","paragraph-generator","random-text","random-text-generator","react","react-basics","react-components","react-dom","react-fundamentals","react-hooks","react-learning","react-tutorial","vite"],"latest_commit_sha":null,"homepage":"https://create-paragraph.vercel.app/","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arnobt78.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-02-09T08:56:43.000Z","updated_at":"2026-03-11T14:05:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"032a65b7-c364-4210-bf76-d4014a7c5815","html_url":"https://github.com/arnobt78/Paragraph-Generator--React-Fundamental-Project-8","commit_stats":null,"previous_names":["arnobt78/lorem-ipsum-generator--react-fundamental-project-8","arnobt78/paragraph-generator--react-fundamental-project-8"],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/arnobt78/Paragraph-Generator--React-Fundamental-Project-8","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FParagraph-Generator--React-Fundamental-Project-8","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FParagraph-Generator--React-Fundamental-Project-8/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FParagraph-Generator--React-Fundamental-Project-8/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FParagraph-Generator--React-Fundamental-Project-8/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arnobt78","download_url":"https://codeload.github.com/arnobt78/Paragraph-Generator--React-Fundamental-Project-8/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arnobt78%2FParagraph-Generator--React-Fundamental-Project-8/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32617741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["controlled-input","educational-project","functional-components","javascript","list-rendering","lorem-ipsum","lorem-ipsum-generator","nanoid","paragraph-generator","random-text","random-text-generator","react","react-basics","react-components","react-dom","react-fundamentals","react-hooks","react-learning","react-tutorial","vite"],"created_at":"2025-07-03T22:38:16.324Z","updated_at":"2026-05-04T17:32:32.196Z","avatar_url":"https://github.com/arnobt78.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Paragraph Generator – React, Vite, JavaScript, Custom CSS Fundamental Project 8\n\nA modern, interactive React application that generates a customizable number of random paragraphs (\"Lorem Ipsum\") for use in design, development, and content prototyping. This project demonstrates fundamental React concepts, state management, and functional component design with practical, real-world utility.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![React](https://img.shields.io/badge/React-18.2-blue)](https://react.dev/)\n[![Vite](https://img.shields.io/badge/Vite-4.1-646CFF)](https://vitejs.dev/)\n[![JavaScript](https://img.shields.io/badge/JavaScript-ES6%2B-yellow)](https://developer.mozilla.org/en-US/docs/Web/JavaScript)\n\n- **Live Demo:** [https://create-paragraph.vercel.app/](https://create-paragraph.vercel.app/)\n\n![Screenshot 2026-03-11 at 15 03 23](https://github.com/user-attachments/assets/b508a770-a164-44fc-a867-f244712f10bc)\n\n## Table of Contents\n\n- [Project Summary](#project-summary)\n- [Features](#features)\n- [Technology Stack](#technology-stack)\n- [Project Structure](#project-structure)\n- [Component Overview](#component-overview)\n- [How It Works (Walkthrough)](#how-it-works-walkthrough)\n- [Setup \u0026 Usage](#setup--usage)\n- [Environment Variables (.env)](#environment-variables-env)\n- [Key Concepts \u0026 Teaching Content](#key-concepts--teaching-content)\n- [Reusing Components in Other Projects](#reusing-components-in-other-projects)\n- [API, Backend \u0026 Routes](#api-backend--routes)\n- [Customization](#customization)\n- [Keywords](#keywords)\n- [Conclusion](#conclusion)\n- [License](#license)\n\n---\n\n## Project Summary\n\nThe **Paragraph Generator** is a learning-focused React project that lets users generate a desired number of random placeholder paragraphs (1–8) with a single form submit. It showcases **form handling**, **state management** (`useState`), and **dynamic list rendering** in React, making it a solid resource for beginners and anyone looking for a clear example of React fundamentals.\n\nThe UI is minimal and accessible: users enter a number between 1 and 8, click **Generate**, and the app instantly displays that many paragraphs below the form. There is no backend or API—all data lives in the frontend, so the project is ideal for studying React in isolation.\n\n---\n\n## Features\n\n- **Custom paragraph count:** Choose how many paragraphs to show (1–8).\n- **Form handling:** Number input with `min`/`max` validation and controlled component pattern.\n- **Live preview:** Generated paragraphs appear immediately on submit.\n- **Stable list keys:** Uses `nanoid` for unique keys in `.map()` to satisfy React’s reconciliation and avoid key warnings.\n- **Accessible UI:** Semantic HTML (`\u003csection\u003e`, `\u003cform\u003e`, `\u003clabel\u003e`, `\u003carticle\u003e`) and associated form controls.\n- **Fast tooling:** Vite for quick dev server and optimized production builds.\n- **Lint:** ESLint with React and React Hooks rules; run with `npm run lint`.\n\n---\n\n## Technology Stack\n\n| Technology            | Purpose                                           |\n| --------------------- | ------------------------------------------------- |\n| **React 18**          | UI library; functional components and hooks       |\n| **Vite 4**            | Dev server, HMR, and production bundling          |\n| **JavaScript (ES6+)** | No TypeScript; modern syntax and modules          |\n| **nanoid**            | Small library for unique IDs (list keys)          |\n| **CSS**               | Custom global and component styles; CSS variables |\n| **HTML5**             | Single `index.html` as app shell                  |\n\n---\n\n## Project Structure\n\n```bash\n08-lorem-ipsum/\n├── public/\n│   └── vite.svg              # Favicon / static asset\n├── src/\n│   ├── App.jsx               # Main component: form + paragraph list\n│   ├── data.js               # Array of 8 paragraph strings (data source)\n│   ├── index.css             # Global + project-specific CSS\n│   └── main.jsx              # React entry: mounts app into #root\n├── index.html                # HTML template and SEO meta tags\n├── vite.config.js            # Vite config (React plugin)\n├── eslint.config.js         # ESLint flat config (React + Hooks)\n├── package.json\n└── README.md\n```\n\n- **Entry:** `index.html` loads `src/main.jsx`, which renders `\u003cApp /\u003e` into `#root`.\n- **Data:** `src/data.js` exports one array; no backend or API.\n- **Styling:** `src/index.css` is imported in `main.jsx` and applies globally.\n\n---\n\n## Component Overview\n\n### `main.jsx` (Entry)\n\n- Imports React, ReactDOM, `App`, and `index.css`.\n- Uses `createRoot` and `render` to mount `\u003cApp /\u003e` inside `\u003cdiv id=\"root\"\u003e`.\n- Wraps the app in `\u003cReact.StrictMode\u003e` for development checks.\n\n```jsx\nimport React from \"react\";\nimport ReactDOM from \"react-dom/client\";\nimport App from \"./App\";\nimport \"./index.css\";\n\nReactDOM.createRoot(document.getElementById(\"root\")).render(\n  \u003cReact.StrictMode\u003e\n    \u003cApp /\u003e\n  \u003c/React.StrictMode\u003e,\n);\n```\n\n---\n\n### `App.jsx` (Main UI)\n\n- **State:** `count` (number of paragraphs to show, default `1`), `text` (array of paragraph strings to render).\n- **Form:** Number input (min 1, max 8), label, and submit button. On submit, `handleSubmit` reads the value, parses it, slices `data` to that length, and updates `text`.\n- **Output:** Renders an `\u003carticle\u003e` that maps over `text` and shows each item in a `\u003cp\u003e` with a `nanoid()` key.\n\nRelevant snippets:\n\n```jsx\nconst [count, setCount] = useState(1);\nconst [text, setText] = useState([]);\n\nconst handleSubmit = (e) =\u003e {\n  e.preventDefault();\n  let amount = parseInt(count);\n  setText(data.slice(0, amount));\n};\n```\n\n```jsx\n\u003carticle className=\"lorem-text\"\u003e\n  {text.map((item) =\u003e {\n    return \u003cp key={nanoid()}\u003e{item}\u003c/p\u003e;\n  })}\n\u003c/article\u003e\n```\n\n---\n\n### `data.js` (Data Module)\n\n- Exports a single array of 8 strings. Each string is one paragraph (various placeholder themes: candy, zombie, cat, cheese, etc.).\n- Used only by `App.jsx` via `data.slice(0, amount)` to select how many paragraphs to display.\n\n---\n\n### `index.css` (Styles)\n\n- **Global:** Reset (margin/padding/box-sizing), `:root` variables (colors, spacing, shadows, typography), base styles for `body`, headings, buttons, forms, alerts.\n- **Project-specific:** `.section-center`, `.lorem-form`, `.lorem-text` for layout and appearance of the generator UI.\n- Reusable utility classes (e.g. `.btn`, `.alert`, `.form`) can be reused in other pages or components.\n\n---\n\n## How It Works (Walkthrough)\n\n1. **Page load:** `main.jsx` mounts `App`. Initial state: `count = 1`, `text = []`, so no paragraphs are shown yet.\n2. **User input:** User changes the number input (1–8). Because the input is controlled (`value={count}`, `onChange` updating `count`), React re-renders with the new value.\n3. **Submit:** User clicks **Generate**. `handleSubmit` runs: `e.preventDefault()` stops full page submit; `amount = parseInt(count)`; `setText(data.slice(0, amount))` sets state to the first `amount` items from `data`.\n4. **Re-render:** React re-renders `App`. The `.map()` over `text` produces one `\u003cp\u003e` per paragraph, each with a unique `key={nanoid()}`.\n5. **Result:** The requested number of paragraphs appears below the form. Changing the number and clicking **Generate** again updates the list.\n\nNo server, no API, no routing—everything happens in the browser with React state and the static `data` array.\n\n---\n\n## Setup \u0026 Usage\n\n### Prerequisites\n\n- **Node.js** (v14 or higher recommended)\n- **npm** (or yarn/pnpm)\n\n### Installation\n\n1. **Clone the repository**\n\n   ```sh\n   git clone https://github.com/arnobt78/Paragraph-Generator--React-Fundamental-Project-8.git\n   cd Paragraph-Generator--React-Fundamental-Project-8\n   ```\n\n2. **Install dependencies**\n\n   ```sh\n   npm install\n   ```\n\n### Run locally\n\n```sh\nnpm run dev\n```\n\nThen open the URL shown in the terminal (typically `http://localhost:5173`). Use the form to pick a number (1–8) and click **Generate** to see the paragraphs.\n\n### Build for production\n\n```sh\nnpm run build\n```\n\nOutput goes to the `dist/` folder. To preview the production build locally:\n\n```sh\nnpm run preview\n```\n\n### Lint\n\n```sh\nnpm run lint\n```\n\nRuns ESLint on `src` (and any other configured paths). Fix any reported errors or warnings to keep the codebase consistent.\n\n---\n\n## Environment Variables (.env)\n\nThis project **does not use any environment variables**. All behavior is driven by the code and the static `data.js` file. There is no API key, no backend URL, and no feature flags.\n\n- The repo’s `.gitignore` already includes `.env` so that if you add a `.env` file later (e.g. for an optional API or analytics), it won’t be committed.\n- **If you extend the project** (e.g. add an API or analytics):\n  - Create a `.env` file in the project root.\n  - In Vite, use `import.meta.env.VITE_*` for variables you want in the client (e.g. `VITE_API_URL`).\n  - Add `.env.example` with placeholder names (no secrets) and document each variable in the README.\n\nFor this educational version, **no `.env` file or environment variables are required** to run or build the app.\n\n---\n\n## Key Concepts \u0026 Teaching Content\n\n### 1. `useState` Hook\n\nState is stored and updated with `useState`. When the setter is called, React re-renders the component and any children that depend on that state.\n\n```js\nconst [count, setCount] = useState(1); // number of paragraphs\nconst [text, setText] = useState([]); // array of strings to show\n```\n\n### 2. Controlled Input\n\nThe number input is “controlled”: its value is `count` and changes go through `setCount`, so React always owns the value.\n\n```jsx\n\u003cinput\n  type=\"number\"\n  value={count}\n  onChange={(e) =\u003e setCount(e.target.value)}\n  min=\"1\"\n  max=\"8\"\n/\u003e\n```\n\n### 3. Form Submit Handler\n\nPrevent default form submission and derive the amount from state (or from the event target if you prefer), then update state.\n\n```js\nconst handleSubmit = (e) =\u003e {\n  e.preventDefault();\n  let amount = parseInt(count);\n  setText(data.slice(0, amount));\n};\n```\n\n### 4. Slicing an Array\n\n`Array.prototype.slice(0, n)` returns the first `n` elements without mutating the original array—ideal for “first N paragraphs.”\n\n```js\nsetText(data.slice(0, amount));\n```\n\n### 5. List Rendering and Keys\n\nWhen rendering lists, each item must have a stable, unique `key` so React can reconcile efficiently. Here, `nanoid()` generates a new ID per item.\n\n```jsx\n{\n  text.map((item) =\u003e \u003cp key={nanoid()}\u003e{item}\u003c/p\u003e);\n}\n```\n\n### 6. Single Source of Truth\n\nParagraph content lives only in `data.js`. The UI only decides _how many_ to show; it doesn’t duplicate or modify the original data.\n\n---\n\n## Reusing Components in Other Projects\n\n### Reusing the “paragraph generator” behavior\n\n1. **Copy `App.jsx`** (and optionally rename it, e.g. `ParagraphGenerator.jsx`). Keep the same logic: `useState` for count and text, form with number input, `handleSubmit` that does `data.slice(0, amount)`, and the `.map()` over `text`.\n2. **Copy or adapt `data.js`**—either the same array or your own list of strings.\n3. **Install `nanoid`** in the other project: `npm install nanoid`.\n4. **Styling:** Copy the relevant parts of `index.css` (e.g. `.section-center`, `.lorem-form`, `.lorem-text`, and any variables/buttons you use), or replace with your own CSS/styled-components.\n\n### Reusing only the form pattern\n\n- Use the same controlled input + `handleSubmit` pattern with your own state and logic (e.g. different limits, different data source, or fetching from an API instead of `data.js`).\n\n### Reusing only the data\n\n- Import `data` from `data.js` (or a copy) in any component that needs placeholder text—e.g. for a preview, a modal, or a different layout.\n\n---\n\n## API, Backend \u0026 Routes\n\n- **API:** None. The app does not call any external or internal API. All text comes from the in-memory `data` array.\n- **Backend:** None. The project is frontend-only. Deployment is typically static (e.g. Vercel, Netlify) serving the built `dist/` output.\n- **Routes:** Single page. There is no router (no React Router or similar). One URL, one screen: the paragraph generator form and result.\n\n---\n\n## Customization\n\n- **Paragraph content:** Edit `src/data.js` to add, remove, or change the strings. Adjust the `max` on the input in `App.jsx` if you add more than 8.\n- **Paragraph limits:** In `App.jsx`, change the input’s `min` and `max` (and optionally the initial `useState(1)` default) to allow a different range (e.g. 1–20).\n- **Styling:** Change `src/index.css`—especially `:root` variables and the `.section-center`, `.lorem-form`, `.lorem-text` rules—to match your theme or layout.\n- **Copy and headings:** Change the `\u003ch4\u003e` and button/label text in `App.jsx` to fit your branding or language.\n\n---\n\n## Keywords\n\nReact, Paragraph Generator, Lorem Ipsum, Vite, useState, nanoid, JavaScript, Functional Components, Form Handling, Array.slice, Random Text, Placeholder Text, Frontend, CSS, Web App, Beginner Project, Controlled Input, List Rendering, React Hooks, ESLint\n\n---\n\n## Conclusion\n\nThis **Paragraph Generator** project is a small, self-contained example of React fundamentals: state, controlled inputs, form handling, and list rendering with stable keys. It has no backend or environment variables, so you can run and modify it immediately. Use it to learn React, to share with others, or as a starting point for a more advanced app (e.g. with an API, routing, or more complex UI).\n\n---\n\n## License\n\nThis project is licensed under the [MIT License](https://opensource.org/licenses/MIT). Feel free to use, modify, and distribute the code as per the terms of the license.\n\n---\n\n## Happy Coding! 🎉\n\nThis is an **open-source project** — feel free to use, enhance, and extend this project further!\n\nIf you have any questions or want to share your work, reach out via GitHub or my portfolio at [https://www.arnobmahmud.com](https://www.arnobmahmud.com).\n\n**Enjoy building and learning!** 🚀\n\nThank you! 😊\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farnobt78%2Fparagraph-generator--react-fundamental-project-8","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farnobt78%2Fparagraph-generator--react-fundamental-project-8","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farnobt78%2Fparagraph-generator--react-fundamental-project-8/lists"}