Notes on regular UI Bhagavad Gita Nextjs web app. built on top of very simple Gita app.

Last updated on 6 Jul. 2024
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/.

Comments