Notes on regular UI Bhagavad Gita Nextjs web app. built on top of Very Simple Gita app

Last updated on 20 Jul. 2024
Minor update on 1 Oct. 2024

Quick Info

App (latest version) deployed at: https://gita-rsi.vercel.app/

Details

Now I am starting the next step of using Tailwind and TypeScript in my very simple Gita app and make it a regular web app. (regular web app UI + tighter and more robust code by using TypeScript). But it no longer will be a very simple Gita app. as the coding complexity will surely increase.

First step is to add Tailwind to the existing project. Note that TypeScript is already setup in the project. It was just that I did not use it - I used .js/.jsx files instead of .ts/.tsx files. But Tailwind is not part of the very simple Gita app project.

Based on: Setting up Tailwind CSS in a Next.js project section in https://tailwindcss.com/docs/guides/nextjs :

To install Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

The above commands executed without any issues. Tailwind and postcss config files were created.
---

Configure template paths:
I used:

  content: [
    "./app/**/*.{js,ts,jsx,tsx,mdx}",
    "./pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./components/**/*.{js,ts,jsx,tsx,mdx}",
  ],
---

Add the Tailwind directives to your CSS:
In /app/ui/global.css I added at the top:
@tailwind base;
@tailwind components;
@tailwind utilities;
---

I then had to do an npm install as I had copied the source files of the very simple Gita app to a new directory.

---
Start your build process:
npm run dev

The app. is running. There was a warning on console about no tailwind utility classes detected in source files but that's expected as the source code does not use Tailwind utility classes as of now.
The default margins and paddings seem to have been set to 0 by Tailwind. Also default underline and colors for links seem to have been removed by Tailwind. As the app relies on default margins and paddings, the UI looks somewhat awkward but the app. works and the CSS rules I have specifed in global.css seem to be in play.

Using Chrome DevTools, I tried to get some understanding of how the CSS rules I have in /app/ui/global.css (e.g.  for body element; Navbar, disabled and SelectChapterVerse classes) come into play in the app with Tailwind. A layout.css file seems to have been generated in .next/static/css/app folder by the build process, and this layout.css is the main CSS file that the app uses at runtime. Very interestingly, the CSS rules that I have specified in /app/ui/global.css appear at the bottom of this layout.css file. So that's how the /app/ui/global.css rules come into play in the app even when using Tailwind.

I tried to spot any layout.css related declaration in a few config files like tailwind.config.js and postcss.config.js but could not spot it. As of now, I don't want to invest further time on it.

Details of what defaults Tailwind removes seem to be given here: Preflight, https://tailwindcss.com/docs/preflight . It also states that to disable Preflight, "all you need to do is set preflight to false in the corePlugins section of your tailwind.config.js file".
'corePlugins: { preflight: false, }'
----

Tried the above, and now the app UI is like it is in the non-Tailwind version. Hmm. That's interesting. I think I can continue to use this temporarily as I am migrating the app to Tailwind. But at some stage, I should drop using it as preflight is supposed to provide some advantages. From the above webpage:
Built on top of modern-normalize, Preflight is a set of base styles for Tailwind projects that are designed to smooth over cross-browser inconsistencies and make it easier for you to work within the constraints of your design system.

Tailwind automatically injects these styles when you include @tailwind base in your CSS:
---

Created public repo: https://github.com/ravisiyer/gita.git and pushed the project's code to it. This is the starter version using Tailwind but with Preflight set to false and so having same UI as earlier non-Tailwind version (verysimplegita).

================================================
Next step is add Tailwind utility classes to the source code.

I tried simple text and background colour Tailwind classes for an h2 header element of one page:
      <h2 class="text-orange-400 bg-black">
        Bhagavad Gita Chapter Summaries भगवत गीता अध्यायों का सारांश
      </h2>
----

The app. shows the Tailwind class colours specified above. Rest of the UI is as before (with Preflight false setting). Hmm. It is interesting to see how one can disable Tailwind Preflight and use a combination of regular CSS classes and some Tailwind classes. 
-----
Initial step I took was to migrate or convert the chapter summaries page (home page) to Tailwind. I removed the Preflight false setting, and so now the Tailwind CSS reset and some other Tailwind default settings like margins reset to 0 for h1, h2 etc. come into play. 

It took quite some effort to find out the default margins Chrome uses (say for h1, h2 elements) which is what very simple Gita (VSG) app. uses as it does not specify CSS classes for elements like h1, h2 (IFIRC), and then specify equivalent Tailwind (Tw) classes in this project to get similar UI to VSG. I used Chrome DevTools and web pages giving info. on Chrome defaults.
...
...
Chrome Default Font: Times New Roman
chrome://settings/fonts on my PC gives: 
Standard font
Times New Roman
...

Serif font
Times New Roman
...

Sans-serif font
Arial
...

Fixed-width font
Consolas
...

Mathematical font
Cambria Math
-----------

https://tailwindcss.com/docs/font-family gives default font-family settings in Tw and methods to change default font.
-------
--------

Tw default font is not Chrome's default font of 'Times New Roman'. So I had to set my project's default font to Times New Roman. I tried the below statements in global.css:

@layer base {
  html {
    font-family: "Times New Roman", system-ui, sans-serif;
  }
}
----

It got picked up and Times New Roman became the English text font for the app. Nirmala UI continued to be font for Sanskrit. I think it seems to be a sort-of default for Sanskrit text on Windows and so Chrome uses it though I don't think the app code specifies that font anywhere.
-----

https://tailwindcss.com/docs/font-family provides a way to use "a one-off font-family value".

I used the approach mentioned in above page for setting font of chapter and verse input elements, as follows:
<input
        className="mr-1 border border-neutral-500 leading-none w-12 text-sm py-px px-0.5 font-['Arial']"
        type="number"
...
---

It worked as expected.
--------------

In Chrome, for chaptersummaries in vercel VSG app (from DevTools):
For h2 element:
font-size: 24px
font-weight 700
margin-block-end 19.92px
margin-block-start 19.92px
margin-bottom 19.92px
margin-inline-end 0px
margin-inline-start 0px
margin-left 0px
margin-right 0px
margin-top 19.92px
--

For h3 element:
font-size 18.72px
font-weight 700
margin-block-end 18.72px
margin-block-start 18.72px
margin-bottom 18.72px
margin-inline-end 0px
margin-inline-start 0px
margin-left 0px
margin-right 0px
margin-top 18.72px
marker-end none
--

For h4 element:
font-size 16px
font-weight 700
margin-block-end 21.28px
margin-block-start 21.28px
margin-bottom 21.28px
margin-inline-end 0px
margin-inline-start 0px
margin-left 0px
margin-right 0px
margin-top 21.28px
---

For p element:
font-size 16px
font-weight 400
line-height normal
margin-block-end 16px
margin-block-start 16px
margin-bottom 16px
margin-inline-end 0px
margin-inline-start 0px
margin-left 0px
margin-right 0px
margin-top 16px
=======================

...

Google search shows a color picker on searching for: #94a3b8 in rgb
Setting rgb to 118,118,118 in it gives hex code of corresponding color as: #767676
Note that I got this rgb 118,118,118 as default colour Chrome gives to input box border (VSG app) using Chrome DevTools.
Tailwind has a Neutral 500 which seems close with value of: #737373

Above shows that to get a 1 px. border we need to simply use border Tw class (without any suffix).

----------

Chrome seems to have a default line height of 1.2 * font size. Ref: https://support.google.com/webdesigner/answer/3241178

https://blog.hubspot.com/website/css-line-height has some info. Repeats 1.2 figure for desktop browsers but adds some exception.

layout.css in project has the following lines:
html,
:host {
  line-height: 1.5; /* 1 */
----

That explains why the line-height by default in the paragraphs is 24px. DevTools shows it is inherited from body element but does not give the value. I could not figure out a way in DevTools to go to the HTML line-height statement that it inherits from. Going directly to HTML element in DevTools shows, 'line-height: 1.5;' and clicking on the associated css rule link (of layout.css file) takes one to the above lines in layout.css.

The browser default (used in VSG app.), in contrast, seems to use line-height: normal, which seems to be 1.2 * font-size which comes to 19.2px assuming default font-size of 16px.


leading-none line-height: 1;
leading-tight line-height: 1.25;
leading-snug line-height: 1.375;
leading-normal line-height: 1.5;
leading-relaxed line-height: 1.625;
----

Tailwind does not seem to have a way to set line-height to normal. Its leading-normal is line-height: 1.5. Perhaps Tailwind wants to be independent of browser defaults and so specify everything itself. That may lead to some consistency in UI across browsers, I guess. But I am not sure.

Anyway, I just need a solution to make the chapter summaries page in the project similar to VSG app (as seen on Chrome on desktop). So it seems leading-tight is what I should use. But even with that the line height is more in this app than VSG app. I could not figure out from DevTools what line-height value comes into play for its paragraph element. Style does not list it and Computed values shows line-height in grey with normal (don't know if grey indicates it is not used).

leading-none makes it too compressed. Smaller gap than VSG.
leading-4 output seems to be similar to leading-none.
I think I need line-height: 1.1; but Tailwind does not seem to have a standard way of specifying it. I don't want to write custom stuff ... or maybe I should.
----
Code that I am using:
  theme: {
    extend: {
      lineHeight: {
        1.1: "1.1",
      },
    },
  },
----
And in jsx file:
          <p className="my-4 mr-4 leading-1.1">{chapter.chapterSummary}</p>
---

That works with both this app and VSG app now having very similar though not same, English paragraph display.

For Hindi paragraphs, the following code does the job of having similar paragraph display:
          <p className="my-4 mr-4 leading-tight">
            {chapter.chapterSummaryHindi}
          </p>
----
I don't know why leading-tight works well for Hindi but not for English (to achieve similar display). .. Later I saw that leading-snug makes Hindi paragraphs in this project's app more like VSG display and so have settled for that instead of leading-tight.

https://tailwindcss.com/docs/line-height provides a way to use "a one-off line-height value".

I think that means that I could have used leading-[1.1] instead of having a custom theme. Tried it and it works as expected.
-----

<form className="inline SelectChapterVerse" onSubmit={handleSubmit}>
Above statement works! So we can combine Tailwind class with CSS class in an HTML element definition. May not be a good idea and not good convention but I am glad to know that it can be combined at element definition level.
I am finding it helpful as I migrate the CSS from VSG CSS classes to Tw classes. I can do it one step/CSS rule at a time, testing at each step, using this combination.
---

A close Tw color seems to be Violet-50 #f5f3ff
----

Tw does not seem to have exact equivalent for: word-break: break-word;  [One comment (at least) seems to be related to this issue: https://github.com/tailwindlabs/tailwindcss/issues/835]
What is suggested by Tw is: break-words which maps to CSS: overflow-wrap: break-word; - https://tailwindcss.com/docs/word-break

Similarly Tw does not seem to have equivalent for:   word-wrap: break-word;

Perhaps break-words is enough. I have used that. But Chapter summaries does not seem to have a test case to check if it works.
---

.disabled {
  pointer-events: none;
  color: rgb(161, 158, 158);
}

To convert above class to Tw:
pointer-events-none of Tw maps to: pointer-events: none;

rgb(161, 158, 158) is: #a19e9e
An awesome app.: Hex to Tailwind Converter, https://tailwind-color-finder.vercel.app/ suggests trueGray-400 #a3a3a3 as suitable and shows both colors. They certainly seem similar. But ... trueGray-400 is not listed as a choice in Intellisense for text-true... Oh! it is neutral-400. Perhaps the names changed across Tw versions.
----------

Now the chapter summaries page of this app. is very close to VSG app. The commit point, "chapter summaries UI close to VSG; No VSG CSS classes used",  https://github.com/ravisiyer/gita/tree/b94cf2a3073629d713f0538b261d3b6eb108dffe has the files at this time point.
----------

Felt that text-blue-700 was better than text-blue-600 for link (not visited). Changed link color to text-blue-700 across app.

Link text font ...
For chapter summaries page, the 'commentaries and more translations' link is plain text within an anchor tag. DevTools shows that in this project, it is Times New Roman 16px. DevTools shows that the font-family is inherited from the html element. font-size is not shown as inherited and is in grey colour which perhaps indicates that it is the browser default coming into play but I am not sure.

In Verse, same para can have English or Devanagari. So leading-[1.1] is making Devanagari text vertical gap as too cramped. I used leading-snug instead. That results in Devanagari text showing quite similar to VSG UI but English text in this app. having more vertical gap between lines than VSG UI. But the vertical gap is also not too much. So I think this is an acceptable solution, as of now.

Later, I can consider writing code that comes into play at runtime which changes the class used based on whether the (dynamic) para is having English content or Devanagari content (Hindi or Sanskrit).
...
The following code displays with same vertical margin as VSG but I have not specified any Tw classes. So shouldn't the vertical margins be 0? Need to check this out to get a better understanding of what's happening:
          <div key={commentary.authorId}>
            <b>
              <i>
                In {capitalizeFirstLetter(commentary.language)} by{" "}
                {commentary.authorName}
              </i>
            </b>
---
There is similar code for translation with same effect.

The div has no margin both in this project app and in VSG app. But the previous and later elements have margins and so their margins come into play in both the apps.
---

As an experiment, I wanted to see if I could make the Go button of this project's app look exactly the same, at least as far as I could make out, as VSG app UI. ...
The Go button is slightly larger in this project app when I use text-sm which specifies 'font-size: 0.875rem /* 14px */;' 'line-height: 1.25rem /* 20px */'. text-xs makes the button text too small. I think I need text-sm but with line-height overridden as 1rem (leading-4 Tw class). So I used 'text-sm leading-4'.
That worked as expected. DevTools shows that the line-height specified by leading-4 (1rem) overrides line-height of 1.25rem specified by text-sm but retains the font-size of 0.875rem specified by text-sm. So the font-size used is 14px and font-family is Times New Roman.

VSG app. uses font-family of Arial and font-size of 13.3333px.
I used the following in this project's Go button: text-[13.33px] and font-['Arial'] to make the button very close to VSG UI. Good to see these escape hatches Tw provides to specify values directly.
I then used arbitrary width of w-[25px]. Now the Go buttons seem to be exactly the same in appearance. The final code:
      <input
        type="submit"
        value="Go"
        className="border-2 border-black text-[13.33px] leading-4 w-[25px] text-violet-50 bg-black rounded-md cursor-pointer hover:text-black hover:bg-violet-50 active:scale-90 font-['Arial'] "
      />
----

Can we use h1, h2 elements default styles other than margin, in Tw? No, as the heading elements are "unstyled by default, and have the same font-size and font-weight as normal text". Ref: Headings are unstyled, https://tailwindcss.com/docs/preflight#headings-are-unstyled.
----

Seems like Chrome delete history feature does not have a filter option, and so one has to search for the website in history and then delete entries of it. Click first entry, scroll to end and Shift-click last entry to select all. Ref: Clear browsing history from specific site on chrome, https://superuser.com/questions/1787991/clear-browsing-history-from-specific-site-on-chrome

Tried the above. The problem is that there are too many hits and Chrome does not show them all at one go. So after one deletes all of the entries shown, then older entries are shown!

How to "unvisit" links in Chrome?, https://superuser.com/questions/634824/how-to-unvisit-links-in-chrome - mentions Chrome extension: http://chrispederick.com/work/web-developer/ that can do the job. May explore it in future as it may be having some other useful features too.

Can changing port so that url becomes different - like localhost:3500 do the trick?
Tried command: '$env:port=3500' and then started nextjs server (npm run dev).
Browsed to: http://localhost:3500/
It worked. The chapter links are shown in blue (not visited) now.
----------------

One big issue I find with Tw as I do this migration, is that I need to repeat (copy-paste) the set of Tw classes I am using for various elements like h2, h3, p across all pages of the app. including minor pages like not-found.jsx.

Reusing Styles(,) Managing duplication and creating reusable abstractions, https://tailwindcss.com/docs/reusing-styles discusses the issue in general but ... It mentions, "you can use Tailwind’s @apply directive to extract repeated utility patterns to custom CSS classes" but adds some buts. I guess I need to know from other sources how they deal with this issue.

Drying up identical tailwind classes, https://stackoverflow.com/questions/73143716/drying-up-identical-tailwind-classes covers this issue but the responses are limited with @apply suggested as a solution with a but.

There are some other more involved articles but I don't want to spend time on reading them now. For this migration to Tailwind step for this app., I will go with repeated code (violates DRY - Don't Repeat Yourself design principle). Later on, perhaps before I add regular web UI features to this app., I will study available info. on how to handle this issue.

Now the entire app UI is very close to VSG app UI. The commit point, "VSG app migrated to Tailwind", https://github.com/ravisiyer/gita/tree/e92ac7e20e10f48ed664524e088b29bd3afb7e84 has the files at this time point. I have also deployed the app: https://gita-rsi.vercel.app/.
====================

I have moved on to next step of migrating the app to TypeScript. Note that the app. has TypeScript  package installed but the main source files were .jsx and .js files and so not using TypeScript. I have started converting them to .tsx and .ts files, which brings TypeScript into play.

For example, a blog could include the following route app/blog/[slug]/page.js where [slug] is the Dynamic Segment for blog posts.

export default function Page({ params }: { params: { slug: string } }) {
  return <div>My Post: {params.slug}</div>
}
-----

The challenging part was related to GraphQL data. As an initial step, I looked up the source code  of "Frontend for BhagavadGita.io v2", gita-frontend-v2, open-source Github repo which seems to use an auto generated typescript file. The types were slightly different from the GraphQL types as I think the app. may not be using GraphQL data source but another data source with same data. However, I got good hints about what the basic data types for leaf-level fields would be for the GraphQL data source my app is using (I did not get into how complex types are used in the gita-frontend-v2 app). Based partially on that and based partially on some guesswork, I hand-wrote some TypeScript (TS) types which I used in the main pages of the app that deal with this data.  But I did not use these types in the lib data.ts file which makes the Apollo client GraphQL function calls. Interestingly, data.ts did not raise any TS errors. Later, I intend to explore whether I can use the relevant TS types in the data.ts file too. 

This hand-coded TS types for GraphQL data worked. This app's 'Partial migration to TypeScript' commit point, https://github.com/ravisiyer/gita/commit/2b208216b1cc147ec9920b93b3aef7e4c869c65b has the source code.

Next step was to confirm the data type info. that I have used, with the GraphQL data source. That turned out to be an involved affair. Given below are the notes related to that.

https://graphql.org/learn/schema/ gives info. on data types in GraphQL. They include: String, ID, Int, Float and Boolean.
...
{
  __schema {
    queryType {
      fields {
        name
        description
      }
    }
  }
}
Above query lists name and description of all GraphQL queries (in that GraphQL server).

...

https://graphql.org/learn/introspection/ may be the reference page for such schema info.
...
{
  __schema {
    types {
        name
    }
  }
}

Above query lists the types used.
...

{
  __type(name: "GitaAuthor") {
    name
    kind
  }
}

Above query gives output:
{
  "data": {
    "__type": {
      "name": "GitaAuthor",
      "kind": "OBJECT"
    }
  }
}

==============

{
  __type(name: "GitaAuthor") {
    name
    fields {
      name
      type {
        name
        kind
        ofType {
          name
          kind
        }
      }
    }
  }
}

Above query gives output:

{
  "data": {
    "__type": {
      "name": "GitaAuthor",
      "fields": [
        {
          "name": "nodeId",
          "type": {
            "name": null,
            "kind": "NON_NULL",
            "ofType": {
              "name": "ID",
              "kind": "SCALAR"
            }
          }
        },
        {
          "name": "id",
          "type": {
            "name": null,
            "kind": "NON_NULL",
            "ofType": {
              "name": "Int",
              "kind": "SCALAR"
            }
          }
        },
        {
          "name": "name",
          "type": {
            "name": "String",
            "kind": "SCALAR",
            "ofType": null
          }
        },
        {
          "name": "gitaCommentariesByAuthorId",
          "type": {
            "name": null,
            "kind": "NON_NULL",
            "ofType": {
              "name": "GitaCommentariesConnection",
              "kind": "OBJECT"
            }
          }
        },
        {
          "name": "gitaTranslationsByAuthorId",
          "type": {
            "name": null,
            "kind": "NON_NULL",
            "ofType": {
              "name": "GitaTranslationsConnection",
              "kind": "OBJECT"
            }
          }
        }
      ]
    }
  }
}

-----

Hmm. That's quite a difficult way to get the data type info. if one does it manually.

Is there a TypeScript types generator for GraphQL? Google search gives lot of hits.

Generate TypeScript Types from a GraphQL Schema, https://www.youtube.com/watch?v=Ob3MRkgQdcc , 4 min. 22 secs., published July 2022.



Initially I felt that the above approach is too complex for my current needs. The above approach surely has advantages like keeping TS types in sync with the GraphQL schema but I think I can ignore that for the time being.

=============
I looked for simpler solutions where I could specify the GraphQL source on some webpage and click a button to get the TS types for that. I could not find such a website. There were some possibilities like some product now owned by IBM called StepZen - "Using GraphQL APIs with TypeScript in a React application" YT video , official website. But in the very quick browse I did of the links given earlier, it seemed to need some registration which I wanted to avoid.

So I gave another shot at getting type info. through GraphQL Explorer for the data that I use and then creating/correcting the data types I use in the app.

I first got all the type info. (and query info.) using the following query:

query {
 __schema {
    types {
  name
  description
  kind
}
queryType {
  fields {
name
description
  }
}
   }
 }


The query's output is very long and so I am not sharing it in this post. I saved the query output in a file.

Then I took up one of the queries of the app. and tried to pick up related type info. from the above query output file. I also made further queries on types. I was able to ensure that for getAllChapters function's query of allGitaChapters, I had a TS data type GitaChapterSummary with the TS object data type and its property types matching the GraphQL object data type and its property data types. Note that GitaChapterSummary uses only some of the fields returned by allGitaChapters,

Next I looked at function getChapter(chapterNumber: string) which uses allGitaChapters again but with a condition and also uses some more fields than used by query used in getAllChapters function. The data has nested types. It was more complex to ensure that TS data types I used in getChapter function matched GraphQL data types. Further, in my hand-written data types, I was using one TS data type GitaChapterSummary in function getAllChapters, and another data type GitaChapter in function getChapter, for the same underlying GraphQL data type. That was not ideal.

So I thought of looking at Codegen again but using it in a limited way. I explored solutions where I could generate type info. of the GraphQL source using codegen in a dummy project, and then examine its contents to see if I could use it in a simple way in my app.

Created a temp copy of app project and in that, tried Codegen mainly by using https://the-guild.dev/graphql/codegen/docs/getting-started page and https://www.youtube.com/watch?v=Ob3MRkgQdcc video (both listed earlier). 

First trip up was that I did not know that I have to run 'npm run codegen' to generate the types as the first link above (Codegen one) did not seem to mention it.

Then Codegen reported error about app source files but it was able to pick up the graphQL data source [Green tick on: ' Load GraphQL schemas']. In config specification, I had used: documents: "app/**/*.tsx",
---
The error was: 
Unable to find any GraphQL type definitions for the following pointers:

              - app/*…
----

I later realized that my GraphQL queries are in app/lib/data.ts . So in config I specified:
  documents: "app/lib/data.ts",
---
That resulted in error:
   ✖ Syntax Error: Unexpected "}".
---
Don't know why it reported this error as the file looked OK in VSCode.

I created a test file datatest.ts where I retained only getAllChapters function (which has one query), and in config file I specified:
  documents: "app/lib/datatest.ts",
---

Codegen reported:
✔ Parse Configuration
❯ Generate outputs
  ❯ Generate to app/gql/
    ✔ Load GraphQL schemas
    ✔ Load GraphQL documents
    ⠹ Generate
[client-preset] the following anonymous operation is skipped:
        query {
          allGitaChapters {
            nodes {
              id
              chapterNumber
              chapterSummary
              chapterSummaryHindi
              name
✔ Parse Configuration
✔ Generate outputs
----

Don't know why the 'anonymous' operation was skipped. But it generated some files. I checked app/gql/graphql.ts which seems to have all the types of the GraphQL source! It is almost 2500 lines!

Created a gqltypes-d.ts from the above file where I copy-pasted the types that I needed. This file was much smaller (around 240 lines). I then used this gqltypes-d.ts file in my app. Note that Codegen is not part of my app. I have simply used gqltypes-d.ts file in my app as a standard TS file which defines some types.
---------

chaptersummaries worked with gqltypes-d.ts.
But [chapternumber]/page.tsx is giving TypeScript error/warning for below line with verse:
              <h3 className="my-4 text-lg font-bold">{`Verse ${verse.verseNumber}`}</h3>
---
The error  message is:
'verse' is possibly 'null'.ts(18047)
(parameter) verse: Maybe<GitaVerse>
----

Articles on this Maybe issue:
Solving The 'Undefined' and the "Maybe' Problem in TypeScript, https://dev.to/rileyseaburg/solving-the-undefined-and-the-maybe-problem-in-typescript-351o
Working efficiently with GraphQL-CodeGen types in TypeScript, https://blog.mayflower.de/8860-typescript-graphql-codegen-types.html

Using the approach of the 1st article above, the earlier line can be changed to:
              <h3 className="my-4 text-lg font-bold">{`Verse ${verse!.verseNumber}`}</h3>
---
The TS error goes away. But is this an acceptable way? I don't know.
For the time being, I am using this approach.

One line needed two !'s:
            <h4 className="my-4 font-bold">{`English translation by ${verse!.gitaTranslationsByVerseId.nodes[0]!.authorName}`}</h4>

-----

Another file verse/[id]/page.tsx also need above ! solution to some TS errors.
----
The approach seems to work okay with app running as expected. The commit point, "more files use codegen generated types file suitably truncated",  https://github.com/ravisiyer/gita/commit/a7324d0ee35f48850ae2db2868a8c3d354b022d7 ,
has the files at this stage. The main files of chapter summaries, chapter and verse work as expected. 

https://github.com/ravisiyer/gita/blob/a7324d0ee35f48850ae2db2868a8c3d354b022d7/app/lib/gqltypes-d.ts shows the gqltypes-d.ts file at this stage. It certainly was much easier to create this file by manually extracting required classes from Codegen's full types file, than to handwrite this file and ensure that TS data types match GraphQL data types.

Perhaps there is a way to ensure Codegen generated types file that is used by the app. is small in size. I don't know how to do that and don't want to invest time, as of now, to figure it out. Also, ideally Codegen should be installed in my app, as that seems to be the norm. As my current objective is to migrate my app to TS and not really focus on GraphQL and TS usage, I think my above solution is good enough. Later, if needed, I can go deeper into GraphQL and TS usage at which time I may try to integrate Codegen into my app itself.

==========================

Sometimes, on changing .js or .jsx file to .ts or .tsx, while the nextjs server is running ('npm run dev'), some errors crop up in the app. Restarting the nextjs server fixes the issue.

Also, some messages about 'update imports', IFIRC appear. I usually have said yes, for them. At times, that results in addition of filename to tsconfig.json with the file being opened and edited with the change, leaving it to me to save it. I have not really understood what's going on here. But will look at it, if required.

TypeScript isNaN only accepts a number, https://stackoverflow.com/questions/42120046/typescript-isnan-only-accepts-a-number : Comment in it suggests using:
isNaN(Number("abc"))
to avoid TypeScript error.
Used that to resolve the error I was having:
  if (isNaN(Number(chapterNumber))) {
---

Event Types in React and TypeScript, https://www.totaltypescript.com/event-types-in-react-and-typescript : "The first solution is to hover over the type of the thing you're trying to pass in:" - works for me for OnSubmit(e) ... Typescript error for parameter e.

---
In below code, TS gives an error for size.

<input
        className="mr-1 border border-neutral-500 leading-none w-12 text-sm py-px px-0.5 font-['Arial']"
        type="number"
        id={idChapterNumber}
        size="2"
        min={FIRST_CHAPTERNUMBER}
        max={LAST_CHAPTERNUMBER}
        required
        value={chapterNumber}
        onChange={(e) => {
          setChapterNumber(e.target.value);
        }}
      />
---

Solution suggested by React TypeScript error for size attribute of html input element, https://stackoverflow.com/questions/62082063/react-typescript-error-for-size-attribute-of-html-input-element of using:
size={100}
worked for me:
        size={2}
---

I had to use an extra exclamation mark here to solve a TS error in verse/[i]/page.tsx that cropped up after I had fixed TS error for the associated function: capitalize..., IFIRC:
                In {capitalizeFirstLetter(translation!.language!)} by{" "}
---
Similarly for commentary.language
----

Fixed all TS errors in project. Tested app. It seems to work.
Commit point, 'All TypeScript errors fixed', https://github.com/ravisiyer/gita/commit/8bfe3eaa0a67d9822b658f04c3940adad27f8120 has the source code at this stage.

---


Intro to the TSConfig Reference, Include, https://www.typescriptlang.org/tsconfig/#include has an example and explanation for it.
From above page: 
* matches zero or more characters (excluding directory separators)
? matches any one character (excluding directory separators)
**/ matches any directory nested to any level
----

I wanted to check that tsc is picking up the files I have specified in tsconfig.json. Note that VSCode editor showing TS errors in Intellisense kind of way would probably be an editor feature. At build time, tsc would run.

Just using 'tsc' command gives a not-found PowerShell error (as tsc is installed locally and my PATH variable does not include its folder). Solution is to use 'npx tsc'. Ref: tsc is not recognized as internal or external command, https://stackoverflow.com/questions/35369501/tsc-is-not-recognized-as-internal-or-external-command .

Then I deliberately introduced a TS error in one .tsx file, but commented out the **/*.tsx line in tsconfig.json, and ran 'npx tsc'. It picked up the .tsx file with the error and listed the error! I could not figure out how it picked up that file. I restarted VSCode and tried the command again with same result!

Then I commented this line in tsconfig.json:
    // ".next/types/**/*.ts"
---
After that, tsc did not pick up the .tsx file! Hmm. Don't know how exactly that works but now I have some idea.

Changed it to:
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
---
Now the file is getting picked up by tsc, as expected.
Using Timeline feature of VSCode, I looked up the wo-twts app version and looked at tsconfig.json at its earlier commit. It had the line:
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
----

So the above seems to be default at app creation time (using create-next-app which is what I think I would have used).
----

Based on: How can I get the list of Typescript files that tsc will compile?, https://stackoverflow.com/questions/53397919/how-can-i-get-the-list-of-typescript-files-that-tsc-will-compile :

I tried:
npx tsc --listFilesOnly
It listed many files including node_modules files!

npx tsc --listFilesOnly -p tsconfig.json
listed too many files So I tried:
npx tsc --listFilesOnly -p tsconfig.json > tsclist.txt
tsclist.txt has 647 lines + 1 blank line.
Lines 624 to 641 were related to my app:
--snip--/dev/app/constants.ts
--snip--/dev/apolloClient.ts
--snip--/dev/app/lib/data.ts
--snip--/dev/app/lib/dummydata.ts
--snip--/dev/app/lib/gqltypes-d.ts
--snip--/dev/app/lib/util.ts
--snip--/dev/app/chaptersummaries.tsx
--snip--/dev/app/error.tsx
--snip--/dev/app/ui/selectchapver.tsx
--snip--/dev/app/ui/navbar.tsx
--snip--/dev/app/layout.tsx
--snip--/dev/app/not-found.tsx
--snip--/dev/app/page.tsx
--snip--/dev/app/[chapternumber]/not-found.tsx
--snip--/dev/app/[chapternumber]/page.tsx
--snip--/dev/app/about/page.tsx
--snip--/dev/app/verse/not-found.tsx
--snip--/dev/app/verse/[id]/page.tsx
----------

OK. So I could confirm that it does pick up my app's files. Why is node_modules picked up - most of the lines in the file relate to files in node_modules?
tsconfig.json has the line:
  "exclude": ["node_modules"]
---

I tried to check if I can quickly get an answer to why node_modules files are being listed but did not suitable solutions. A couple of pages suggested using '"skipLibCheck": true,' in compilerOptions but that is already there in my tsconfig.json. I feel I should not invest further time into this as I can still check whether my app files are getting compiled by tsc which is my main need.
...
 ...
I ran 'npx tsc' after removing the deliberate TS error I had introduced. It finished execution without any messages. So I presume it did not find any errors.
===================

Note that many variables do not have explicitly defined types but TS is able to figure out the type with Intellisense showing the (implicit) type. I have not invested time in explicitly defining types for all variables - don't know if that is acceptable conventions wise for projects using TS.
----

I considered work involved in introducing types in data.ts. To do a complete job, I would need new types like GitaChaptersConnection which holds an array of GitaChapter in node. I would need to understand the GitaChaptersConnection type and how it maps to GraphQL type. I don't think I should invest so much time now as GraphQL is not really an area I want to focus on. So I have decided to leave data.ts as it is now with any data type being implicitly applied to its data variables. It is a small file (less than 100 lines) with the main code being the query and straightforward extraction of required data from the returned data.

--------
Merged to-ts branch (was used for TS migration) in main. Commit point, Migration to TypeScript done, https://github.com/ravisiyer/gita/commit/14312727a24293ed6eb1b4d7b2ace2570102b647 has the source code at this stage.

The app. is deployed at: https://gita-rsi.vercel.app/.
-----------

The root layout (app/layout.tsx) is shared across app. I had max width set in app/page.tsx which uses ChapterSummaries component and so home page had max width set. Other pages including Chapter and Verse pages have their own page.tsx files which do not have the same max width setting (or do not have it) and so those pages had a different width for large window width cases. 

One solution is to make changes to Root Layout where we add a main element and provide max-width Tw class there. But is that acceptable convention wise?

Below page gives an example of using common layout across app but it seems to use a separate Layout page (not Root Layout page):


Exploring the Next.js Root Layout for Scalable Web Applications, https://www.dhiwise.com/post/exploring-nextjs-root-layout-for-scalable-web-application

https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#root-layout-required gives an example of root layout where children are within main element:
      <body>
        {/* Layout UI */}
        <main>{children}</main>
      </body>
---

As the above approach is from nextjs documentation, I think it is OK to use it. That worked with all pages including not-found and error pages, using the max-width specified in the root layout's main element.

===================================

Why You Shouldn’t Pass React’s setState as a Prop: A Deep Dive, https://medium.com/@christopherthai/why-you-shouldnt-pass-react-s-setstate-as-a-prop-a-deep-dive-8a3dcd74bec8 advises against passing a setState method down from parent to client. One solution suggested is to have a function in the parent that does the required modification by using setState and passing that function down to the child.

I decided to use this approach for closing the drop-down menu when Go button in SCV is clicked, with Navbar being parent of SCV.
===============



How to type React Props with TypeScript, https://akoskm.com/how-to-type-react-props-with-typescript
----

Two very useful links about React and TS:


---
Merged reg-menu branch (was used for this feature) in main and updated the README/About files. Commit point, Updated README, About and Metadata,  https://github.com/ravisiyer/gita/commit/6f557fac54599186a22b0f0b8a73ba9eb5fed41d has the source code at this stage.

The app. is deployed at: https://gita-rsi.vercel.app/.
-----------

Added icons to navigation bar. Notes for that are given below:

Official nextjs tutorial uses @heroicons.
Search for icons (without icon names): https://heroicons.com/ [Has link to copy SVG but does not mention icon name]
List of icon names: https://unpkg.com/browse/@heroicons/react@2.1.4/24/outline/ . Note that icon names are used in official Nextjs tutorial. I think that makes the code more readable than copy-pasting SVG icons code.

I did not get Next icon when I searched the above and so I switched to react-icons where I was able to get many Next (and Previous and Up) icons.

import { GrLinkNext } from "react-icons/gr";
<GrLinkNext />
npm install react-icons --save
[As my npm version is close to latest, 'npm install react-icons' is enough.]

The commit point for the app with menu icons is: menu icons added,  https://github.com/ravisiyer/gita/commit/400ead4a85043b623dc261abba4373c41224cf3e

------------------


The above article below helped me to clip the height of the image when window width was >=930px, so as to hide a bottom part of the hero image that I did not want to be seen. But as the window width reduced from 930px the image started getting compressed and so the bottom part started becoming visible. Therefore I have decided to manually clip the image bottom in the image file itself. However, the code that hides it till a point may be useful later and so I have given that below:

      <div className="max-w-4xl max-h-[520px] overflow-hidden">
        <Image
          src="/hero.jpg"
          alt="Hero Image"
          width={896}
          height={520}
          // Image aspect ratio is retained with width:896 and height:636. Image is 3040x2160
          style={{ objectFit: "contain" }}
          // style={{ objectFit: "cover" }}
        />
      </div>
----

The above code is not pretty but it works till the 930px point. It took me quite some time to get the above 'solution'. I find this aspect of Nextjs Image component to be quite strange.
==================

Changed Next and Prev icons as earlier ones could get confused with Forward and Back icons of browser.

For below 896 max-width, header width becomes visibly slightly longer than hero image and other contents below.

Moved p-4 out of layout and specified px-4 at needed places in app/page to make hero image aligned with nav bar. Will need to add px-4 to all other pages for consistency!!! Don't know if having px-4 for mobile is good design. Need to check this out. Official nextjs tutorial may help.

Official Nextjs tutorial (Acme)
------------------------------
Padding for title bar (Acme logo bar) in home page (not logged in): 24px padding for entire main element
app/layout.tsx does not specify any padding or margin:
<body className={`${inter.className} antialiased`}>{children}</body>
---
app/page.tsx specifies p-6 as padding for main:
    <main className="flex min-h-screen flex-col p-6">
---
So the blue bar having logo inside it has p-6 padding
The logo itself in above page.tsx has additional p-4 padding in the div associated with the blue bar having logo:
      <div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
----
Other content in the page have more x-axis (width) padding.
----
app/login/page.tsx has effectively p-4 padding though it is applied to a div contained in main element:
    <main className="flex items-center justify-center md:h-screen">
      <div className="relative mx-auto flex w-full max-w-[400px] flex-col space-y-2.5 p-4 md:-mt-32">
----
The blue bar with the logo inside it in above login page is within this div:
        <div className="flex h-20 w-full items-end rounded-lg bg-blue-500 p-3 md:h-36">
---
The above div has p-3 for the logo.
When I compared the home page and login page display for small width window, I found that blue bar with logo for login page has more white background on left and right than the home page, even though padding is only 4 for login page while it is 6 for home page . I think that may be due to mx-auto being used in login page.
What's clear is that there is lack of consistency in white background area for blue logo bar btw home page and login page.
---

The dashboard page has both blue logo bar and a navigation bar below it. They both have equal width for small window width (and probably for other widths too). But the white space on the left and right is lesser than home page. Once again, lack of consistency in this matter.

dashboard has a layout page. Its key code related to this issue:
    <div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
      <div className="w-full flex-none md:w-64">
        <SideNav />
      </div>
      <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
    </div>
----

The logo bar and nav bar are in SideNav component. The div's containing it do not specify padding or margin.
SideNav component div element containing both logo bar and navbar:
    <div className="flex h-full flex-col px-3 py-4 md:px-2">
---
So it is px-3 in this case which explains the white space on left and right being lesser than home page.

Further note that in dashboard layout, the contents below SideNav are in a div with p-6 [and md:p-12]. So those contents have more white space on left and right than SideNav (px-3) for width below md. [Note that for md and above width the SideNav becomes a vertical bar with the children (dashboard data) coming to its right. We need not examine that scenario for our needs here.]

===========
Conclusions about Acme tut.:
1) Root layout page does not specify margin or padding. So other pages or layouts have to specify that. Dashboard layout does specify padding.
2) The white background on left and right of blue logo bar is not consistent across home, login and dashboard pages.
3) Even on less than tablet breakpoint (and so includes mobile), the padding and so white space on left and right of blue bar having logo, is at least 12 pixels. And the logo (icon & text) has additional padding in the blue bar (at least 12 pixels)
-----

Therefore, going by Nextjs tutorial example, Simple Gita app. having 8 pixels white space on left and right of navbar for mobile size should be OK. Further, padding or margin should not be specified in Root layout if Nextjs example has to be followed. [Later I felt I need not follow Nextjs tutorial convention on this point but do what I feel is reasonable.]
====

In Verse page, font leading (leading-snug) for Hindi and Sanskrit is the same as used in Chapter for Hindi. Large block of Hindi/Sanskrit text in Verse page seems to be smaller than in Chapter page but in Chrome DevTools I checked that even the large block has leading-snug associated with it.

Tw:
leading-none line-height: 1;
leading-tight line-height: 1.25;
leading-snug line-height: 1.375;
leading-normal line-height: 1.5;

Should I use leading-tight instead of leading-[1.1] in my app? I am using leading-snug for Devanagari or text that could be English or Devanagari (Translations/Commentaries).

If leading is not specified and there is no text (font) size specification (e.g. text-sm) then the line-height that is set to 1.5 (leading-normal value) by Tw for html,:host elements gets applied. My initial thoughts were that this line-height results in too much gap. IIRC, Chrome browser default is 1.2. gita-frontend-v2 uses leading-loose which is line-height of 2 for Chapter page. Official nextjs tutorial seems to use leading sparingly and so it may be going with the default (1.5 value) for text without (font) size specification.

Using Chrome DevTools, I saw that Gita Supersite (does not seem to use Tw) uses 16px font for English Translation with line-height of 20.8px [font is Open Sans though Times New Roman is also mentioned after it]. The gap seems good. [Tw 1.5 line-height would make it 24px]. For Sanskrit Commentary, it uses font-size of 16px with line-height of 20.8 px [Font is Nirmala UI though Open Sans is also mentioned after it]. This gap seems to be less. Ref: https://www.gitasupersite.iitk.ac.in/srimad?language=dv&field_chapter_value=1&field_nsutra_value=1&scsri=1&etgb=1&choose=1

Size Matters: Balancing Line Length And Font Size In Responsive Web Design, https://www.smashingmagazine.com/2014/09/balancing-line-length-font-size-responsive-web-design/ states, "While there is no perfect line height, a good rule of thumb is to set it at approximately 150% of the font size.". That's the Tw default.

I thought that, as of now, I should play safe and go with default Tw value for leading for both English and Sanskrit normal size text, and did that. Later when I have more knowledge about this topic, I could change it.


=====================================
Is Times New Roman a font that is used for apps (my app is using that now)? If not, consider replacing it with what's more popular for apps.
Roboto, Inter and Open Sans are mentioned in this page as good fonts: 11 best fonts for web design, https://webflow.com/blog/fonts-for-web-design. Roboto, IIRC, was used in some of the Dave Gray tutorials. Inter is used by gita-frontend-v2 as well as nextjs tutorial.

Nextjs tutorial has a fonts.ts file with following statements:
import { Inter, Lusitana } from 'next/font/google';

export const inter = Inter({ subsets: ['latin'] });

export const lusitana = Lusitana({
  weight: ['400', '700'],
  subsets: ['latin'],
});
---
Subsequently in layout.tsx it has these statements:
import { inter } from '@/app/ui/fonts';
...
<body className={`${inter.className} antialiased`}>{children}</body>
---
https://nextjs.org/learn/dashboard-app/optimizing-fonts-images explains benefits of using next/font module (prevents layout shift as fonts are downloaded at build time and hosted with other static assets). "By adding Inter to the <body> element, the font will be applied throughout your application. Here, you're also adding the Tailwind antialiased class which smooths out the font. It's not necessary to use this class, but it adds a nice touch."

Lusitana is used as a secondary font.

In app/page.tsx Lusitana font is used. Related statements are:
import { lusitana } from '@/app/ui/fonts';
...
          <p
            className={`${lusitana.className} text-xl text-gray-800 md:text-3xl md:leading-normal`}
          >
            <strong>Welcome to Acme.</strong> This is the example for the{' '}
            <a href="https://nextjs.org/learn/" className="text-blue-500">
              Next.js Learn Course
            </a>
            , brought to you by Vercel.
          </p>
----
----

gita-frontend-v2 uses Inter font in two ways. One is a variation of the above way, where all the main statements to use Inter are in app/layout.tsx and using it in html element rather than body. It also defines/declares it in tailwind config and in global.css!
In tailwind config, key statements are:
...
theme: {
    extend: {
      fontFamily: {
        inter: ['"Inter"', "sans-serif"],
        dev: ["Noto Sans Devanagari", "sans-serif"],
      },
...
-----
In global.css, key statements are:
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@200;400;800&display=swap");
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari&display=swap");

body {
  font-family: "Inter", sans-serif !important;
}
-----------
Example of code to use the font is:
      <div className="absolute inset-x-0 mx-auto max-w-5xl text-center font-inter">
----
font-inter to use inter("Inter") and font-dev to use "Noto Sans Devanagari"
---

Reviewing Inter: A Versatile Font for Web and User Interface, https://typogram.co/font-discovery/how-to-use-inter-font, June 2023 - "This week we share inter, a highly versatile neo-grotesque sans-serif font perfect for digital things like the web and apps."
--------

Noto Sans Devanagari, https://fonts.google.com/noto/specimen/Noto+Sans+Devanagari - "Noto is a global font collection for writing in all modern and ancient languages. Noto Sans Devanagari is an unmodulated (“sans serif”) design for texts in the Indic Devanagari script. It has 954 glyphs."


---------

Windows seems to use Nirmala UI Devanagari font. So my app. which, as of now, does not specify a Devanagari font family, uses the default which is Nirmala UI for Devanagari text, on Chrome on Windows (and perhaps on Edge on Windows too). Don't know what font will be used for non-Windows systems. 

Nirmala UI, https://en.wikipedia.org/wiki/Nirmala_UI - "Nirmala UI ("User Interface") is an Indic scripts typeface created by Tiro Typeworks and commissioned by Microsoft. It was first released with Windows 8 in 2012 as a UI font and currently supports languages using Bengali–Assamese, Devanagari, Kannada, Gujarati, Gurmukhi, Malayalam, Meitei, Odia, Ol Chiki, Sinhala, Sora Sompeng, Tamil and Telugu."

For Devanagari on Ubuntu Linux, the comments in this page mention Lohit Devanagari, Gargi and Noto Sans Devanagari (Nirmala UI is not mentioned):  How can I make Devanagari fonts render properly in Ubuntu 16.04?, https://askubuntu.com/questions/855739/how-can-i-make-devanagari-fonts-render-properly-in-ubuntu-16-04, Dec. 2016.

----------

In my app, currently I think I should take the straightforward path and use Inter for all English text and Noto Sans Devanagari for Hindi/Sanskrit text. Inter can be applied at body level and so font need not be specified in contained elements. For elements that can have English or Sanskrit/Hindi text, I wonder if it can automatically sense the language and so use Noto Sans Devanagari.

(Devanagari Font) How to ensure all parts of the text are visible in a <select>?, https://stackoverflow.com/questions/67752213/devanagari-font-how-to-ensure-all-parts-of-the-text-are-visible-in-a-select , May 2021 discusses using Noto Sans font "to render English text along with Hindi (Devanagari) in a <select>"
From the above, it seems that one can use "Noto Sans" font for English or Devanagari text elements! Hmm.

How to serve a page with content in multiple languages ?, https://www.geeksforgeeks.org/how-to-serve-a-page-with-content-in-multiple-languages/ discusses using the lang attribute but does not mention font. Hmm. Interesting!

Seems to be a very appropriate article to study sometime later: Styling using language attributes, https://www.w3.org/International/questions/qa-css-lang/1000

=======================

Done
===========
Is have para tags within header tag OK?
          <h3 className="text-lg font-bold">
            <p>Chapter Summaries</p>
            <p>अध्यायों का सारांश</p>
          </h3>
----

Is it valid to have paragraph elements inside of a heading tag in HTML5 (P inside H1)?, https://stackoverflow.com/questions/19779519/is-it-valid-to-have-paragraph-elements-inside-of-a-heading-tag-in-html5-p-insid . Comment(s) in the article say that it should not be done. It also says, "As stated before, span tag is perfectly valid inside of a header elements (h1-h6). And you can apply "display: block;" style to it to make it render as a block level element (each on a different line). It will save you a br tag."
So consider changing above code in app. ... Done
---
Done: In Navbar.tsx, closeMobileMenuIfOpen() and menuLinkClickHandler arrow function do the same task. Only one such function should be retained.
---
Done: Consider adding active: to Chapter Tiles and perhaps some other link buttons.
---
Done: About page uses usual web page styling for links. Should that be changed to what rest of app uses? Rest of app. pages use buttons. It seems inappropriate to use buttons for the About page links. So am retaining it as is.
---

Done but dropped Noto Sans Devanagiri ... See notes on this topic: Use Inter and Noto Sans Devanagiri fonts. [Consider replacing font-['Arial'] with more regular way of specifiying it. ... Removed Arial font class and let default (Inter) be used.]
==========================================

From https://developer.mozilla.org/en-US/docs/Web/CSS/font-family : "The font-family property specifies a list of fonts, from highest priority to lowest. Font selection does not stop at the first font in the list that is on the user's system. Rather, font selection is done one character at a time, so that if an available font does not have a glyph for a needed character, the latter fonts are tried. When a font is only available in some styles, variants, or sizes, those properties may also influence which font family is chosen." Hmm. So if I have Inter followed by Noto Sans Devanagiri as the first two fonts in the font-family, and if I have Devanagari text in an element, if the Devanagari text characters do not have glyphs in Inter, then Noto Sans Devanagari will be used by the browser, if my understanding is right.


Inter supports 147 languages but Devanagari script does not seem to be supported: https://rsms.me/inter/#languages


From: Win10, change System Font for a better one?, https://write.tedomum.net/rgx/win10-change-system-font-for-a-better-one : "For Windows 10 users, the default System font is the new 'Segoe UI' font and its variants, all included in the default Windows 10 install."

When I comment out the Times New Roman font-family lines from global.css, then Tw default of font-family: 'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"' comes into play as the style of text elements (as seen in Chrome DevTools). If the text content is Devanagari, the applied fonts are Nirmala UI and Segoe UI (I think space character is handled by Segoe UI). If the text content is English, the applied font is Segoe UI (only).

----




=============================

Code I tried:
app/ui/fonts.ts:
import { Inter, Noto_Sans_Devanagari } from "next/font/google";

export const inter = Inter({ subsets: ["latin"] });

export const nsdev = Noto_Sans_Devanagari({ subsets: ["devanagari"] });
----
app/layout.tsx:
import { inter, nsdev } from "@/app/ui/fonts";
...
      <body
        className={`${nsdev.className} ${inter.className} antialiased mx-2 mb-2 break-words`}
      >
----

The above was a trial to see if both Noto Sans Devanagari (NSD) and Inter get added to font-family for body with NSD having precedence. DevTools showed that only NSD was picked up and Inter was overridden. IFIRC, I tried changing the order of NSD and Inter and got the same result of NSD being picked and Inter being overridden.

Key point is that above way of specifying both fonts does not work.

I was surprised to see in DevTools that English text was being rendered with NSD even though I had specified only Devanagari subset.
----

If only Inter is used, with code as follows:
      <body
        className={`${inter.className} antialiased mx-2 mb-2 break-words`}
----
then English text is rendered with Inter and Devanagari with Nirmala UI.
For Sanskrit text with font-family inherited from body, DevTools Styles shows:
.__className_aaf875 {
    font-family: '__Inter_aaf875', '__Inter_Fallback_aaf875';
    font-style: normal;
}
----
But it displays the Sanskrit text correctly! DevTools Computed shows:
Rendered Fonts
Family name: Nirmala UI
PostScript name: NirmalaUI
Font origin: Local file(187 glyphs)
Family name: Inter
PostScript name: Inter-Thin
Font origin: Network resource(51 glyphs)
----

So, in this case, for Devanagari text, the system default for it is used by the browser. Interesting and good! 
...

I modified chapter page to have following code (similar code repeated for other Hindi text):
import { nsdev } from "@/app/ui/fonts";
...
          <span className="block text-xl font-bold text-center mt-2">{`Chapter ${chapterNumber}`}</span>
          <span className="block text-3xl font-bold text-center mt-2">{`${gitaChapter.nameTranslated}`}</span>
          <span
            className={`${nsdev.className} block text-3xl font-bold text-center mt-4`}
---

For the Hindi summary large block of text, DevTools Computed showed:
Rendered Fonts
Family name: Noto Sans Devanagari
PostScript name: Noto-Sans-Devanagari-Thin
Font origin: Network resource(246 glyphs)
----
So even spaces in Hindi text were rendered using NSD.
But English text where no font className was specified used Inter font (as expected).

my-gita app uses Kalam font from Google fonts.

From: Introducing variable fonts, https://fonts.google.com/knowledge/introducing_type/introducing_variable_fonts : "Variable fonts—officially known as OpenType Font Variations—remove the explicit distinctions between different weights and styles, which have existed since the early days of typesetting. It’s no exaggeration to say that this represents a huge leap forward in font technology in recent years."

Inter and Noto Sans Devanagari seem to be variable fonts (Clicking 'Get Font' leads to page where 'variable' is shown next to the font name) while Kalam does not seem to be a variable font ((Clicking 'Get Font' leads to page where 'static' is shown next to the font name). Just saw that Font search shows variable for Inter and Noto Sans Devanagari whereas for Kalam it shows '3 styles'.

gita-frontend-v2 (bg-io) seems to only show Swami Sivananda English translation and commentary. Using 'Source' menu to change both to Swami Ramsukhdas Hindi did not result in any change in content of page (even after refresh and moving to another verse). Inter, sans-serif font family is specified for the translation and commentary for this text. As Swami Sivanananda English commentary has mostly English text but some Sanskrit text too, DevTools shows that Arial and Nirmala UI are used to render them. Why is Inter not used instead of Arial? Hmm. Does the code in bg-io project that imports Inter font have some problem?

NSD font for same weight (700) and font-size (18px) and line-height (28px) seems to be quite smaller than Nirmala UI (Nirmala UI Bold?).

Searching for Devanagari fonts on Google Fonts seems to show few Devanagari fonts with Noto Sans Devananagari and Anek Devanagari as perhaps the only suitable variable fonts for Hindi or Sanskrit.  Anek Devanagari font seems to have same quite small size as compared to Nirmala UI (Bold?) font.

I think I had opted for using Noto Sans Devanagari (NSD) as I saw that (bg-io) code uses it and presumed that the bg-io site is using it. Now that I know that the bg-io site does NOT use it (don't know why?), and I don't know of a site that I am familiar with which uses NSD, I think I should go with the default Nirmala UI on Windows which, on Windows, is used by bg-io as well as Gita Supersite. The cursive Kalam font used by my-gita seems to be unsuitable for my app.

I think that I simply need not specify a Devanagari font and leave it to the browser (and underlying OS) to choose which font to use to render the Devanagari characters. Later, after I get a better understanding of Devanagari font usage in Nexjs apps, I can consider changing it.

Made the above mentioned change. Most of the Devanagari text in app looks OK now. But Verse page main verse text has a very small gap btw lines issue as compared to earlier version of app running on vercel.
Now my app has my-4 text-3xl Tw classes ((font-size: 30px line-height:36px) for it whereas earlier version has my-4 text-3xl leading-snug (font-size: 30px line-height:41.25px).
Hmm. I wonder if this issue is limited to 3xl size and whether other Devanagari text in the app also have the very small gap btw lines issue.

Did the analysis:
text-3xl has font size of 1.875rem (16 * 1.875 = 30px) and line-height of 2.25rem (16 * 2.25 = 36px). So a 6px diff. btw font-size and line-height which makes the gap between lines too small for Devanagari text (in Nirmala UI font).
.text-lg {
    font-size: 1.125rem;
    line-height: 1.75rem;
}
which makes it font-size: 16 * 1.125 = 18px and line-height: 16*1.75 =28px. So a 10px diff. btw font-size and line-height which seems fine for Devanagari text (in Nirmala UI font).

Quite surprising to see that text-3xl has lesser line-height difference than text-lg.

.text-2xl {
    font-size: 1.5rem;
    line-height: 2rem;
}
which makes it font-size: 16 * 1.5 = 24px and line-height: 16*2 =32px. So an 8px diff. btw font-size and line-height which seems fine for Devanagari text (in Nirmala UI font).

For elements without text class (e.g. p elements without text class used in Verse page for translations and commentaries), line-height default of Tw of 1.5rem (24px) (inherited from html element) seems to come into play. The font size is 1rem (16px). So there is difference of 8px btw font-size and line-height. This gap still seems OK.

I think text-3xl and any other text classes used in app that have difference btw line-height and font-size less than 8px , should have an additional leading class applied to it so that that difference is 8px or more. For text-3xl with font-size of 30px leading-10 can be specified to make line-height 40px (if that is too much then 'leading-[38px]' can be used perhaps by defining a custom class). ..... Added leading-10 for all text-3xl elements showing Devanagari text.
----

Inter font seems to be bigger than Times New Roman and so Navbar buttons are bigger. Have to adjust that. .... Done.

Commit point "fixed apostrophe vercel build error",  https://github.com/ravisiyer/gita/commit/f0d771e6b7ecb81ec46ecf7d95fa9cd9665b6ff4 has the app version with above changes. The same version is deployed on Vercel (production).
======================

From : Above the Fold vs. Below the Fold: Does it Still Matter in 2023?, https://www.abtasty.com/blog/above-the-fold/ :
"We could also consider a website’s “above the fold” as above the scroll." (Simplistic view but perhaps enough for me, as of now).

Done/fixed by using priority={true}: Check out this browser error: warn-once.js:16 Image with src "/hero-desktop.jpg" was detected as the Largest Contentful Paint (LCP). Please add the "priority" property if this image is above the fold.

app/chaptersummaries and app/[chapternumber] are working when used together! 

Next.js overlaps static route with dynamic route, https://stackoverflow.com/questions/70120480/next-js-overlaps-static-route-with-dynamic-route has a comment, "predefined routes take precedence over dynamic routes, and dynamic routes over catch all routes" and provides a link to Nextjs documentation but that link does not seem to mention this. I tried some more searches to get an authoritative reference page in Nextjs that confirms the above but could not get a suitable page.

I think the right thing may be to prevent such confusion possibilities by introducing a chapter folder within which we have the dynamic chapter routes (like verse folder). ... Done.

Issue understood, know solution but retained behaviour as it may be standard expected behaviour: Double-clicking the text in grey Navbar links results in them becoming white!
Seems to be due to browser selecting the text (in p element). The fix is to use: user-select: none. Ref: How TO - Disable Text Selection, https://www.w3schools.com/howto/howto_css_disable_text_selection.asp .
The following works:
<p style="pointer-events: none; user-select: none">Up</p>
----
But I don't know whether I should disable this standard browser behaviour. What if a user wants to copy-paste the text of the Navbar link? Note that even if the text gets selected (becomes white in our case), it is still not enabled as a link. I think I will skip doing anything about this now until I am sure that disabling text selection in such cases is OK.
----------

Browser gives this error: "[Violation] Forced reflow while executing JavaScript took <N>ms" for chapter, verse and chaptersummaries pages.

My very simple but functional, Bhagavad Gita Next.js web app with minimal code and coding complexity, shared as open-source free-software; Notes, https://raviswdev.blogspot.com/2024/05/notes-on-my-very-simple-bhagavad-gita.html mentions this problem in the context of usePathname in SCV (Select Chapter Verse in Navbar).

Even on commenting out Navbar in layout.tsx (so entire Navbar is not present in app), the forced reflow message is shown on going to chaptersummaries, chapter and verse pages. Home page, About page do not show this error. So Navbar and its SCV component are not the cause.


TIL: class change forces “Style Recalculation” while style change doesn’t. This could be a major performance optimization in some cases., https://medium.com/@nikolozz/til-class-change-forces-reflow-layout-while-style-change-doesnt-435b0a07dd6e

WHAT IS A FORCED REFLOW AND HOW TO SOLVE IT?, https://yonatankra.com/layout-reflow/

Goodbye JS Profiler, profiling CPU with the Performance panel, https://developer.chrome.com/blog/profiling-cpu


==================
Capturing some info. from my trials yesterday (17 Jul), based on my recollection and so may have some inaccuracies:
Nextjs tutorial app. does NOT have the forced reflow warning issue.
my-gita app. does have forced reflow warning issue.
bg-io app. has it for some pages.
-----------
Very Simple Gita app has forced reflow warning for chapter summaries, chapter and verse pages.
Its About page does not have this issue.

Wrote a test page variation of chaptersummaries called testreflow/page and through trial-and-error simplified the code which reports the reflow warning, to the following:
async function Page() {
  let arr = new Array(100).fill(0);

  return (
    <div>
      {arr.map((dummy, index) => (
        <div key={index}>
          <p>div key:{index}</p>
          <p>
            blah blah blah blah blah blah blah blah blah blah blah blah blah
            blah blah blah blah blah blah blah blah blah blah blah blah blah
            blah blah blah blah blah blah blah blah blah blah blah blah blah
            blah blah blah blah blah blah blah blah blah blah blah blah blah
            blah blah blah blah blah blah blah blah blah blah blah blah blah
            blah blah blah blah blah
          </p>
        </div>
      ))}
    </div>
  );
}
export default Page;
----
The reflow warnings reported:
[Violation] Forced reflow while executing JavaScript took 33ms
[Violation] Forced reflow while executing JavaScript took 33ms
[Violation] Forced reflow while executing JavaScript took 32ms
----

When the array size in above code is reduced to 50, the warning rarely appears or does not appear.
  let arr = new Array(50).fill(0); // Reports warning rarely, or does not report warning
---

The above trials show that on large size of HTML output on the page we get the reflow warning but on smaller size of output using the same code does not create the reflow warning.

The code also seems very straightforward with no Tailwind classes applied at the page level though some Tw classes may be getting inherited from layout.tsx. But the same Tailwind classes of layout.tsx are used in Home page which does not report this error. Home page (app/page.tsx) has limited HTML code but has React JS map in ChapterTiles component (app/chaptertiles.tsx). About page is very straightforward and so I am not mentioning it in this discussion.

I think that, as of now, I should not invest further time into this reflow warning issue. Later if I find that performance is a significant issue then I can invest further time on this issue.

=============================

gita-frontend-v2 has nice feature of showing a coloured thin bar in top of window while page is loading. Consider if that can be done easily for my app. nextjs tut app does not seem to have such feedback. ... Partially done.

It seems to use Next Js TopLoader, https://www.npmjs.com/package/nextjs-toploader for this feature.
Tried it. It works for Link links but not for useRouter push/replace. Others have faced the issue: Compatibility with useRouter, https://github.com/TheSGJ/nextjs-toploader/issues/10 . The workaround mentioned seems to be rather involved. 

gita-frontend-v2 app does not face an issue for useRouter push. The source code on GitHub (which I could not successfully build) does not seem to use the workaround.

I think I should not invest more time on this. I am using Next Js TopLoader. SCV uses useRouter replace/push - that alone will not show progress bar.
===========

Sanskrit and Hindi translations and commentary text in Verse page is showed with normal font size. On desktop, the normal size is fine but on mobile it seems quite small. However, browser zoom can be used to increase that font size. I am not sure that using slightly larger font for Verse translations and commentary is appropriate.

========

About the question mark (?) character being shown instead of comma in some commentaries ....


GraphQL comes with a set of default scalar types out of the box:
..
String: A UTF‐8 character sequence.
--------
So GraphQL String type uses UTF-8. 

UTF-8 requires 8, 16, 24 or 32 bits (one to four bytes) to encode a Unicode character, UTF-16 requires either 16 or 32 bits to encode a character, and UTF-32 always requires 32 bits to encode a character. The first 128 Unicode code points, U+0000 to U+007F, used for the C0 Controls and Basic Latin characters and which correspond one-to-one to their ASCII-code equivalents, are encoded using 8 bits in UTF-8, 16 bits in UTF-16, and 32 bits in UTF-32.
...
A UTF-8 file that contains only ASCII characters is identical to an ASCII file. Legacy programs can generally handle UTF-8 encoded files, even if they contain non-ASCII characters. For instance, the C printf function can print a UTF-8 string, as it only looks for the ASCII '%' character to define a formatting string, and prints all other bytes unchanged, thus non-ASCII characters will be output unchanged.

UTF-16 and UTF-32 are incompatible with ASCII files, and thus require Unicode-aware programs to display, print and manipulate them, even if the file is known to contain only characters in the ASCII subset. Because they contain many zero bytes, the strings cannot be manipulated by normal null-terminated string handling for even simple operations such as copy.[a]

--- end extracts ---

---
As both my app and GraphQL explorer show most, if not all, Devanagari characters correctly with underlying fields being String and so UTF-8 type, I don't think the ? issue is a program encoding/decoding issue. I think the underlying database field would be having the ? character. I cannot confirm it as I do not have access to the underlying database.

=======================

Added following code to verse page:
            {/* Hack to partially fix ? characters instead of , characters in Swami Sivananda
            commentaries. Disadvantage is that even ? chars that should be ? will be 
            changed to , chars. But such cases seem to be very few. */}
            {commentary!
              .authorName!.toLowerCase()
              .includes("swami sivananda") ? (
              <p className="my-4 ">
                {commentary!.description!.replace(/\?/g, ",")}
              </p>
            ) : (
              <p className="my-4 ">{commentary!.description}</p>
            )}
----
The code seems to work. Interestingly for Chapter 4, Verse 4, Swami Sivananda commentary does not have a ? where one would expect it, on Gita SS. If it had then my above hack would converted that appropriate ? to ,. Looks like my hack may work for most cases (of Swami Sivananda commentary).
This page in my app has Swami Ramsukhdas commentary (in Hindi) which has an appropriate ?. That is not changed (as expected).

-------

Chapter 13, verse 34 shows that many commentaries in Hindi and Sanskrit have the same ? problem.


Other commentaries with this issue in above Gita SS page are:
Hindi Commentary By Swami Chinmayananda
Some Sanskrit commentaries seem to have this issue but as I don't know Sanskrit I am not able to know for sure whether the ? character is appropriate in the Sanskrit sentence's context.

But its English Commentary By Swami Sivananda does not have this issue.

Hmm. 
DevTools shows that Gita SS page for "Hindi Commentary By Swami Chinmayananda" paragraph (with ?mark issue) is rendered on my desktop PC by Nirmala UI and Open Sans font (families).
"English Commentary By Swami Sivananda" (without ?mark issue) is rendered by Open Sans and Nirmala UI font (families) (Order is different).

I checked it out on my Samsung M21 phone (Android) and the site's page showed the same issue for "Hindi Commentary By Swami Chinmayananda" paragraph (see GitaSS-c13v34-p2-Chinmaya-WithIssue.jpg) and no issue for "English Commentary By Swami Sivananda" (see GitaSS-c13v34-p1-SivanandaWithoutIssue.jpg). [These pics are on my PC. Was not sure if I should put it up on this post.]

----

I think temporarily I should convert ? to , in all commentaries. ... Done. 
=====================

gita-frontend-v2 app shows chapter and verse number in history as part of title. See if same can be done in my app. ... Done.

Covers static title for pages: Adding Metadata, https://nextjs.org/learn/dashboard-app/adding-metadata
Covers static and dynamic title for pages: Metadata, https://nextjs.org/docs/app/building-your-application/optimizing/metadata#seo .

I plan to 'release' this code as version 1.0 of (Simple) Gita app. Made suitable changes to Readme and About pages.

Commit point: "Added note about ? changed to , in commentaries in Verse page; other …", https://github.com/ravisiyer/gita/commit/317a5f7878b15e56599ea2e307752f17ef9238f1 , has the code at this stage.

Comments