Update the `initialize_token_mint` instruction to also create a token metadata account.

Here's a reference `initialize` instruction that:

- initialize a mint
- creates a metadata account for the mint
- mints the token

You can remove the `mint_to` cpi from the `initialize` instruction for your use case. 

    use anchor_lang::{prelude::*, solana_program::program::invoke_signed};
        use anchor_spl::{
            associated_token::AssociatedToken,
            token::{mint_to, Mint, MintTo, Token, TokenAccount},
        };
        use borsh::BorshDeserialize;
        use mpl_token_metadata::{
            instruction::create_metadata_accounts_v3, pda::find_metadata_account, ID as MetadataID,
        };
        
        declare_id!("8LgkDyXcYXtX6h78eNRydLr2tkWHxduREnpb5TZdgE8b");
        
        #[program]
        pub mod token_with_metadata {
            use super::*;
        
            pub fn initialize(
                ctx: Context<InitializeMint>,
                uri: String,
                name: String,
                symbol: String,
            ) -> Result<()> {
                let seeds = &["mint".as_bytes(), &[*ctx.bumps.get("mint").unwrap()]];
                let signer = [&seeds[..]];
        
                let account_info = vec![
                    ctx.accounts.metadata.to_account_info(),
                    ctx.accounts.mint.to_account_info(),
                    ctx.accounts.user.to_account_info(),
                    ctx.accounts.token_metadata_program.to_account_info(),
                    ctx.accounts.token_program.to_account_info(),
                    ctx.accounts.system_program.to_account_info(),
                    ctx.accounts.rent.to_account_info(),
                ];
        
                invoke_signed(
                    &create_metadata_accounts_v3(
                        ctx.accounts.token_metadata_program.key(), // token metadata program
                        ctx.accounts.metadata.key(),               // metadata account PDA for mint
                        ctx.accounts.mint.key(),                   // mint account
                        ctx.accounts.mint.key(),                   // mint authority
                        ctx.accounts.user.key(),                   // payer for transaction
                        ctx.accounts.mint.key(),                   // update authority
                        name,                                      // name
                        symbol,                                    // symbol
                        uri,                                       // uri (offchain metadata)
                        None,                                      // (optional) creators
                        0,                                         // seller free basis points
                        true,                                      // (bool) update authority is signer
                        true,                                      // (bool) is mutable
                        None,                                      // (optional) collection
                        None,                                      // (optional) uses
                        None,                                      // (optional) collection details
                    ),
                    account_info.as_slice(),
                    &signer,
                )?;
        
                mint_to(
                    CpiContext::new_with_signer(
                        ctx.accounts.token_program.to_account_info(),
                        MintTo {
                            authority: ctx.accounts.mint.to_account_info(),
                            to: ctx.accounts.token_account.to_account_info(),
                            mint: ctx.accounts.mint.to_account_info(),
                        },
                        &signer,
                    ),
                    1,
                )?;
        
                Ok(())
            }
        }
        
        #[derive(Accounts)]
        pub struct InitializeMint<'info> {
            #[account(
                init,
                seeds = [b"mint"],
                bump,
                payer = user,
                mint::decimals = 6,
                mint::authority = mint,
            )]
            pub mint: Account<'info, Mint>,
            /// CHECK: Using "address" constraint to validate metadata account address
            #[account(
                mut,
                address=find_metadata_account(&mint.key()).0
            )]
            pub metadata: UncheckedAccount<'info>,
            #[account(
                init_if_needed,
                payer = user,
                associated_token::mint = mint,
                associated_token::authority = user
            )]
            pub token_account: Account<'info, TokenAccount>,
            #[account(mut)]
            pub user: Signer<'info>,
            pub token_program: Program<'info, Token>,
            pub token_metadata_program: Program<'info, TokenMetaData>,
            pub associated_token_program: Program<'info, AssociatedToken>,
            pub rent: Sysvar<'info, Rent>,
            pub system_program: Program<'info, System>,
        }
        
        #[derive(Clone)]
        pub struct TokenMetaData;
        impl anchor_lang::Id for TokenMetaData {
            fn id() -> Pubkey {
                MetadataID
            }
        }

Here's how the test looks 

    import * as anchor from "@project-serum/anchor"
    import { Program } from "@project-serum/anchor"
    import { TokenWithMetadata } from "../target/types/token_with_metadata"
    import { findMetadataPda } from "@metaplex-foundation/js"
    import { getAccount, getAssociatedTokenAddressSync } from "@solana/spl-token"
    
    describe("token-with-metadata", () => {
      const provider = anchor.AnchorProvider.env()
      anchor.setProvider(provider)
    
      const program = anchor.workspace
        .TokenWithMetadata as Program<TokenWithMetadata>
    
      const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey(
        "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
      )
    
      const nft = {
        uri: "https://arweave.net/OwXDf7SM6nCVY2cvQ4svNjtV7WBTz3plbI4obN9JNkk",
        name: "NAME",
        symbol: "SYMBOL",
      }
    
      const [mintPDA] = anchor.web3.PublicKey.findProgramAddressSync(
        [Buffer.from("mint")],
        program.programId
      )
    
      const tokenAccount = getAssociatedTokenAddressSync(
        mintPDA,
        provider.wallet.publicKey
      )
    
      it("Is initialized!", async () => {
        // Add your test here.
        const metadataPDA = await findMetadataPda(mintPDA)
    
        const tx = await program.methods
          .initialize(nft.uri, nft.name, nft.symbol)
          .accounts({
            mint: mintPDA,
            metadata: metadataPDA,
            tokenAccount: tokenAccount,
            user: provider.wallet.publicKey,
            tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
          })
          .rpc()
        console.log("Your transaction signature", tx)
    
        const account = await getAccount(provider.connection, tokenAccount)
        console.log(account.amount)
      })
    })

Also update `Cargo.toml`, you can remove `init-if-needed` if you're not using it

    [dependencies]
    anchor-lang = { version = "0.25.0", features = ["init-if-needed"] }
    anchor-spl = "0.25.0"
    mpl-token-metadata = {version = "1.5.0", features = ["no-entrypoint"]}



Check out the metaplex sdk to see how to create the uri for the off-chain metadata for your token

https://github.com/metaplex-foundation/js#readme

You'll need to:
- upload an image to a storage service to get the image uri (ex. arweave)
- then upload again with the other metadata you want for the token (name, symbol etc) and the include the image uri from the previous step

Here's an example of the BONK token metadata

image uri: https://arweave.net/hQiPZOsRZXGXBJd_82PhVdlM_hACsT_q6wqwf5cSY7I

token metadata uri (which points to the image uri): https://arweave.net/QPC6FYdUn-3V8ytFNuoCS85S2tHAuiDblh6u3CIZLsw


Recommend looking through the metaplex docs, great diagrams for understanding relationship between accounts

https://docs.metaplex.com/programs/understanding-programs
https://docs.metaplex.com/programs/token-metadata/overview